diff -Nru binaryen-108/auto_update_tests.py binaryen-99/auto_update_tests.py --- binaryen-108/auto_update_tests.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/auto_update_tests.py 2021-01-07 20:01:06.000000000 +0000 @@ -87,10 +87,6 @@ print('..', os.path.basename(t)) ctors = open(t + '.ctors').read().strip() cmd = shared.WASM_CTOR_EVAL + [t, '-all', '-o', 'a.wast', '-S', '--ctors', ctors] - if 'ignore-external-input' in t: - cmd += ['--ignore-external-input'] - if 'results' in t: - cmd += ['--kept-exports', 'test1,test3'] support.run_command(cmd) actual = open('a.wast').read() out = t + '.out' @@ -118,8 +114,8 @@ for t in shared.get_tests(shared.get_test_dir('reduce'), ['.wast']): print('..', os.path.basename(t)) # convert to wasm - support.run_command(shared.WASM_AS + [t, '-o', 'a.wasm', '-all']) - print(support.run_command(shared.WASM_REDUCE + ['a.wasm', '--command=%s b.wasm --fuzz-exec -all' % shared.WASM_OPT[0], '-t', 'b.wasm', '-w', 'c.wasm'])) + support.run_command(shared.WASM_AS + [t, '-o', 'a.wasm']) + print(support.run_command(shared.WASM_REDUCE + ['a.wasm', '--command=%s b.wasm --fuzz-exec' % shared.WASM_OPT[0], '-t', 'b.wasm', '-w', 'c.wasm'])) expected = t + '.txt' support.run_command(shared.WASM_DIS + ['c.wasm', '-o', expected]) @@ -142,27 +138,6 @@ o.write(stdout) -def update_lit_tests(): - print('\n[ updating lit testcases... ]\n') - script = os.path.join(shared.options.binaryen_root, - 'scripts', - 'update_lit_checks.py') - lit_dir = shared.get_test_dir('lit') - subprocess.check_output([sys.executable, - script, - '--binaryen-bin=' + shared.options.binaryen_bin, - os.path.join(lit_dir, '**', '*.wast'), - os.path.join(lit_dir, '**', '*.wat')]) - - # Update the help lit tests - script = os.path.join(shared.options.binaryen_root, - 'scripts', - 'update_help_checks.py') - subprocess.check_output([sys.executable, - script, - '--binaryen-bin=' + shared.options.binaryen_bin]) - - TEST_SUITES = OrderedDict([ ('wasm-opt', wasm_opt.update_wasm_opt_tests), ('wasm-dis', update_wasm_dis_tests), @@ -174,7 +149,6 @@ ('lld', lld.update_lld_tests), ('wasm2js', wasm2js.update_wasm2js_tests), ('binaryenjs', binaryenjs.update_binaryen_js_tests), - ('lit', update_lit_tests), ]) diff -Nru binaryen-108/CHANGELOG.md binaryen-99/CHANGELOG.md --- binaryen-108/CHANGELOG.md 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/CHANGELOG.md 2021-01-07 20:01:06.000000000 +0000 @@ -15,152 +15,6 @@ Current Trunk ------------- -v108 ----- - -- Add CMake flag BUILD_TOOLS to control building tools (#4655) -- Add CMake flag JS_OF_OCAML for js_of_ocaml (#4637) -- Remove externref (#4633) - -v107 ----- - -- Update the wasm GC type section binary format (#4625, #4631) -- Lift the restriction in liveness-traversal.h on max 65535 locals (#4567) -- Switch to nominal fuzzing by default (#4610) -- Refactor Feature::All to match FeatureSet.setAll() (#4557) -- New Signature Pruning pass (#4545) -- Add support for extended-const proposal (#4529) -- Add BUILD_TESTS CMake option to make gtest dependency optional. -- Updated tests to use filecheck 0.0.22 (#4537). Updating is required to - successfully run the lit tests. This can be done with - `pip3 install -r requirements-dev.txt`. - -v106 ----- - -- [wasm2js] Support exports of Globals (#4523) -- MergeSimilarFunctions optimization pass (#4414) -- Various wasm-ctor-eval improvements, including support for GC. - -v105 ----- - -- This release contains binaries for ARM64 MacOS devices (#4397) -- Otherwise, mostly bug fixes and incremental optimization improvements. - -v104 ----- - -- Bugfixes only, release created due to incorrect github release artifacts in - v103 release (#4398). - -v103 ----- - -- The EffectAnalyzer now takes advantage of immutability of globals. To achieve - that it must have access to the module. That is already the case in the C++ - API, but the JS API allowed one to optionally not add a module when calling - `getSideEffects()`. It is now mandatory to pass in the module. -- JS and Wasm builds now emit ECMAScript modules. New usage is: - ```js - import Binaryen from "path/to/binaryen.js"; - const binaryen = await Binaryen(); - ... - ``` -- CallIndirect changed from storing a Signature to storing a HeapType - -v102 ----- - -- Add `BinaryenUpdateMaps` to the C API. - -- Adds a TrapsNeverHappen mode (#4059). This has many of the benefits of - IgnoreImplicitTraps, but can be used safely in more cases. IgnoreImplicitTraps - is now deprecated. - -- Adds type argument for BinaryenAddTable method (#4107). For the binaryen.js api - this parameter is optional and by default is set to funcref type. - -- Replace `BinaryenExpressionGetSideEffects`'s features parameter with a module - parameter. - -- OptimizeInstructions now lifts identical code in `select`/`if` arms (#3828). This may cause direct `BinaryenTupleExtract(BinaryenTupleMake(...))` to [use multivalue types](https://github.com/grain-lang/grain/pull/1158). - -v101 ----- - -- `BinaryenSetFunctionTable` and `module.setFunctionTable` have been removed - in favor of `BinaryenAddTable` and `module.addTable` respectively. -- `BinaryenIsFunctionTableImported` is removed. -- A new type `BinaryenElementSegmentRef` has been added to the C API with - new apis in both C & JS: - - `BinaryenAddActiveElementSegment` - - `BinaryenAddPassiveElementSegment` - - `BinaryenRemoveElementSegment` - - `BinaryenGetElementSegment` - - `BinaryenGetElementSegmentByIndex` - - `BinaryenElementSegmentGetName` - - `BinaryenElementSegmentSetName` - - `BinaryenElementSegmentGetTable` - - `BinaryenElementSegmentSetTable` - - `BinayenElementSegmentIsPassive` - - `module.addActiveElementSegment` - - `module.addPassiveElementSegment` - - `module.removeElementSegment` - - `module.getElementSegment` - - `module.getElementSegmentByIndex` - - `module.getTableSegments` - - `module.getNumElementSegments` - - `binaryen.getElementSegmentInfo` -- `BinaryenAddTable` and `module.addTable` no longer take offset and function - names. -- `BinaryenGetNumFunctionTableSegments` is replaced with - `BinaryenGetNumElementSegments`. -- `BinaryenGetFunctionTableSegmentOffset` is replaced with - `BinaryenElementSegmentGetOffset`. -- `BinaryenGetFunctionTableSegmentLength` is replaced with - `BinaryenElementSegmentGetLength`. -- `BinaryenGetFunctionTableSegmentData` is replaced with - `BinaryenElementSegmentGetData`. -- Boolean values in the C API now should use `bool` instead of `int`. -- Experimental SIMD instructions have been removed and the names and opcodes of - the standard instructions have been updated to match the final spec. - -v100 ----- - -- `wasm-dis` now supports options to enable or disable Wasm features. -- Reference types support has been improved by allowing multiple tables in a - module. -- `call_indirect` and `return_call_indirect` now take an additional table name - parameter. This is necessary for reference types support. -- New getter/setter methods have been introduced for `call_indirect` table name: - - `BinaryenCallIndirectGetTable` - - `BinaryenCallIndirectSetTable` - - JS API `CallIndirect.table` -- New APIs have been added to add and manipulate multiple tables in a module: - - `BinaryenAddTable` - - `BinaryenRemoveTable` - - `BinaryenGetNumTables` - - `BinaryenGetTable` - - `BinaryenGetTableByIndex` - - `BinaryenTableGetName` - - `BinaryenTableGetInitial` - - `BinaryenTableHasMax` - - `BinaryenTableGetMax` - - `BinaryenTableImportGetModule` - - `BinaryenTableImportGetBase` - - `module.addTable` - - `module.removeTable` - - `module.getTable` - - `module.getTableByIndex` - - `module.getNumTables` - - `binaryen.getTableInfo` - -v99 ---- - - `RefFunc` C and JS API constructors (`BinaryenRefFunc` and `ref.func` respectively) now take an extra `type` parameter, similar to `RefNull`. This is necessary for typed function references support. diff -Nru binaryen-108/check.py binaryen-99/check.py --- binaryen-108/check.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/check.py 2021-01-07 20:01:06.000000000 +0000 @@ -39,18 +39,27 @@ return int(version) -def run_version_tests(): - print('[ checking --version ... ]\n') +def run_help_tests(): + print('[ checking --help is useful... ]\n') - not_executable_suffix = ['.DS_Store', '.txt', '.js', '.ilk', '.pdb', '.dll', '.wasm', '.manifest'] - not_executable_prefix = ['binaryen-lit', 'binaryen-unittests'] + not_executable_suffix = ['.txt', '.js', '.ilk', '.pdb', '.dll', '.wasm', '.manifest', 'binaryen-lit'] bin_files = [os.path.join(shared.options.binaryen_bin, f) for f in os.listdir(shared.options.binaryen_bin)] - executables = [f for f in bin_files if os.path.isfile(f) and - not any(f.endswith(s) for s in not_executable_suffix) and - not any(os.path.basename(f).startswith(s) for s in not_executable_prefix)] + executables = [f for f in bin_files if os.path.isfile(f) and not any(f.endswith(s) for s in not_executable_suffix)] executables = sorted(executables) assert len(executables) + for e in executables: + print('.. %s --help' % e) + out, err = subprocess.Popen([e, '--help'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE).communicate() + out = out.decode('utf-8') + err = err.decode('utf-8') + assert len(err) == 0, 'Expected no stderr, got:\n%s' % err + assert os.path.basename(e).replace('.exe', '') in out, 'Expected help to contain program name, got:\n%s' % out + assert len(out.split('\n')) > 8, 'Expected some help, got:\n%s' % out + + print('[ checking --version ... ]\n') changelog_version = get_changelog_version() for e in executables: print('.. %s --version' % e) @@ -119,10 +128,6 @@ print('..', os.path.basename(t)) ctors = open(t + '.ctors').read().strip() cmd = shared.WASM_CTOR_EVAL + [t, '-all', '-o', 'a.wat', '-S', '--ctors', ctors] - if 'ignore-external-input' in t: - cmd += ['--ignore-external-input'] - if 'results' in t: - cmd += ['--kept-exports', 'test1,test3'] support.run_command(cmd) actual = open('a.wat').read() out = t + '.out' @@ -154,8 +159,8 @@ for t in shared.get_tests(shared.get_test_dir('reduce'), ['.wast']): print('..', os.path.basename(t)) # convert to wasm - support.run_command(shared.WASM_AS + [t, '-o', 'a.wasm', '-all']) - support.run_command(shared.WASM_REDUCE + ['a.wasm', '--command=%s b.wasm --fuzz-exec -all ' % shared.WASM_OPT[0], '-t', 'b.wasm', '-w', 'c.wasm', '--timeout=4']) + support.run_command(shared.WASM_AS + [t, '-o', 'a.wasm']) + support.run_command(shared.WASM_REDUCE + ['a.wasm', '--command=%s b.wasm --fuzz-exec --detect-features ' % shared.WASM_OPT[0], '-t', 'b.wasm', '-w', 'c.wasm', '--timeout=4']) expected = t + '.txt' support.run_command(shared.WASM_DIS + ['c.wasm', '-o', 'a.wat']) with open('a.wat') as seen: @@ -225,8 +230,6 @@ if 'exports.wast' in base: # FIXME continue - run_spec_test(wast) - # check binary format. here we can verify execution of the final # result, no need for an output verification # some wast files cannot be split: @@ -238,21 +241,21 @@ if base not in ['comments.wast', 'ref_null.wast', 'ref_is_null.wast', 'ref_func.wast', 'old_select.wast']: split_num = 0 actual = '' - with open('spec.wast', 'w') as transformed_spec_file: - for module, asserts in support.split_wast(wast): - print(' testing split module', split_num) - split_num += 1 - support.write_wast('split.wast', module, asserts) - run_opt_test('split.wast') # also that our optimizer doesn't break on it - result_wast_file = shared.binary_format_check('split.wast', verify_final_result=False, original_wast=wast) - with open(result_wast_file) as f: - result_wast = f.read() - # add the asserts, and verify that the test still passes - transformed_spec_file.write(result_wast + '\n' + '\n'.join(asserts)) - + for module, asserts in support.split_wast(wast): + print(' testing split module', split_num) + split_num += 1 + support.write_wast('split.wast', module, asserts) + run_spec_test('split.wast') # before binary stuff - just check it's still ok split out + run_opt_test('split.wast') # also that our optimizer doesn't break on it + result_wast = shared.binary_format_check('split.wast', verify_final_result=False, original_wast=wast) + # add the asserts, and verify that the test still passes + open(result_wast, 'a').write('\n' + '\n'.join(asserts)) + actual += run_spec_test(result_wast) # compare all the outputs to the expected output - actual = run_spec_test('spec.wast') check_expected(actual, os.path.join(shared.get_test_dir('spec'), 'expected-output', base + '.log')) + else: + # handle unsplittable wast files + run_spec_test(wast) def run_validator_tests(): @@ -272,16 +275,16 @@ support.run_command(cmd, expected_status=1) -def run_example_tests(): - print('\n[ checking native example testcases...]\n') +def run_gcc_tests(): + print('\n[ checking native gcc testcases...]\n') if not shared.NATIVECC or not shared.NATIVEXX: shared.fail_with_error('Native compiler (e.g. gcc/g++) was not found in PATH!') return # windows + gcc will need some work - if shared.skip_if_on_windows('example'): + if shared.skip_if_on_windows('gcc'): return - for t in shared.get_tests(shared.get_test_dir('example')): + for t in sorted(os.listdir(shared.get_test_dir('example'))): output_file = 'example' cmd = ['-I' + os.path.join(shared.options.binaryen_root, 't'), '-g', '-pthread', '-o', output_file] if not t.endswith(('.c', '.cpp')): @@ -326,37 +329,19 @@ def run_lit(): - def run(): - lit_script = os.path.join(shared.options.binaryen_bin, 'binaryen-lit') - lit_tests = os.path.join(shared.options.binaryen_root, 'test', 'lit') - # lit expects to be run as its own executable - cmd = [sys.executable, lit_script, lit_tests, '-vv'] - result = subprocess.run(cmd) - if result.returncode != 0: - shared.num_failures += 1 - if shared.options.abort_on_first_failure and shared.num_failures: - raise Exception("lit test failed") - - shared.with_pass_debug(run) - - -def run_gtest(): - def run(): - gtest = os.path.join(shared.options.binaryen_bin, 'binaryen-unittests') - if not os.path.isfile(gtest): - shared.warn('gtest binary not found - skipping tests') - else: - result = subprocess.run(gtest) - if result.returncode != 0: - shared.num_failures += 1 - if shared.options.abort_on_first_failure and shared.num_failures: - raise Exception("gtest test failed") - - shared.with_pass_debug(run) + lit_script = os.path.join(shared.options.binaryen_bin, 'binaryen-lit') + lit_tests = os.path.join(shared.options.binaryen_root, 'test', 'lit') + # lit expects to be run as its own executable + cmd = [sys.executable, lit_script, lit_tests, '-vv'] + result = subprocess.run(cmd) + if result.returncode != 0: + shared.num_failures += 1 + if shared.options.abort_on_first_failure and shared.num_failures: + raise Exception("lit test failed") TEST_SUITES = OrderedDict([ - ('version', run_version_tests), + ('help-messages', run_help_tests), ('wasm-opt', wasm_opt.test_wasm_opt), ('wasm-dis', run_wasm_dis_tests), ('crash', run_crash_tests), @@ -368,12 +353,11 @@ ('lld', lld.test_wasm_emscripten_finalize), ('wasm2js', wasm2js.test_wasm2js), ('validator', run_validator_tests), - ('example', run_example_tests), + ('gcc', run_gcc_tests), ('unit', run_unittest), ('binaryenjs', binaryenjs.test_binaryen_js), ('binaryenjs_wasm', binaryenjs.test_binaryen_wasm), ('lit', run_lit), - ('gtest', run_gtest), ]) diff -Nru binaryen-108/CMakeLists.txt binaryen-99/CMakeLists.txt --- binaryen-108/CMakeLists.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/CMakeLists.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,26 +1,10 @@ -# Version set according the the cmake versions available in Ubuntu/Bionic: -# https://packages.ubuntu.com/bionic/cmake -cmake_minimum_required(VERSION 3.10.2) - -# Needed for C++17 (std::variant) -# TODO(https://github.com/WebAssembly/binaryen/issues/4299): We need -# to reduce this for compatability with emsdk. -set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14" CACHE STRING "Minimum OS X deployment version") - -project(binaryen LANGUAGES C CXX VERSION 108) +cmake_minimum_required(VERSION 3.1.3) +project(binaryen LANGUAGES C CXX VERSION 98) include(GNUInstallDirs) # The C++ standard whose features are required to build Binaryen. # Keep in sync with scripts/test/shared.py cxx_standard -# The if condition allows embedding in a project with a higher default C++ standard set -set(REQUIRED_CXX_STANDARD 17) -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD ${REQUIRED_CXX_STANDARD}) -elseif(CMAKE_CXX_STANDARD LESS ${REQUIRED_CXX_STANDARD}) - message(SEND_ERROR "Building with C++ standards older than C++${REQUIRED_CXX_STANDARD} is not supported, change CMAKE_CXX_STANDARD to ${REQUIRED_CXX_STANDARD} or later") -endif() -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +set(CXX_STANDARD 14) if(NOT CMAKE_BUILD_TYPE) message(STATUS "No build type selected, default to Release") @@ -31,15 +15,6 @@ # more useful error reports from users. option(BYN_ENABLE_ASSERTIONS "Enable assertions" ON) -# Turn this off to avoid the dependency on gtest. -option(BUILD_TESTS "Build GTest-based tests" ON) - -# Turn this off to build only the library. -option(BUILD_TOOLS "Build tools" ON) - -# Turn this on to build binaryen.js as ES5, with additional compatibility configuration for js_of_ocaml. -option(JS_OF_OCAML "Build binaryen.js for js_of_ocaml" OFF) - # For git users, attempt to generate a more useful version string if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) find_package(Git QUIET REQUIRED) @@ -61,41 +36,41 @@ # Support functionality. -function(add_compile_flag value) +function(ADD_COMPILE_FLAG value) message(STATUS "Building with ${value}") - foreach(variable CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + FOREACH(variable CMAKE_C_FLAGS CMAKE_CXX_FLAGS) set(${variable} "${${variable}} ${value}" PARENT_SCOPE) - endforeach(variable) + ENDFOREACH(variable) endfunction() -function(add_cxx_flag value) +function(ADD_CXX_FLAG value) message(STATUS "Building with ${value}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}" PARENT_SCOPE) endfunction() -function(add_debug_compile_flag value) +function(ADD_DEBUG_COMPILE_FLAG value) if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") message(STATUS "Building with ${value}") endif() - foreach(variable CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG) + FOREACH(variable CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG) set(${variable} "${${variable}} ${value}" PARENT_SCOPE) - endforeach(variable) + ENDFOREACH(variable) endfunction() -function(add_nondebug_compile_flag value) +function(ADD_NONDEBUG_COMPILE_FLAG value) if(NOT "${CMAKE_BUILD_TYPE}" MATCHES "Debug") message(STATUS "Building with ${value}") endif() - foreach(variable CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL) + FOREACH(variable CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL) set(${variable} "${${variable}} ${value}" PARENT_SCOPE) - endforeach(variable) + ENDFOREACH(variable) endfunction() -function(add_link_flag value) +function(ADD_LINK_FLAG value) message(STATUS "Linking with ${value}") - foreach(variable CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS) + FOREACH(variable CMAKE_EXE_LINKER_FLAGS) set(${variable} "${${variable}} ${value}" PARENT_SCOPE) - endforeach(variable) + ENDFOREACH(variable) endfunction() function(binaryen_setup_rpath name) @@ -103,7 +78,7 @@ return() endif() - if(APPLE) + if (APPLE) set(_install_name_dir INSTALL_NAME_DIR "@rpath") set(_install_rpath "@loader_path/../lib") elseif(UNIX) @@ -122,24 +97,16 @@ ${_install_name_dir}) endfunction() -function(binaryen_add_executable name sources) - add_executable(${name} ${sources}) - target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT}) - target_link_libraries(${name} binaryen) - binaryen_setup_rpath(${name}) - install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR}) -endfunction() - # Options option(BUILD_STATIC_LIB "Build as a static library" OFF) -if(MSVC) +if (MSVC) # We don't have dllexport declarations set up for windows yet. set(BUILD_STATIC_LIB ON) endif() # For now, don't include full DWARF support in JS builds, for size. -if(NOT EMSCRIPTEN) +if (NOT EMSCRIPTEN) option(BUILD_LLVM_DWARF "Enable full DWARF support" ON) if(BUILD_LLVM_DWARF) @@ -162,37 +129,21 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) # Force output to bin/ and lib/. This is to suppress CMake multigenerator output paths and avoid bin/Debug, bin/Release/ and so on, which is CMake default. -foreach(SUFFIX "_DEBUG" "_RELEASE" "_RELWITHDEBINFO" "_MINSIZEREL" "") +FOREACH(SUFFIX "_DEBUG" "_RELEASE" "_RELWITHDEBINFO" "_MINSIZEREL" "") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY${SUFFIX} "${PROJECT_BINARY_DIR}/bin") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY${SUFFIX} "${PROJECT_BINARY_DIR}/lib") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY${SUFFIX} "${PROJECT_BINARY_DIR}/lib") -endforeach() - -option(BYN_ENABLE_LTO "Build with LTO" Off) -if(BYN_ENABLE_LTO) - if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") - message(FATAL_ERROR "ThinLTO is only supported by clang") - endif() - add_link_flag("-fuse-ld=lld") - set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=2) - set(CMAKE_JOB_POOL_LINK link_job_pool) - add_compile_flag("-flto=thin") -endif() +ENDFOREACH() if(MSVC) - if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # multi-core build. - add_compile_flag("/MP") - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0") - # VS2013 and older explicitly need /arch:sse2 set, VS2015 no longer has that option, but always enabled. - add_compile_flag("/arch:sse2") - endif() + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0") # VS2013 and older explicitly need /arch:sse2 set, VS2015 no longer has that option, but always enabled. + add_compile_flag("/arch:sse2") endif() add_compile_flag("/wd4146") # Ignore warning "warning C4146: unary minus operator applied to unsigned type, result still unsigned", this pattern is used somewhat commonly in the code. # 4267 and 4244 are conversion/truncation warnings. We might want to fix these but they are currently pervasive. add_compile_flag("/wd4267") add_compile_flag("/wd4244") - # 4722 warns that destructors never return, even with [[noreturn]]. + # 4722 warns that destructors never return, even with WASM_NORETURN. add_compile_flag("/wd4722") # "destructor was implicitly defined as deleted" caused by LLVM headers. add_compile_flag("/wd4624") @@ -201,14 +152,15 @@ add_nondebug_compile_flag("/O2") add_compile_flag("/D_CRT_SECURE_NO_WARNINGS") add_compile_flag("/D_SCL_SECURE_NO_WARNINGS") - # workaround for https://github.com/WebAssembly/binaryen/issues/3661 - add_compile_flag("/D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING") # Visual Studio 2018 15.8 implemented conformant support for std::aligned_storage, but the conformant support is only enabled when the following flag is passed, to avoid # breaking backwards compatibility with code that relied on the non-conformant behavior (the old nonconformant behavior is not used with Binaryen) add_compile_flag("/D_ENABLE_EXTENDED_ALIGNED_STORAGE") # Don't warn about using "strdup" as a reserved name. add_compile_flag("/D_CRT_NONSTDC_NO_DEPRECATE") + # multi-core build. + add_compile_flag("/MP") + if(BYN_ENABLE_ASSERTIONS) # On non-Debug builds cmake automatically defines NDEBUG, so we # explicitly undefine it: @@ -245,6 +197,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) set(CMAKE_THREAD_PREFER_PTHREAD ON) find_package(Threads REQUIRED) + add_cxx_flag("-std=c++${CXX_STANDARD}") if(NOT EMSCRIPTEN) if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$") # wasm doesn't allow for x87 floating point math @@ -267,23 +220,21 @@ add_compile_flag("-Wno-implicit-int-float-conversion") add_compile_flag("-Wno-unknown-warning-option") add_compile_flag("-Wswitch") # we explicitly expect this in the code - add_compile_flag("-Wimplicit-fallthrough") - add_compile_flag("-Wnon-virtual-dtor") - if(WIN32) add_compile_flag("-D_GNU_SOURCE") add_compile_flag("-D__STDC_FORMAT_MACROS") - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_link_flag("-Wl,/stack:8388608") - else() - add_link_flag("-Wl,--stack,8388608") - endif() + add_link_flag("-Wl,--stack,8388608") elseif(NOT EMSCRIPTEN) add_compile_flag("-fPIC") endif() add_debug_compile_flag("-O0") add_debug_compile_flag("-g3") - add_nondebug_compile_flag("-O2") + if(EMSCRIPTEN) + # really focus on minimizing output size when compiling sources + add_nondebug_compile_flag("-Oz") + else() + add_nondebug_compile_flag("-O2") + endif() if(BYN_ENABLE_ASSERTIONS) # On non-Debug builds cmake automatically defines NDEBUG, so we # explicitly undefine it: @@ -316,7 +267,7 @@ # Static libraries # Current (partial) dependency structure is as follows: -# tools -> passes -> wasm -> asmjs -> support +# passes -> wasm -> asmjs -> support # TODO: It's odd that wasm should depend on asmjs, maybe we should fix that. add_subdirectory(src/ir) add_subdirectory(src/asmjs) @@ -325,22 +276,11 @@ add_subdirectory(src/passes) add_subdirectory(src/support) add_subdirectory(src/wasm) - -if(BUILD_TOOLS) - # Build binaryen tools - add_subdirectory(src/tools) -endif() - add_subdirectory(third_party) # Configure lit tests add_subdirectory(test/lit) -if(BUILD_TESTS) - # Configure GTest unit tests - add_subdirectory(test/gtest) -endif() - # Object files set(binaryen_objs $ @@ -351,9 +291,9 @@ $ $) -if(BUILD_LLVM_DWARF) +IF(BUILD_LLVM_DWARF) SET(binaryen_objs ${binaryen_objs} $) -endif() +ENDIF() # Sources. @@ -370,15 +310,34 @@ message(STATUS "Building libbinaryen as shared library.") add_library(binaryen SHARED ${binaryen_SOURCES} ${binaryen_objs}) endif() -if(NOT (BUILD_STATIC_LIB AND BYN_INSTALL_TOOLS_ONLY)) - install(TARGETS binaryen - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) -endif() -if(NOT BYN_INSTALL_TOOLS_ONLY) - install(FILES src/binaryen-c.h src/wasm-delegations.def DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -endif() +install(TARGETS binaryen + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install(FILES src/binaryen-c.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +function(binaryen_add_executable name sources) + add_executable(${name} ${sources}) + target_link_libraries(${name} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(${name} binaryen) + set_property(TARGET ${name} PROPERTY CXX_STANDARD ${CXX_STANDARD}) + set_property(TARGET ${name} PROPERTY CXX_STANDARD_REQUIRED ON) + binaryen_setup_rpath(${name}) + install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_BINDIR}) +endfunction() + +binaryen_add_executable(wasm-opt src/tools/wasm-opt.cpp) +binaryen_add_executable(wasm-shell src/tools/wasm-shell.cpp) +binaryen_add_executable(wasm-metadce src/tools/wasm-metadce.cpp) +binaryen_add_executable(wasm2js src/tools/wasm2js.cpp) +binaryen_add_executable(wasm-emscripten-finalize src/tools/wasm-emscripten-finalize.cpp) +binaryen_add_executable(wasm-as src/tools/wasm-as.cpp) +binaryen_add_executable(wasm-dis src/tools/wasm-dis.cpp) +binaryen_add_executable(wasm-ctor-eval src/tools/wasm-ctor-eval.cpp) +binaryen_add_executable(wasm-reduce src/tools/wasm-reduce.cpp) +binaryen_add_executable(wasm-split src/tools/wasm-split.cpp) + # binaryen.js # @@ -398,14 +357,16 @@ target_link_libraries(binaryen_wasm wasm asmjs emscripten-optimizer passes ir cfg support wasm) target_link_libraries(binaryen_wasm "-s NO_FILESYSTEM=0") target_link_libraries(binaryen_wasm "-s NODERAWFS=0") - target_link_libraries(binaryen_wasm "-s EXPORT_NAME=Binaryen") - target_link_libraries(binaryen_wasm "-s EXPORT_ES6=1") + target_link_libraries(binaryen_wasm "-s EXPORT_NAME=binaryen") target_link_libraries(binaryen_wasm "--post-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-post.js") target_link_libraries(binaryen_wasm "--extern-pre-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-extern-pre.js") + target_link_libraries(binaryen_wasm "--extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-extern-post.js") target_link_libraries(binaryen_wasm optimized "--closure 1") target_link_libraries(binaryen_wasm optimized "--closure-args \"--language_in=ECMASCRIPT6 --language_out=ECMASCRIPT6\"") target_link_libraries(binaryen_wasm optimized "-flto") target_link_libraries(binaryen_wasm debug "--profiling") + set_property(TARGET binaryen_wasm PROPERTY CXX_STANDARD ${CXX_STANDARD}) + set_property(TARGET binaryen_wasm PROPERTY CXX_STANDARD_REQUIRED ON) install(TARGETS binaryen_wasm DESTINATION ${CMAKE_INSTALL_BINDIR}) # binaryen.js JavaScript variant @@ -418,39 +379,19 @@ # only valid with fastcomp and WASM=0 target_link_libraries(binaryen_js "-s ELIMINATE_DUPLICATE_FUNCTIONS=1") endif() - # Disabling filesystem and setting web environment for js_of_ocaml - # so it doesn't try to detect the "node" environment - if(JS_OF_OCAML) - target_link_libraries(binaryen_js "-s NO_FILESYSTEM=1") - target_link_libraries(binaryen_js "-s ENVIRONMENT=web,worker") - else() - target_link_libraries(binaryen_js "-s NO_FILESYSTEM=0") - endif() + target_link_libraries(binaryen_js "-s NO_FILESYSTEM=0") target_link_libraries(binaryen_js "-s NODERAWFS=0") - target_link_libraries(binaryen_js "-s EXPORT_NAME=Binaryen") - # Currently, js_of_ocaml can only process ES5 code - if(JS_OF_OCAML) - target_link_libraries(binaryen_js "-s EXPORT_ES6=0") - else() - target_link_libraries(binaryen_js "-s EXPORT_ES6=1") - endif() + target_link_libraries(binaryen_js "-s EXPORT_NAME=binaryen") target_link_libraries(binaryen_js "--post-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-post.js") - # js_of_ocaml needs a specified variable with special comment to provide the library to consumers - if(JS_OF_OCAML) - target_link_libraries(binaryen_js "--extern-pre-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.jsoo-extern-pre.js") - else() - target_link_libraries(binaryen_js "--extern-pre-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-extern-pre.js") - endif() + target_link_libraries(binaryen_js "--extern-pre-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-extern-pre.js") + target_link_libraries(binaryen_js "--extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/src/js/binaryen.js-extern-post.js") target_link_libraries(binaryen_js optimized "--closure 1") - # Currently, js_of_ocaml can only process ES5 code - if(JS_OF_OCAML) - target_link_libraries(binaryen_js optimized "--closure-args \"--language_in=ECMASCRIPT6 --language_out=ECMASCRIPT5\"") - else() - target_link_libraries(binaryen_js optimized "--closure-args \"--language_in=ECMASCRIPT6 --language_out=ECMASCRIPT6\"") - endif() + target_link_libraries(binaryen_js optimized "--closure-args \"--language_in=ECMASCRIPT6 --language_out=ECMASCRIPT6\"") target_link_libraries(binaryen_js optimized "-flto") target_link_libraries(binaryen_js debug "--profiling") target_link_libraries(binaryen_js debug "-s ASSERTIONS") + set_property(TARGET binaryen_js PROPERTY CXX_STANDARD ${CXX_STANDARD}) + set_property(TARGET binaryen_js PROPERTY CXX_STANDARD_REQUIRED ON) install(TARGETS binaryen_js DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff -Nru binaryen-108/Contributing.md binaryen-99/Contributing.md --- binaryen-108/Contributing.md 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/Contributing.md 2021-01-07 20:01:06.000000000 +0000 @@ -3,7 +3,7 @@ Interested in participating? Please follow [the same contributing guidelines as the design repository][]. - [the same contributing guidelines as the design repository]: https://github.com/WebAssembly/design/blob/main/Contributing.md + [the same contributing guidelines as the design repository]: https://github.com/WebAssembly/design/blob/master/Contributing.md Also, please be sure to read [the README.md](README.md) for this repository. diff -Nru binaryen-108/debian/changelog binaryen-99/debian/changelog --- binaryen-108/debian/changelog 2022-05-28 12:15:15.000000000 +0000 +++ binaryen-99/debian/changelog 2022-10-14 00:17:16.000000000 +0000 @@ -1,57 +1,9 @@ -binaryen (108-1) unstable; urgency=medium +binaryen (99-3~18.04.sav0) bionic; urgency=medium - * New upstream version 108 - * Drop no-gtests.patch. - * Disable the tests to avoid a dependency on gtests. - * Declare compliance with Debian Policy 4.6.1. + * Backport to Bionic + * debian/control: Set debhelper-compat (= 11) BD - -- Markus Koschany Sat, 28 May 2022 14:15:15 +0200 - -binaryen (106-1) unstable; urgency=medium - - * New upstream version 106. - * Build-depend on libgtest-dev and do not look for a local copy of the - gtest library. - - -- Markus Koschany Fri, 29 Apr 2022 12:50:19 +0200 - -binaryen (105-1) unstable; urgency=medium - - * New upstream version 105. - - -- Markus Koschany Sun, 16 Jan 2022 12:52:04 +0100 - -binaryen (104-1) unstable; urgency=medium - - * New upstream version 104. - - -- Markus Koschany Tue, 21 Dec 2021 12:36:52 +0100 - -binaryen (103-1) unstable; urgency=medium - - * New upstream version 103. - - -- Markus Koschany Sun, 12 Dec 2021 03:04:56 +0100 - -binaryen (102-1) unstable; urgency=medium - - * New upstream version 102. - - -- Markus Koschany Tue, 14 Sep 2021 00:21:00 +0200 - -binaryen (101-1) unstable; urgency=medium - - * New upstream version 101. - * Declare compliance with Debian Policy 4.6.0. - - -- Markus Koschany Wed, 18 Aug 2021 20:41:28 +0200 - -binaryen (100-1) experimental; urgency=medium - - * New upstream version 100. - * Drop all patches. Fixed upstream. - - -- Markus Koschany Tue, 09 Mar 2021 23:53:29 +0100 + -- Rob Savoury Thu, 13 Oct 2022 17:17:16 -0700 binaryen (99-3) unstable; urgency=medium diff -Nru binaryen-108/debian/control binaryen-99/debian/control --- binaryen-108/debian/control 2022-05-28 12:15:15.000000000 +0000 +++ binaryen-99/debian/control 2022-10-14 00:17:16.000000000 +0000 @@ -4,10 +4,9 @@ Maintainer: Markus Koschany Build-Depends: cmake, - debhelper-compat (= 13), - libgtest-dev, + debhelper-compat (= 11), python3 -Standards-Version: 4.6.1 +Standards-Version: 4.5.1 Homepage: https://github.com/WebAssembly/binaryen Vcs-Git: https://salsa.debian.org/debian/binaryen.git Vcs-Browser: https://salsa.debian.org/debian/binaryen diff -Nru binaryen-108/debian/copyright binaryen-99/debian/copyright --- binaryen-108/debian/copyright 2022-05-28 12:15:15.000000000 +0000 +++ binaryen-99/debian/copyright 2021-02-02 13:54:30.000000000 +0000 @@ -3,10 +3,10 @@ Source: https://github.com/WebAssembly/binaryen Files: * -Copyright: 2015-2022, WebAssembly Community Group participants +Copyright: 2015-2020, WebAssembly Community Group participants License: Apache-2.0 -Files: third_party/llvm-project/* +Files: third_party/* Copyright: LLVM project License: Apache-2.0-with-LLVM-Exceptions See /usr/share/common-licenses/Apache-2.0 for the complete license text of the @@ -27,7 +27,7 @@ Software. Files: debian/* -Copyright: 2018-2022, Markus Koschany +Copyright: 2018-2021, Markus Koschany License: Apache-2.0 License: Apache-2.0 diff -Nru binaryen-108/debian/patches/project-version.patch binaryen-99/debian/patches/project-version.patch --- binaryen-108/debian/patches/project-version.patch 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/debian/patches/project-version.patch 2021-02-02 13:54:30.000000000 +0000 @@ -0,0 +1,21 @@ +From: Markus Koschany +Date: Tue, 2 Feb 2021 14:53:17 +0100 +Subject: project version + +Bug-Debian: https://bugs.debian.org/981638 +Forwarded: no +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 775fade..da9d69e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,5 +1,5 @@ + cmake_minimum_required(VERSION 3.1.3) +-project(binaryen LANGUAGES C CXX VERSION 98) ++project(binaryen LANGUAGES C CXX VERSION 99) + include(GNUInstallDirs) + + # The C++ standard whose features are required to build Binaryen. diff -Nru binaryen-108/debian/patches/series binaryen-99/debian/patches/series --- binaryen-108/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/debian/patches/series 2021-02-02 13:54:30.000000000 +0000 @@ -0,0 +1,2 @@ +wasm-delegations.patch +project-version.patch diff -Nru binaryen-108/debian/patches/wasm-delegations.patch binaryen-99/debian/patches/wasm-delegations.patch --- binaryen-108/debian/patches/wasm-delegations.patch 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/debian/patches/wasm-delegations.patch 2021-02-02 13:54:30.000000000 +0000 @@ -0,0 +1,24 @@ +From: Markus Koschany +Date: Mon, 11 Jan 2021 23:06:19 +0100 +Subject: wasm-delegations + +Install missing wasm-delegations.h file. + +Origin: https://github.com/WebAssembly/binaryen/commit/0a1972b56a5bae9874808673041d3a48d3c86153 +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9a2744b..775fade 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -315,7 +315,7 @@ install(TARGETS binaryen + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +-install(FILES src/binaryen-c.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) ++install(FILES src/binaryen-c.h src/wasm-delegations.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + function(binaryen_add_executable name sources) + add_executable(${name} ${sources}) diff -Nru binaryen-108/debian/rules binaryen-99/debian/rules --- binaryen-108/debian/rules 2022-05-28 12:15:15.000000000 +0000 +++ binaryen-99/debian/rules 2021-02-02 13:54:30.000000000 +0000 @@ -4,13 +4,9 @@ %: dh $@ --buildsystem=cmake -override_dh_auto_configure: - dh_auto_configure -- -DBUILD_TESTS=OFF - override_dh_auto_install: dh_auto_install - # Building wasm.js from source requires emscripten - # which would create a circular dependency chain + # Building wasm.js from source requires emscripten which is RC buggy $(RM) debian/binaryen/usr/share/binaryen/wasm.js override_dh_auto_test: diff -Nru binaryen-108/.flake8 binaryen-99/.flake8 --- binaryen-108/.flake8 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/.flake8 2021-01-07 20:01:06.000000000 +0000 @@ -3,4 +3,4 @@ E501, # line too long E241, # space after comma (ignored for list in gen-s-parser.py) W504 # line break after binary operator -exclude = third_party,./test/emscripten,./test/spec,./test/wasm-install,./test/lit +exclude = ./test/emscripten,./test/spec,./test/wasm-install,./test/lit diff -Nru binaryen-108/.git-blame-ignore-revs binaryen-99/.git-blame-ignore-revs --- binaryen-108/.git-blame-ignore-revs 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/.git-blame-ignore-revs 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# This file contains a list of revisions that are ignored by git blame -# These revisions are unlikely what you are interested in when blaming. -# You can set this file as a default ignore file for blame by running -# the following command. -# -# $ git config blame.ignoreRevsFile .git-blame-ignore-revs - -# Mass change to apply clang-format to everything -db9124f1de0478dcac525009b6f1589b44a7edd8 diff -Nru binaryen-108/.github/workflows/build_release.yml binaryen-99/.github/workflows/build_release.yml --- binaryen-108/.github/workflows/build_release.yml 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/.github/workflows/build_release.yml 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,159 @@ +name: Build Release + +# Trigger whenever a release is created +on: + release: + types: + - created + +jobs: + build: + name: build + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [macos-latest, windows-latest] + defaults: + run: + shell: bash + steps: + - uses: actions/setup-python@v1 + with: + python-version: '3.x' + - uses: actions/checkout@v1 + with: + submodules: true + + - name: install ninja (macos) + run: brew install ninja + if: matrix.os == 'macos-latest' + + - name: install ninja (win) + run: choco install ninja + if: matrix.os == 'windows-latest' + + - name: mkdir + run: mkdir -p out + + - name: cmake (macos) + run: cmake -S . -B out -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=out/install + if: matrix.os == 'macos-latest' + + - name: cmake (win) + # -G "Visual Studio 15 2017" + run: cmake -S . -B out -DCMAKE_INSTALL_PREFIX=out/install + if: matrix.os == 'windows-latest' + + - name: build + run: cmake --build out --config Release --target install + + - name: strip + run: find out/install/ -type f -perm -u=x -exec strip -x {} + + if: matrix.os != 'windows-latest' + + - name: archive + id: archive + run: | + OSNAME=$(echo ${{ matrix.os }} | sed 's/-latest//') + VERSION=${{ github.event.release.tag_name }} + PKGNAME="binaryen-$VERSION-x86_64-$OSNAME" + TARBALL=$PKGNAME.tar.gz + SHASUM=$PKGNAME.tar.gz.sha256 + mv out/install binaryen-$VERSION + tar -czf $TARBALL binaryen-$VERSION + echo "::set-output name=tarball::$TARBALL" + echo "::set-output name=shasum::$SHASUM" + + - name: upload tarball + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.tarball }} + asset_name: ${{ steps.archive.outputs.tarball }} + asset_content_type: application/gzip + + # We do the shasum as a seprate step because this tool doesn't + # exist on windows. + - name: shasum + id: shasum + run: shasum -a 256 ${{ steps.archive.outputs.tarball }} > ${{ steps.archive.outputs.shasum }} + if: matrix.os != 'windows-latest' + + - name: upload shasum + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.shasum }} + asset_name: ${{ steps.archive.outputs.shasum }} + asset_content_type: text/plain + if: matrix.os != 'windows-latest' + + # Build with gcc 6.3 and run tests on Alpine Linux (inside chroot). + # Note: Alpine uses musl libc. + build-alpine: + name: alpine + runs-on: ubuntu-latest + steps: + - uses: actions/setup-python@v1 + with: + python-version: '3.x' + - uses: actions/checkout@v1 + - name: start docker + run: | + docker run -w /src -dit --name alpine -v $PWD:/src node:lts-alpine + echo 'docker exec alpine "$@";' > ./alpine.sh + chmod +x ./alpine.sh + + - name: install packages + run: | + ./alpine.sh apk update + ./alpine.sh apk add build-base cmake git python3 clang ninja + + - name: cmake + run: | + ./alpine.sh cmake . -G Ninja -DCMAKE_CXX_FLAGS="-static" -DCMAKE_C_FLAGS="-static" -DCMAKE_BUILD_TYPE=Release -DBUILD_STATIC_LIB=ON -DCMAKE_INSTALL_PREFIX=install + + - name: build + run: | + ./alpine.sh ninja install + + - name: test + run: ./alpine.sh python3 ./check.py + + - name: archive + id: archive + run: | + VERSION=${{ github.event.release.tag_name }} + PKGNAME="binaryen-$VERSION-x86_64-linux" + TARBALL=$PKGNAME.tar.gz + SHASUM=$PKGNAME.tar.gz.sha256 + ./alpine.sh find install/ -type f -perm -u=x -exec strip {} + + mv install binaryen-$VERSION + tar -czf $TARBALL binaryen-$VERSION + shasum -a 256 $TARBALL > $SHASUM + echo "::set-output name=tarball::$TARBALL" + echo "::set-output name=shasum::$SHASUM" + + - name: upload tarball + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.tarball }} + asset_name: ${{ steps.archive.outputs.tarball }} + asset_content_type: application/gzip + + - name: upload shasum + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./${{ steps.archive.outputs.shasum }} + asset_name: ${{ steps.archive.outputs.shasum }} + asset_content_type: text/plain diff -Nru binaryen-108/.github/workflows/ci.yml binaryen-99/.github/workflows/ci.yml --- binaryen-108/.github/workflows/ci.yml 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/.github/workflows/ci.yml 2021-01-07 20:01:06.000000000 +0000 @@ -5,7 +5,7 @@ # branches which are also PRs. push: branches: - - main + - master - kripken/* pull_request: @@ -13,15 +13,12 @@ lint: name: lint - if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-latest steps: - uses: actions/setup-python@v1 with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install tools run: | sudo pip3 install -r requirements-dev.txt @@ -35,6 +32,8 @@ # clang-tidy requires compile_commands.json generated by cmake cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ./scripts/clang-tidy-diff.sh + - name: gen-s-parser + run: ./scripts/gen-s-parser.py | diff src/gen-s-parser.inc - build: name: build @@ -47,16 +46,10 @@ with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install Python dev dependencies run: pip3 install -r requirements-dev.txt - - name: gen-s-parser - run: ./scripts/gen-s-parser.py | diff src/gen-s-parser.inc - - if: matrix.os == 'ubuntu-latest' - - name: install ninja (linux) run: sudo apt-get install ninja-build if: matrix.os == 'ubuntu-latest' @@ -77,7 +70,7 @@ if: matrix.os == 'ubuntu-latest' - name: cmake (macos) - run: cmake -S . -B out -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_OSX_ARCHITECTURES=x86_64 + run: cmake -S . -B out -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=out/install if: matrix.os == 'macos-latest' - name: cmake (win) @@ -86,7 +79,7 @@ if: matrix.os == 'windows-latest' - name: build - run: cmake --build out --config Release -v + run: cmake --build out --config Release - name: install run: cmake --install out --config Release @@ -102,21 +95,19 @@ path: out/install - name: test binaryen-lit - run: python out/bin/binaryen-lit -vv test/lit/parse-error.wast + run: python out/bin/binaryen-lit test/lit/parse-error.wast - name: test run: python check.py --binaryen-bin=out/bin build-clang: - name: clang (LTO) + name: clang runs-on: ubuntu-latest steps: - uses: actions/setup-python@v1 with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install ninja run: sudo apt-get install ninja-build - name: install Python dev dependencies @@ -124,11 +115,11 @@ - name: cmake run: | mkdir -p out - cmake -S . -B out -G Ninja -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DBYN_ENABLE_LTO=ON + cmake -S . -B out -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ - name: build - run: cmake --build out -v + run: cmake --build out - name: test binaryen-lit - run: python out/bin/binaryen-lit -vv test/lit/parse-error.wast + run: python out/bin/binaryen-lit test/lit/parse-error.wast - name: test run: python check.py --binaryen-bin=out/bin @@ -144,8 +135,6 @@ with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install ninja run: sudo apt-get install ninja-build - name: install Python dev dependencies @@ -153,50 +142,12 @@ - name: cmake run: | mkdir -p out - cmake -S . -B out -G Ninja -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" + cmake -S . -B out -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" - name: build run: cmake --build out - name: test run: python check.py --binaryen-bin=out/bin - # Build with gcc 6.3 and run tests on Alpine Linux (inside chroot). - # Note: Alpine uses musl libc. - # Keep in sync with build_release.yml - build-alpine: - name: alpine - runs-on: ubuntu-latest - steps: - - uses: actions/setup-python@v1 - with: - python-version: '3.x' - - uses: actions/checkout@v1 - with: - submodules: true - - name: start docker - run: | - docker run -w /src -dit --name alpine -v $PWD:/src node:lts-alpine - echo 'docker exec alpine "$@";' > ./alpine.sh - chmod +x ./alpine.sh - - - name: install packages - run: | - ./alpine.sh apk update - ./alpine.sh apk add build-base cmake git python3 py3-pip clang ninja - - - name: install python dev dependencies - run: ./alpine.sh pip3 install -r requirements-dev.txt - - - name: cmake - run: | - ./alpine.sh cmake . -G Ninja -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_CXX_FLAGS="-static" -DCMAKE_C_FLAGS="-static" -DCMAKE_BUILD_TYPE=Release -DBUILD_STATIC_LIB=ON -DCMAKE_INSTALL_PREFIX=install - - - name: build - run: | - ./alpine.sh ninja install - - - name: test - run: ./alpine.sh python3 ./check.py - # Duplicates build-asan. Please keep in sync build-ubsan: name: ubsan @@ -210,8 +161,6 @@ with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install ninja run: sudo apt-get install ninja-build - name: install Python dev dependencies @@ -219,7 +168,7 @@ - name: cmake run: | mkdir -p out - cmake -S . -B out -G Ninja -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS -fsanitize-blacklist=$PWD/ubsan.blacklist" + cmake -S . -B out -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS -fsanitize-blacklist=$PWD/ubsan.blacklist" - name: build run: cmake --build out - name: test @@ -237,8 +186,6 @@ with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install ninja run: sudo apt-get install ninja-build - name: install Python dev dependencies @@ -246,7 +193,7 @@ - name: cmake run: | mkdir -p out - cmake -S . -B out -G Ninja -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" -DCMAKE_EXE_LINKER_FLAGS="$LINKER_FLAGS" + cmake -S . -B out -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" -DCMAKE_EXE_LINKER_FLAGS="$LINKER_FLAGS" - name: build run: cmake --build out - name: test @@ -261,8 +208,6 @@ with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: install ninja run: sudo apt-get install ninja-build - name: emsdk install @@ -288,8 +233,6 @@ with: python-version: '3.x' - uses: actions/checkout@v1 - with: - submodules: true - name: cmake run: | mkdir -p out diff -Nru binaryen-108/.github/workflows/create_release.yml binaryen-99/.github/workflows/create_release.yml --- binaryen-108/.github/workflows/create_release.yml 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/.github/workflows/create_release.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -name: Create Release - -# Trigger whenever a tag is created/updated - -on: - push: - tags: - - "*" - -permissions: - contents: write - -jobs: - build: - name: build - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [macos-latest, windows-latest] - defaults: - run: - shell: bash - steps: - - uses: actions/checkout@v1 - with: - submodules: true - - - name: install ninja (macos) - run: brew install ninja - if: matrix.os == 'macos-latest' - - - name: install ninja (win) - run: choco install ninja - if: matrix.os == 'windows-latest' - - - name: mkdir - run: mkdir -p out - - - name: cmake (macos) - run: | - cmake -S . -B out -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=out/install -DCMAKE_OSX_ARCHITECTURES=x86_64 - cmake -S . -B out-arm64 -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=out-arm64/install -DCMAKE_OSX_ARCHITECTURES=arm64 - if: matrix.os == 'macos-latest' - - - name: cmake (win) - # -G "Visual Studio 15 2017" - run: cmake -S . -B out -DCMAKE_INSTALL_PREFIX=out/install - if: matrix.os == 'windows-latest' - - - name: build - run: cmake --build out -v --config Release --target install - - - name: build-arm64 - run: cmake --build out-arm64 -v --config Release --target install - if: matrix.os == 'macos-latest' - - - name: strip - run: find out*/install/ -type f -perm -u=x -exec strip -x {} + - if: matrix.os != 'windows-latest' - - - name: archive - id: archive - run: | - OSNAME=$(echo ${{ matrix.os }} | sed 's/-latest//') - VERSION=$GITHUB_REF_NAME - PKGNAME="binaryen-$VERSION-x86_64-$OSNAME" - TARBALL=$PKGNAME.tar.gz - SHASUM=$PKGNAME.tar.gz.sha256 - rm -rf binaryen-$VERSION - mv out/install binaryen-$VERSION - tar -czf $TARBALL binaryen-$VERSION - # on Windows, MSYS2 will strip the carriage return from CMake output - cmake -E sha256sum $TARBALL > $SHASUM - echo "::set-output name=tarball::$TARBALL" - echo "::set-output name=shasum::$SHASUM" - - - name: archive-arm64 - id: archive-arm64 - run: | - OSNAME=$(echo ${{ matrix.os }} | sed 's/-latest//') - VERSION=$GITHUB_REF_NAME - PKGNAME="binaryen-$VERSION-arm64-$OSNAME" - TARBALL=$PKGNAME.tar.gz - SHASUM=$PKGNAME.tar.gz.sha256 - rm -rf binaryen-$VERSION - mv out-arm64/install binaryen-$VERSION - tar -czf $TARBALL binaryen-$VERSION - # on Windows, MSYS2 will strip the carriage return from CMake output - cmake -E sha256sum $TARBALL > $SHASUM - echo "::set-output name=tarball::$TARBALL" - echo "::set-output name=shasum::$SHASUM" - if: matrix.os == 'macos-latest' - - - name: upload tarball - uses: softprops/action-gh-release@v1 - with: - draft: true - files: | - ${{ steps.archive.outputs.tarball }} - ${{ steps.archive.outputs.shasum }} - ${{ steps.archive-arm64.outputs.tarball }} - ${{ steps.archive-arm64.outputs.shasum }} - - # Build with gcc 6.3 and run tests on Alpine Linux (inside chroot). - # Note: Alpine uses musl libc. - build-alpine: - name: alpine - runs-on: ubuntu-latest - steps: - - uses: actions/setup-python@v1 - with: - python-version: '3.x' - - uses: actions/checkout@v1 - with: - submodules: true - - name: start docker - run: | - docker run -w /src -dit --name alpine -v $PWD:/src node:lts-alpine - echo 'docker exec alpine "$@";' > ./alpine.sh - chmod +x ./alpine.sh - - - name: install packages - run: | - ./alpine.sh apk update - ./alpine.sh apk add build-base cmake git python3 clang ninja py3-pip - - - name: install python dev dependencies - run: ./alpine.sh pip3 install -r requirements-dev.txt - - - name: cmake - run: | - ./alpine.sh cmake . -G Ninja -DCMAKE_CXX_FLAGS="-static" -DCMAKE_C_FLAGS="-static" -DCMAKE_BUILD_TYPE=Release -DBUILD_STATIC_LIB=ON -DCMAKE_INSTALL_PREFIX=install - - - name: build - run: | - ./alpine.sh ninja install - - - name: test - run: ./alpine.sh python3 ./check.py - - - name: archive - id: archive - run: | - VERSION=$GITHUB_REF_NAME - PKGNAME="binaryen-$VERSION-x86_64-linux" - TARBALL=$PKGNAME.tar.gz - SHASUM=$PKGNAME.tar.gz.sha256 - ./alpine.sh find install/ -type f -perm -u=x -exec strip {} + - mv install binaryen-$VERSION - tar -czf $TARBALL binaryen-$VERSION - cmake -E sha256sum $TARBALL > $SHASUM - echo "::set-output name=tarball::$TARBALL" - echo "::set-output name=shasum::$SHASUM" - - - name: upload tarball - uses: softprops/action-gh-release@v1 - with: - draft: true - files: | - ${{ steps.archive.outputs.tarball }} - ${{ steps.archive.outputs.shasum }} diff -Nru binaryen-108/.gitignore binaryen-99/.gitignore --- binaryen-108/.gitignore 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/.gitignore 2021-01-07 20:01:06.000000000 +0000 @@ -22,6 +22,8 @@ /bin/ /lib/ /config.h +*.o +*.obj compile_commands.json test/lit/lit.site.cfg.py @@ -43,6 +45,3 @@ # files related to VS Code /.history /.vscode - -# files related to Emsdk installation -.emsdk_version diff -Nru binaryen-108/.gitmodules binaryen-99/.gitmodules --- binaryen-108/.gitmodules 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/.gitmodules 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -[submodule "third_party/googletest"] - path = third_party/googletest - url = https://github.com/google/googletest.git diff -Nru binaryen-108/README.md binaryen-99/README.md --- binaryen-108/README.md 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/README.md 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,4 @@ -[![CI](https://github.com/WebAssembly/binaryen/workflows/CI/badge.svg?branch=main&event=push)](https://github.com/WebAssembly/binaryen/actions?query=workflow%3ACI) +[![CI](https://github.com/WebAssembly/binaryen/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/WebAssembly/binaryen/actions?query=workflow%3ACI) # Binaryen @@ -26,8 +26,8 @@ Compilers using Binaryen include: - * [`AssemblyScript`](https://github.com/AssemblyScript/assemblyscript) which compiles a variant of TypeScript to WebAssembly - * [`wasm2js`](https://github.com/WebAssembly/binaryen/blob/main/src/wasm2js.h) which compiles WebAssembly to JS + * [`AssemblyScript`](https://github.com/AssemblyScript/assemblyscript) which compiles a subset of TypeScript to WebAssembly + * [`wasm2js`](https://github.com/WebAssembly/binaryen/blob/master/src/wasm2js.h) which compiles WebAssembly to JS * [`Asterius`](https://github.com/tweag/asterius) which compiles Haskell to WebAssembly * [`Grain`](https://github.com/grain-lang/grain) which compiles Grain to WebAssembly @@ -70,11 +70,7 @@ multivalue instructions and blocks, it is represented with tuple types that do not exist in the WebAssembly language. In addition to multivalue instructions, locals and globals can also have tuple types in Binaryen IR - but not in WebAssembly. Experiments show that better support for - multivalue could enable useful but small code size savings of 1-3%, so it - has not been worth changing the core IR structure to support it better. - * Block input values (currently only supported in `catch` blocks in the - exception handling feature) are represented as `pop` subexpressions. + but not in WebAssembly. * Types and unreachable code * WebAssembly limits block/if/loop types to none and the concrete value types (i32, i64, f32, f64). Binaryen IR has an unreachable type, and it allows @@ -111,12 +107,19 @@ emitted when generating wasm. Instead its list of operands will be directly used in the containing node. Such a block is sometimes called an "implicit block". - * Reference Types - * The wasm text and binary formats require that a function whose address is - taken by `ref.func` must be either in the table, or declared via an - `(elem declare func $..)`. Binaryen will emit that data when necessary, but - it does not represent it in IR. That is, IR can be worked on without needing - to think about declaring function references. + * Multivalue + * Binaryen will not represent multivalue instructions and values directly. + Binaryen's main focus is on optimization of wasm, and therefore the question + of whether we should have multivalue in the main IR is whether it justifes + the extra complexity there. Experiments show that the shrinking of code + size thanks to multivalue is useful but small, just 1-3% or so. Given that, + we prefer to keep the main IR simple, and focus on multivalue optimizations + in Stack IR, which is more suitable for such things. + * Binaryen does still need to implement the "ABI" level of multivalue, that + is, we need multivalue calls because those may cross module boundaries, + and so they are observable externally. To support that, Binaryen may use + `push` and `pop` as mentioned earlier; another option is to add LLVM-like + `extractvalue/composevalue` instructions. As a result, you might notice that round-trip conversions (wasm => Binaryen IR => wasm) change code a little in some corner cases. @@ -141,46 +144,6 @@ incorrectly. * For similar reasons, nodes should not appear in more than one functions. -### Intrinsics - -Binaryen intrinsic functions look like calls to imports, e.g., - -```wat -(import "binaryen-intrinsics" "foo" (func $foo)) -``` - -Implementing them that way allows them to be read and written by other tools, -and it avoids confusing errors on a binary format error that could happen in -those tools if we had a custom binary format extension. - -An intrinsic method may be optimized away by the optimizer. If it is not, it -must be **lowered** before shipping the wasm, as otherwise it will look like a -call to an import that does not exist (and VMs will show an error on not having -a proper value for that import). That final lowering is *not* done -automatically. A user of intrinsics must run the pass for that explicitly, -because the tools do not know when the user intends to finish optimizing, as the -user may have a pipeline of multiple optimization steps, or may be doing local -experimentation, or fuzzing/reducing, etc. Only the user knows when the final -optimization happens before the wasm is "final" and ready to be shipped. Note -that, in general, some additional optimizations may be possible after the final -lowering, and so a useful pattern is to optimize once normally with intrinsics, -then lower them away, then optimize after that, e.g.: - -``` -wasm-opt input.wasm -o output.wasm -O --intrinsic-lowering -O -``` - -Each intrinsic defines its semantics, which includes what the optimizer is -allowed to do with it and what the final lowering will turn it to. See -[intrinsics.h](https://github.com/WebAssembly/binaryen/blob/main/src/ir/intrinsics.h) -for the detailed definitions. A quick summary appears here: - -* `call.without.effects`: Similar to a `call_ref` in that it receives - parameters, and a reference to a function to call, and calls that function - with those parameters, except that the optimizer can assume the call has no - side effects, and may be able to optimize it out (if it does not have a - result that is used, generally). - ## Tools This repository contains code that builds the following tools in `bin/`: @@ -202,16 +165,16 @@ also run the spec test suite. * **wasm-emscripten-finalize**: Takes a wasm binary produced by llvm+lld and performs emscripten-specific passes over it. - * **wasm-ctor-eval**: A tool that can execute functions (or parts of functions) - at compile time. - * **binaryen.js**: A standalone JavaScript library that exposes Binaryen methods for [creating and optimizing Wasm modules](https://github.com/WebAssembly/binaryen/blob/main/test/binaryen.js/hello-world.js). For builds, see [binaryen.js on npm](https://www.npmjs.com/package/binaryen) (or download it directly from [github](https://raw.githubusercontent.com/AssemblyScript/binaryen.js/master/index.js), [rawgit](https://cdn.rawgit.com/AssemblyScript/binaryen.js/master/index.js), or [unpkg](https://unpkg.com/binaryen@latest/index.js)). + * **wasm-ctor-eval**: A tool that can execute C++ global constructors ahead of + time. Used by Emscripten. + * **binaryen.js**: A standalone JavaScript library that exposes Binaryen methods for [creating and optimizing WASM modules](https://github.com/WebAssembly/binaryen/blob/master/test/binaryen.js/hello-world.js). For builds, see [binaryen.js on npm](https://www.npmjs.com/package/binaryen) (or download it directly from [github](https://raw.githubusercontent.com/AssemblyScript/binaryen.js/master/index.js), [rawgit](https://cdn.rawgit.com/AssemblyScript/binaryen.js/master/index.js), or [unpkg](https://unpkg.com/binaryen@latest/index.js)). Usage instructions for each are below. ## Binaryen Optimizations Binaryen contains -[a lot of optimization passes](https://github.com/WebAssembly/binaryen/tree/main/src/passes) +[a lot of optimization passes](https://github.com/WebAssembly/binaryen/tree/master/src/passes) to make WebAssembly smaller and faster. You can run the Binaryen optimizer by using ``wasm-opt``, but also they can be run while using other tools, like ``wasm2js`` and ``wasm-metadce``. @@ -293,34 +256,23 @@ it usually is run on the final linked wasm. Advanced optimization techniques in the Binaryen optimizer include -[SSAification](https://github.com/WebAssembly/binaryen/blob/main/src/passes/SSAify.cpp), -[Flat IR](https://github.com/WebAssembly/binaryen/blob/main/src/ir/flat.h), and -[Stack/Poppy IR](https://github.com/WebAssembly/binaryen/blob/main/src/ir/stack-utils.h). +[SSAification](https://github.com/WebAssembly/binaryen/blob/master/src/passes/SSAify.cpp), +[Flat IR](https://github.com/WebAssembly/binaryen/blob/master/src/ir/flat.h), and +[Stack/Poppy IR](https://github.com/WebAssembly/binaryen/blob/master/src/ir/stack-utils.h). Binaryen also contains various passes that do other things than optimizations, like -[legalization for JavaScript](https://github.com/WebAssembly/binaryen/blob/main/src/passes/LegalizeJSInterface.cpp), -[Asyncify](https://github.com/WebAssembly/binaryen/blob/main/src/passes/Asyncify.cpp), +[legalization for JavaScript](https://github.com/WebAssembly/binaryen/blob/master/src/passes/LegalizeJSInterface.cpp), +[Asyncify](https://github.com/WebAssembly/binaryen/blob/master/src/passes/Asyncify.cpp), etc. ## Building -Binaryen uses git submodules (at time of writing just for gtest), so before you build you will have to initialize the submodules: - -``` -git submodule init -git submodule update -``` - -After that you can build with CMake: - ``` cmake . && make ``` -A C++17 compiler is required. Note that you can also use `ninja` as your generator: `cmake -G Ninja . && ninja`. - -To avoid the gtest dependency, you can pass `-DBUILD_TESTS=OFF` to cmake. +A C++14 compiler is required. Note that you can also use `ninja` as your generator: `cmake -G Ninja . && ninja`. Binaryen.js can be built using Emscripten, which can be installed via [the SDK](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html)). @@ -383,7 +335,7 @@ It's easy to add your own transformation passes to the shell, just add `.cpp` files into `src/passes`, and rebuild the shell. For example code, take a look at -the [`lower-if-else` pass](https://github.com/WebAssembly/binaryen/blob/main/src/passes/LowerIfElse.cpp). +the [`lower-if-else` pass](https://github.com/WebAssembly/binaryen/blob/master/src/passes/LowerIfElse.cpp). Some more notes: @@ -460,86 +412,6 @@ int/float conversions do not trap, and so forth. There may also be slight differences in corner cases of conversions, like non-trapping float to int. -### wasm-ctor-eval - -`wasm-ctor-eval` executes functions, or parts of them, at compile time. -After doing so it serializes the runtime state into the wasm, which is like -taking a "snapshot". When the wasm is later loaded and run in a VM, it will -continue execution from that point, without re-doing the work that was already -executed. - -For example, consider this small program: - -```wat -(module - ;; A global variable that begins at 0. - (global $global (mut i32) (i32.const 0)) - - (import "import" "import" (func $import)) - - (func "main" - ;; Set the global to 1. - (global.set $global - (i32.const 1)) - - ;; Call the imported function. This *cannot* be executed at - ;; compile time. - (call $import) - - ;; We will never get to this point, since we stop at the - ;; import. - (global.set $global - (i32.const 2)) - ) -) -``` - -We can evaluate part of it at compile time like this: - -``` -wasm-ctor-eval input.wat --ctors=main -S -o - -``` - -This tells it that there is a single function that we want to execute ("ctor" -is short for "global constructor", a name that comes from code that is executed -before a program's entry point) and then to print it as text to `stdout`. The -result is this: - -```wat -trying to eval main - ...partial evalling successful, but stopping since could not eval: call import: import.import - ...stopping -(module - (type $none_=>_none (func)) - (import "import" "import" (func $import)) - (global $global (mut i32) (i32.const 1)) - (export "main" (func $0_0)) - (func $0_0 - (call $import) - (global.set $global - (i32.const 2) - ) - ) -) -``` - -The logging shows us managing to eval part of `main()`, but not all of it, as -expected: We can eval the first `global.get`, but then we stop at the call to -the imported function (because we don't know what that function will be when the -wasm is actually run in a VM later). Note how in the output wasm the global's -value has been updated from 0 to 1, and that the first `global.get` has been -removed: the wasm is now in a state that, when we run it in a VM, will seamlessly -continue to run from the point at which `wasm-ctor-eval` stopped. - -In this tiny example we just saved a small amount of work. How much work can be -saved depends on your program. (It can help to do pure computation up front, and -leave calls to imports to as late as possible.) - -Note that `wasm-ctor-eval`'s name is related to global constructor functions, -as mentioned earlier, but there is no limitation on what you can execute here. -Any export from the wasm can be executed, if its contents are suitable. For -example, in Emscripten `wasm-ctor-eval` is even run on `main()` when possible. - ## Testing ``` @@ -572,10 +444,6 @@ (or `python third_party/setup.py`) installs required dependencies like the SpiderMonkey JS shell, the V8 JS shell and WABT in `third_party/`. Other scripts automatically pick these up when installed. -Run `pip3 install -r requirements-dev.txt` to get the requirements for the `lit` -tests. Note that you need to have the location `pip` installs to in your `$PATH` -(on linux, `~/.local/bin`). - ### Fuzzing ``` @@ -612,9 +480,8 @@ * Does it compile under Windows and/or Visual Studio? Yes, it does. Here's a step-by-step [tutorial][win32] on how to compile it -under **Windows 10 x64** with with **CMake** and **Visual Studio 2015**. -However, Visual Studio 2017 may now be required. Help would be appreciated on -Windows and OS X as most of the core devs are on Linux. +under **Windows 10 x64** with with **CMake** and **Visual Studio 2015**. Help +would be appreciated on Windows and OS X as most of the core devs are on Linux. [compiling to WebAssembly]: https://github.com/WebAssembly/binaryen/wiki/Compiling-to-WebAssembly-with-Binaryen [win32]: https://github.com/brakmic/bazaar/blob/master/webassembly/COMPILING_WIN32.md diff -Nru binaryen-108/requirements-dev.txt binaryen-99/requirements-dev.txt --- binaryen-108/requirements-dev.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/requirements-dev.txt 2021-01-07 20:01:06.000000000 +0000 @@ -4,5 +4,5 @@ # Install with `pip3 install -r requirements-dev.txt` flake8==3.7.8 -filecheck==0.0.22 +filecheck==0.0.17 lit==0.11.0.post1 diff -Nru binaryen-108/scripts/binaryen-lit.in binaryen-99/scripts/binaryen-lit.in --- binaryen-108/scripts/binaryen-lit.in 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/binaryen-lit.in 2021-01-07 20:01:06.000000000 +0000 @@ -27,5 +27,7 @@ } } +print(builtin_parameters) + if __name__ == '__main__': main(builtin_parameters) diff -Nru binaryen-108/scripts/clang-format-diff.sh binaryen-99/scripts/clang-format-diff.sh --- binaryen-108/scripts/clang-format-diff.sh 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/clang-format-diff.sh 2021-01-07 20:01:06.000000000 +0000 @@ -1,24 +1,28 @@ #!/bin/bash set -o errexit -set -o pipefail -if [ -n "$1" ]; then - BRANCH="$1" -elif [ -n "$GITHUB_BASE_REF" ]; then - BRANCH="origin/$GITHUB_BASE_REF" +# When we are running on travis and *not* part of a pull request we don't +# have any upstream branch to compare against. +if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then + echo "Skipping since not running on travis PR" + exit 0 +fi + +if [ -n "$TRAVIS_BRANCH" ]; then + BRANCH=$TRAVIS_BRANCH else - BRANCH="@{upstream}" + BRANCH=origin/master fi MERGE_BASE=$(git merge-base $BRANCH HEAD) -FORMAT_MSG=$(git clang-format $MERGE_BASE -q --diff) +FORMAT_MSG=$(git clang-format $MERGE_BASE -q --diff -- src/) if [ -n "$FORMAT_MSG" -a "$FORMAT_MSG" != "no modified files to format" ] then echo "Please run git clang-format before committing, or apply this diff:" echo # Run git clang-format again, this time without capruting stdout. This way # clang-format format the message nicely and add color. - git clang-format $MERGE_BASE -q --diff + git clang-format $MERGE_BASE -q --diff -- src/ exit 1 fi diff -Nru binaryen-108/scripts/clang-tidy-diff.sh binaryen-99/scripts/clang-tidy-diff.sh --- binaryen-108/scripts/clang-tidy-diff.sh 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/clang-tidy-diff.sh 2021-01-07 20:01:06.000000000 +0000 @@ -1,14 +1,18 @@ #!/bin/bash set -o errexit -set -o pipefail -if [ -n "$1" ]; then - BRANCH="$1" -elif [ -n "$GITHUB_BASE_REF" ]; then - BRANCH="origin/$GITHUB_BASE_REF" +# When we are running on travis and *not* part of a pull request we don't +# have any upstream branch to compare against. +if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then + echo "Skipping since not running on travis PR" + exit 0 +fi + +if [ -n "$TRAVIS_BRANCH" ]; then + BRANCH=$TRAVIS_BRANCH else - BRANCH="@{upstream}" + BRANCH=origin/master fi CLANG_TIDY=$(which clang-tidy) @@ -17,23 +21,17 @@ exit 1 fi -# This needs for FreeBSD and Darwin which doesn't support readlink -f command -function realpath() { - python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" $1; -} - -CLANG_DIR=$(dirname $(dirname $(realpath $CLANG_TIDY))) +CLANG_DIR=$(dirname $(dirname $(readlink -f $CLANG_TIDY))) CLANG_TIDY_DIFF=$CLANG_DIR/share/clang/clang-tidy-diff.py -ARG="-quiet -p1 -iregex=src/.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)" if [ ! -e "$CLANG_TIDY_DIFF" ]; then echo "Failed to find clang-tidy-diff.py ($CLANG_TIDY_DIFF)" exit 1 fi -TIDY_MSG=$(git diff -U0 $BRANCH... | $CLANG_TIDY_DIFF $ARG 2> /dev/null) +TIDY_MSG=$(git diff -U0 $BRANCH... | $CLANG_TIDY_DIFF -quiet -p1 2> /dev/null) if [ -n "$TIDY_MSG" -a "$TIDY_MSG" != "No relevant changes found." ]; then echo "Please fix clang-tidy errors before committing" echo # Run clang-tidy once again to show the error - git diff -U0 $BRANCH... | $CLANG_TIDY_DIFF $ARG 2> /dev/null + git diff -U0 $BRANCH... | $CLANG_TIDY_DIFF -quiet -p1 2> /dev/null exit 1 fi diff -Nru binaryen-108/scripts/embedwat.py binaryen-99/scripts/embedwat.py --- binaryen-108/scripts/embedwat.py 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/scripts/embedwat.py 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# +# Copyright 2018 WebAssembly Community Group participants +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys + +input_file = sys.argv[1] +output_file = sys.argv[2] + +with open(input_file) as f: + wat = f.read() + +output = """\ +// Automatically generated by embedwat.py + +#include "passes/intrinsics-module.h" + +static const char theModule[%d] = { +""" % (len(wat) + 1) + +for c in wat: + output += str(ord(c)) + ', ' + +output += '''0 +}; + +namespace wasm { +const char* IntrinsicsModuleWast = theModule; +} +''' + +with open(output_file, 'w') as f: + f.write(output) diff -Nru binaryen-108/scripts/emcc-tests.sh binaryen-99/scripts/emcc-tests.sh --- binaryen-108/scripts/emcc-tests.sh 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/emcc-tests.sh 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env bash -set -o errexit -set -o pipefail +set -e mkdir -p emcc-build echo "emcc-tests: build:wasm" diff -Nru binaryen-108/scripts/foreach.py binaryen-99/scripts/foreach.py --- binaryen-108/scripts/foreach.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/foreach.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2021 WebAssembly Community Group participants -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -import subprocess - -from test import support - - -# Usage: foreach infile tempfile cmd... -# -# Split 'infile', which contains multiple text modules, into separate temp files -# containing one text module each and named `tempfile`.0, `tempfile`.1, etc. Run -# `cmd` with the current temp file appended to it on all the temp files in -# sequence. Exit with code 0 only if all of the subprocesses exited with code 0. -def main(): - infile = sys.argv[1] - tempfile = sys.argv[2] - cmd = sys.argv[3:] - returncode = 0 - all_modules = open(infile).read() - for i, (module, asserts) in enumerate(support.split_wast(infile)): - tempname = tempfile + '.' + str(i) - with open(tempname, 'w') as temp: - print(module, file=temp) - new_cmd = cmd + [tempname] - result = subprocess.run(new_cmd) - if result.returncode != 0: - returncode = result.returncode - module_char_start = all_modules.find(module) - module_line_start = all_modules[:module_char_start].count(os.linesep) - print(f'[Failing module at line {module_line_start}]', file=sys.stderr) - sys.exit(returncode) - - -if __name__ == '__main__': - main() diff -Nru binaryen-108/scripts/fuzz_opt.py binaryen-99/scripts/fuzz_opt.py --- binaryen-108/scripts/fuzz_opt.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/fuzz_opt.py 2021-01-07 20:01:06.000000000 +0000 @@ -35,11 +35,9 @@ # parameters -TYPE_SYSTEM_FLAG = '--nominal' - # feature options that are always passed to the tools. +# * multivalue: https://github.com/WebAssembly/binaryen/issues/2770 CONSTANT_FEATURE_OPTS = ['--all-features'] -CONSTANT_FEATURE_OPTS.append(TYPE_SYSTEM_FLAG) INPUT_SIZE_MIN = 1024 INPUT_SIZE_MEAN = 40 * 1024 @@ -47,8 +45,6 @@ PRINT_WATS = False -given_seed = None - # utilities @@ -122,21 +118,6 @@ print('randomized feature opts:', ' '.join(FEATURE_OPTS)) -ALL_FEATURE_OPTS = ['--all-features', '-all', '--mvp-features', '-mvp'] - - -def update_feature_opts(wasm): - global FEATURE_OPTS - # we will re-compute the features; leave all other things as they are - EXTRA = [x for x in FEATURE_OPTS if not x.startswith('--enable') and - not x.startswith('--disable') and x not in ALL_FEATURE_OPTS] - FEATURE_OPTS = run([in_bin('wasm-opt'), wasm] + FEATURE_OPTS + ['--print-features']).strip().split('\n') - # filter out '', which can happen if no features are enabled - FEATURE_OPTS = [x for x in FEATURE_OPTS if x] - print(FEATURE_OPTS, EXTRA) - FEATURE_OPTS += EXTRA - - def randomize_fuzz_settings(): # a list of the optimizations to run on the wasm global FUZZ_OPTS @@ -169,92 +150,11 @@ print('randomized settings (NaNs, OOB, legalize):', NANS, OOB, LEGALIZE) -def init_important_initial_contents(): - FIXED_IMPORTANT_INITIAL_CONTENTS = [ - # Perenially-important passes - os.path.join('lit', 'passes', 'optimize-instructions.wast'), - os.path.join('passes', 'optimize-instructions_fuzz-exec.wast'), - ] - MANUAL_RECENT_INITIAL_CONTENTS = [ - # Recently-added or modified passes. These can be added to and pruned - # frequently. - os.path.join('lit', 'passes', 'once-reduction.wast'), - os.path.join('passes', 'remove-unused-brs_enable-multivalue.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-bulk-memory.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-ignore-traps.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-gc.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-gc-iit.wast'), - os.path.join('lit', 'passes', 'optimize-instructions-call_ref.wast'), - os.path.join('lit', 'passes', 'inlining_splitting.wast'), - os.path.join('heap-types.wast'), - ] - RECENT_DAYS = 30 - - # Returns the list of test wast/wat files added or modified within the - # RECENT_DAYS number of days counting from the commit time of HEAD - def auto_select_recent_initial_contents(): - # Print 'git log' with changed file status and without commit messages, - # with commits within RECENT_DAYS number of days, counting from the - # commit time of HEAD. The reason we use the commit time of HEAD instead - # of the current system time is to make the results deterministic given - # the Binaryen HEAD commit. - from datetime import datetime, timedelta, timezone - head_ts_str = run(['git', 'log', '-1', '--format=%cd', '--date=raw'], - silent=True).split()[0] - head_dt = datetime.utcfromtimestamp(int(head_ts_str)) - start_dt = head_dt - timedelta(days=RECENT_DAYS) - start_ts = start_dt.replace(tzinfo=timezone.utc).timestamp() - log = run(['git', 'log', '--name-status', '--format=', '--date=raw', '--no-renames', f'--since={start_ts}'], silent=True).splitlines() - # Pick up lines in the form of - # A test/../something.wast - # M test/../something.wast - # (wat extension is also included) - p = re.compile(r'^[AM]\stest' + os.sep + r'(.*\.(wat|wast))$') - matches = [p.match(e) for e in log] - auto_set = set([match.group(1) for match in matches if match]) - auto_set = auto_set.difference(set(FIXED_IMPORTANT_INITIAL_CONTENTS)) - return sorted(list(auto_set)) - - def is_git_repo(): - try: - ret = run(['git', 'rev-parse', '--is-inside-work-tree'], - silent=True, stderr=subprocess.DEVNULL) - return ret == 'true\n' - except subprocess.CalledProcessError: - return False - - if not is_git_repo() and shared.options.auto_initial_contents: - print('Warning: The current directory is not a git repository, so you cannot use "--auto-initial-contents". Using the manually selected contents.\n') - shared.options.auto_initial_contents = False - - print('- Perenially-important initial contents:') - for test in FIXED_IMPORTANT_INITIAL_CONTENTS: - print(' ' + test) - print() - - recent_contents = [] - print('- Recently added or modified initial contents ', end='') - if shared.options.auto_initial_contents: - print(f'(automatically selected: within last {RECENT_DAYS} days):') - recent_contents += auto_select_recent_initial_contents() - else: - print('(manually selected):') - recent_contents = MANUAL_RECENT_INITIAL_CONTENTS - for test in recent_contents: - print(' ' + test) - print() - - # We prompt the user only when there is no seed given. This fuzz_opt.py is - # often used with seed in a script called from wasm-reduce, in which case we - # should not pause for a user input. - if given_seed is None: - ret = input('Do you want to proceed with these initial contents? (Y/n) ').lower() - if ret != 'y' and ret != '': - sys.exit(1) - - initial_contents = FIXED_IMPORTANT_INITIAL_CONTENTS + recent_contents - global IMPORTANT_INITIAL_CONTENTS - IMPORTANT_INITIAL_CONTENTS = [os.path.join(shared.get_test_dir('.'), t) for t in initial_contents] +IMPORTANT_INITIAL_CONTENTS = [ + os.path.join('passes', 'optimize-instructions_all-features.wast'), + os.path.join('passes', 'optimize-instructions_fuzz-exec.wast'), +] +IMPORTANT_INITIAL_CONTENTS = [os.path.join(shared.get_test_dir('.'), t) for t in IMPORTANT_INITIAL_CONTENTS] def pick_initial_contents(): @@ -273,12 +173,6 @@ else: test_name = random.choice(all_tests) print('initial contents:', test_name) - if shared.options.auto_initial_contents: - # when using auto initial contents, we look through the git history to - # find test files. if a test file was renamed or removed then it may - # no longer exist, and we should just skip it. - if not os.path.exists(test_name): - return assert os.path.exists(test_name) # tests that check validation errors are not helpful for us if '.fail.' in test_name: @@ -315,29 +209,12 @@ global FEATURE_OPTS FEATURE_OPTS += [ + # has not been enabled in the fuzzer yet + '--disable-exception-handling', # has not been fuzzed in general yet '--disable-memory64', - # avoid multivalue for now due to bad interactions with gc rtts in - # stacky code. for example, this fails to roundtrip as the tuple code - # ends up creating stacky binary code that needs to spill rtts to locals, - # which is not allowed: - # - # (module - # (type $other (struct)) - # (func $foo (result (rtt $other)) - # (select - # (rtt.canon $other) - # (rtt.canon $other) - # (tuple.extract 1 - # (tuple.make - # (i32.const 0) - # (i32.const 0) - # ) - # ) - # ) - # ) - # ) - '--disable-multivalue', + # has not been fuzzed in general yet + '--disable-gc', # DWARF is incompatible with multivalue atm; it's more important to # fuzz multivalue since we aren't actually fuzzing DWARF here '--strip-dwarf', @@ -345,22 +222,7 @@ # the given wasm may not work with the chosen feature opts. for example, if # we pick atomics.wast but want to run with --disable-atomics, then we'd - # error, so we need to test the wasm. first, make sure it doesn't have a - # features section, as that would enable a feature that we might want to - # be disabled, and our test would not error as we want it to. - if test_name.endswith('.wasm'): - temp_test_name = 'initial.wasm' - try: - run([in_bin('wasm-opt'), test_name, '-all', '--strip-target-features', - '-o', temp_test_name]) - except Exception: - # the input can be invalid if e.g. it is raw data that is used with - # -ttf as fuzzer input - print('(initial contents are not valid wasm, ignoring)') - return - test_name = temp_test_name - - # next, test the wasm. + # error. test the wasm. try: run([in_bin('wasm-opt'), test_name] + FEATURE_OPTS, stderr=subprocess.PIPE, @@ -378,29 +240,18 @@ # Traps are reported as [trap REASON] TRAP_PREFIX = '[trap ' -# Host limits are reported as [host limit REASON] -HOST_LIMIT_PREFIX = '[host limit ' - # --fuzz-exec reports calls as [fuzz-exec] calling foo FUZZ_EXEC_CALL_PREFIX = '[fuzz-exec] calling' # compare two strings, strictly -def compare(x, y, context, verbose=True): +def compare(x, y, context): if x != y and x != IGNORE and y != IGNORE: message = ''.join([a + '\n' for a in difflib.unified_diff(x.splitlines(), y.splitlines(), fromfile='expected', tofile='actual')]) - if verbose: - raise Exception(context + " comparison error, expected to have '%s' == '%s', diff:\n\n%s" % ( - x, y, - message - )) - else: - raise Exception(context + "\nDiff:\n\n%s" % (message)) - - -# converts a possibly-signed integer to an unsigned integer -def unsign(x, bits): - return x & ((1 << bits) - 1) + raise Exception(context + " comparison error, expected to have '%s' == '%s', diff:\n\n%s" % ( + x, y, + message + )) # numbers are "close enough" if they just differ in printing, as different @@ -409,17 +260,6 @@ # handle nan comparisons like -nan:0x7ffff0 vs NaN, ignoring the bits if 'nan' in x.lower() and 'nan' in y.lower(): return True - # if one input is a pair, then it is in fact a 64-bit integer that is - # reported as two 32-bit chunks. convert such 'low high' pairs into a 64-bit - # integer for comparison to the other value - if ' ' in x or ' ' in y: - def to_64_bit(a): - if ' ' not in a: - return unsign(int(a), bits=64) - low, high = a.split(' ') - return unsign(int(low), 32) + (1 << 32) * unsign(int(high), 32) - - return to_64_bit(x) == to_64_bit(y) # float() on the strings will handle many minor differences, like # float('1.0') == float('1') , float('inf') == float('Infinity'), etc. try: @@ -509,31 +349,17 @@ def run_vm(cmd): - def filter_known_issues(output): - known_issues = [ - # can be caused by flatten, ssa, etc. passes - 'local count too large', - # https://github.com/WebAssembly/binaryen/issues/3767 - # note that this text is a little too broad, but the problem is rare - # enough that it's unlikely to hide an unrelated issue - 'found br_if of type', - # all host limitations are arbitrary and may differ between VMs and also - # be affected by optimizations, so ignore them. - HOST_LIMIT_PREFIX, - ] + # ignore some vm assertions, if bugs have already been filed + known_issues = [ + 'local count too large', # ignore this; can be caused by flatten, ssa, etc. passes + ] + try: + return run(cmd) + except subprocess.CalledProcessError: + output = run_unchecked(cmd) for issue in known_issues: if issue in output: return IGNORE - return output - - try: - # some known issues do not cause the entire process to fail - return filter_known_issues(run(cmd)) - except subprocess.CalledProcessError: - # other known issues do make it fail, so re-run without checking for - # success and see if we should ignore it - if filter_known_issues(run_unchecked(cmd)) == IGNORE: - return IGNORE raise @@ -571,10 +397,6 @@ return run_d8_js(in_binaryen('scripts', 'fuzz_shell.js'), [wasm], liftoff=liftoff) -def all_disallowed(features): - return not any(('--enable-' + x) in FEATURE_OPTS for x in features) - - class TestCaseHandler: # how frequent this handler will be run. 1 means always run it, 0.5 means half the # time @@ -690,7 +512,7 @@ if random.random() < 0.5: return False # wasm2c doesn't support most features - return all_disallowed(['exception-handling', 'simd', 'threads', 'bulk-memory', 'nontrapping-float-to-int', 'tail-call', 'sign-ext', 'reference-types', 'multivalue', 'gc']) + return all([x in FEATURE_OPTS for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types', '--disable-multivalue', '--disable-gc']]) def run(self, wasm): run([in_bin('wasm-opt'), wasm, '--emit-wasm2c-wrapper=main.c'] + FEATURE_OPTS) @@ -723,7 +545,6 @@ os.path.join(self.wasm2c_dir, 'wasm-rt-impl.c'), '-I' + self.wasm2c_dir, '-lm', - '-s', 'ENVIRONMENT=shell', '-s', 'ALLOW_MEMORY_GROWTH'] # disable the signal handler: emcc looks like unix, but wasm has # no signals @@ -755,12 +576,8 @@ # NaNs can differ from wasm VMs return not NANS - self.vms = [BinaryenInterpreter(), - D8(), - D8Liftoff(), - D8TurboFan(), - Wasm2C(), - Wasm2C2Wasm()] + self.vms = [BinaryenInterpreter(), D8(), D8Liftoff(), D8TurboFan(), + Wasm2C(), Wasm2C2Wasm()] def handle_pair(self, input, before_wasm, after_wasm, opts): before = self.run_vms(before_wasm) @@ -794,7 +611,7 @@ compare(before[vm], after[vm], 'CompareVMs between before and after: ' + vm.name) def can_run_on_feature_opts(self, feature_opts): - return all_disallowed(['simd', 'multivalue']) + return all([x in feature_opts for x in ['--disable-simd', '--disable-reference-types', '--disable-exception-handling', '--disable-multivalue', '--disable-gc']]) # Check for determinism - the same command must have the same output. @@ -806,14 +623,7 @@ # check for determinism run([in_bin('wasm-opt'), before_wasm, '-o', 'b1.wasm'] + opts) run([in_bin('wasm-opt'), before_wasm, '-o', 'b2.wasm'] + opts) - b1 = open('b1.wasm', 'rb').read() - b2 = open('b2.wasm', 'rb').read() - if (b1 != b2): - run([in_bin('wasm-dis'), 'b1.wasm', '-o', 'b1.wat', TYPE_SYSTEM_FLAG]) - run([in_bin('wasm-dis'), 'b2.wasm', '-o', 'b2.wat', TYPE_SYSTEM_FLAG]) - t1 = open('b1.wat', 'r').read() - t2 = open('b2.wat', 'r').read() - compare(t1, t2, 'Output must be deterministic.', verbose=False) + assert open('b1.wasm', 'rb').read() == open('b2.wasm', 'rb').read(), 'output must be deterministic' class Wasm2JS(TestCaseHandler): @@ -858,7 +668,7 @@ # the trap, which lets us compare at least some results in some cases. # (this is why wasm2js is not in CompareVMs, which does full # comparisons - we need to limit the comparison in a special way here) - interpreter = run_bynterp(before_wasm_temp, ['--fuzz-exec-before']) + interpreter = run([in_bin('wasm-opt'), before_wasm_temp, '--fuzz-exec-before']) if TRAP_PREFIX in interpreter: trap_index = interpreter.index(TRAP_PREFIX) # we can't test this function, which the trap is in the middle of. @@ -939,7 +749,7 @@ # specifically for growth here if INITIAL_CONTENTS: return False - return all_disallowed(['exception-handling', 'simd', 'threads', 'bulk-memory', 'nontrapping-float-to-int', 'tail-call', 'sign-ext', 'reference-types', 'multivalue', 'gc']) + return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-threads', '--disable-bulk-memory', '--disable-nontrapping-float-to-int', '--disable-tail-call', '--disable-sign-ext', '--disable-reference-types', '--disable-multivalue', '--disable-gc']]) class Asyncify(TestCaseHandler): @@ -993,7 +803,7 @@ compare(before, after_asyncify, 'Asyncify (before/after_asyncify)') def can_run_on_feature_opts(self, feature_opts): - return all_disallowed(['exception-handling', 'simd', 'tail-call', 'reference-types', 'multivalue', 'gc']) + return all([x in feature_opts for x in ['--disable-exception-handling', '--disable-simd', '--disable-tail-call', '--disable-reference-types', '--disable-multivalue', '--disable-gc']]) # Check that the text format round-trips without error. @@ -1001,11 +811,7 @@ frequency = 0.05 def handle(self, wasm): - # use name-types because in wasm GC we can end up truncating the default - # names which are very long, causing names to collide and the wast to be - # invalid - # FIXME: run name-types by default during load? - run([in_bin('wasm-opt'), wasm, '--name-types', '-S', '-o', 'a.wast'] + FEATURE_OPTS) + run([in_bin('wasm-dis'), wasm, '-o', 'a.wast']) run([in_bin('wasm-opt'), 'a.wast'] + FEATURE_OPTS) @@ -1016,8 +822,7 @@ CheckDeterminism(), Wasm2JS(), Asyncify(), - # FIXME: Re-enable after https://github.com/WebAssembly/binaryen/issues/3989 - # RoundtripText() + RoundtripText() ] @@ -1028,8 +833,7 @@ wasm2js_tests = shared.get_tests(shared.get_test_dir('wasm2js'), test_suffixes) lld_tests = shared.get_tests(shared.get_test_dir('lld'), test_suffixes) unit_tests = shared.get_tests(shared.get_test_dir(os.path.join('unit', 'input')), test_suffixes) -lit_tests = shared.get_tests(shared.get_test_dir('lit'), test_suffixes, recursive=True) -all_tests = core_tests + passes_tests + spec_tests + wasm2js_tests + lld_tests + unit_tests + lit_tests +all_tests = core_tests + passes_tests + spec_tests + wasm2js_tests + lld_tests + unit_tests # Do one test, given an input file for -ttf and some optimizations to run @@ -1052,7 +856,7 @@ else: # emit the target features section so that reduction can work later, # without needing to specify the features - generate_command = [in_bin('wasm-opt'), random_input, '-ttf', '-o', 'a.wasm'] + FUZZ_OPTS + FEATURE_OPTS + generate_command = [in_bin('wasm-opt'), random_input, '-ttf', '-o', 'a.wasm', '--emit-target-features'] + FUZZ_OPTS + FEATURE_OPTS if INITIAL_CONTENTS: generate_command += ['--initial-fuzz=' + INITIAL_CONTENTS] if PRINT_WATS: @@ -1064,7 +868,6 @@ wasm_size = os.stat('a.wasm').st_size bytes = wasm_size print('pre wasm size:', wasm_size) - update_feature_opts('a.wasm') # create a second wasm for handlers that want to look at pairs. generate_command = [in_bin('wasm-opt'), 'a.wasm', '-o', 'b.wasm'] + opts + FUZZ_OPTS + FEATURE_OPTS @@ -1124,7 +927,6 @@ opt_choices = [ [], ['-O1'], ['-O2'], ['-O3'], ['-O4'], ['-Os'], ['-Oz'], - ["--cfp"], ["--coalesce-locals"], # XXX slow, non-default ["--coalesce-locals-learning"], ["--code-pushing"], @@ -1140,19 +942,12 @@ # ["--fpcast-emu"], # removes indirect call failures as it makes them go through regardless of type ["--inlining"], ["--inlining-optimizing"], - ["--flatten", "--simplify-locals-notee-nostructure", "--local-cse"], - ["--global-refining"], - ["--gto"], - ["--local-cse"], - ["--heap2local"], - ["--remove-unused-names", "--heap2local"], + ["--flatten", "--local-cse"], ["--generate-stack-ir"], ["--licm"], - ["--local-subtyping"], ["--memory-packing"], ["--merge-blocks"], ['--merge-locals'], - ['--once-reduction'], ["--optimize-instructions"], ["--optimize-stack-ir"], ["--generate-stack-ir", "--optimize-stack-ir"], @@ -1169,15 +964,12 @@ ["--flatten", "--rereloop"], ["--roundtrip"], ["--rse"], - ["--signature-pruning"], - ["--signature-refining"], ["--simplify-locals"], ["--simplify-locals-nonesting"], ["--simplify-locals-nostructure"], ["--simplify-locals-notee"], ["--simplify-locals-notee-nostructure"], ["--ssa"], - ["--type-refining"], ["--vacuum"], ] @@ -1192,21 +984,14 @@ if has_flatten: print('avoiding multiple --flatten in a single command, due to exponential overhead') continue - if '--enable-multivalue' in FEATURE_OPTS and '--enable-reference-types' in FEATURE_OPTS: - print('avoiding --flatten due to multivalue + reference types not supporting it (spilling of non-nullable tuples)') - continue - if '--gc' not in FEATURE_OPTS: - print('avoiding --flatten due to GC not supporting it (spilling of RTTs)') + if '--disable-exception-handling' not in FEATURE_OPTS: + print('avoiding --flatten due to exception catching which does not support it yet') continue if INITIAL_CONTENTS and os.path.getsize(INITIAL_CONTENTS) > 2000: print('avoiding --flatten due using a large amount of initial contents, which may blow up') continue else: has_flatten = True - if ('--rereloop' in choice or '--dfo' in choice) and \ - '--enable-exception-handling' in FEATURE_OPTS: - print('avoiding --rereloop or --dfo due to exception-handling not supporting it') - continue flag_groups.append(choice) if len(flag_groups) > 20 or random.random() < 0.3: break @@ -1221,17 +1006,6 @@ ret += ['--optimize-level=' + str(random.randint(0, 3))] if random.random() < 0.5: ret += ['--shrink-level=' + str(random.randint(0, 3))] - # possibly converge. don't do this very often as it can be slow. - if random.random() < 0.05: - ret += ['--converge'] - # possibly inline all the things as much as possible. inlining that much may - # be realistic in some cases (on GC benchmarks it is very helpful), but - # also, inlining so much allows other optimizations to kick in, which - # increases coverage - # (the specific number here doesn't matter, but it is far higher than the - # wasm limitation on function body size which is 128K) - if random.random() < 0.5: - ret += ['-fimfs=99999999'] assert ret.count('--flatten') <= 1 return ret @@ -1247,7 +1021,7 @@ # some features depend on other features, so if a required feature is # disabled, its dependent features need to be disabled as well. IMPLIED_FEATURE_OPTS = { - '--disable-reference-types': ['--disable-gc'] + '--disable-reference-types': ['--disable-exception-handling', '--disable-gc'] } if __name__ == '__main__': @@ -1266,9 +1040,6 @@ else: given_seed = None print('checking infinite random inputs') - - init_important_initial_contents() - seed = time.time() * os.getpid() raw_input_data = 'input.dat' counter = 0 @@ -1358,22 +1129,15 @@ original_wasm = os.path.abspath('original.wasm') shutil.copyfile('a.wasm', original_wasm) # write out a useful reduce.sh - auto_init = '' - if shared.options.auto_initial_contents: - auto_init = '--auto-initial-contents' with open('reduce.sh', 'w') as reduce_sh: reduce_sh.write('''\ # check the input is even a valid wasm file -echo "At least one of the next two values should be 0:" -%(wasm_opt)s %(typesystem)s --detect-features %(temp_wasm)s -echo " " $? -%(wasm_opt)s %(typesystem)s --all-features %(temp_wasm)s -echo " " $? +%(wasm_opt)s --detect-features %(temp_wasm)s +echo "should be 0:" $? # run the command -echo "The following value should be 1:" -./scripts/fuzz_opt.py %(auto_init)s --binaryen-bin %(bin)s %(seed)d %(temp_wasm)s > o 2> e -echo " " $? +./scripts/fuzz_opt.py --binaryen-bin %(bin)s %(seed)d %(temp_wasm)s > o 2> e +echo "should be 1:" $? # # You may want to print out part of "o" or "e", if the output matters and not @@ -1401,10 +1165,8 @@ ''' % {'wasm_opt': in_bin('wasm-opt'), 'bin': shared.options.binaryen_bin, 'seed': seed, - 'auto_init': auto_init, 'original_wasm': original_wasm, 'temp_wasm': os.path.abspath('t.wasm'), - 'typesystem': TYPE_SYSTEM_FLAG, 'reduce_sh': os.path.abspath('reduce.sh')}) print('''\ @@ -1426,24 +1188,16 @@ vvvv -%(wasm_reduce)s %(type_system_flag)s %(original_wasm)s '--command=bash %(reduce_sh)s' -t %(temp_wasm)s -w %(working_wasm)s +%(wasm_reduce)s %(original_wasm)s '--command=bash %(reduce_sh)s' -t %(temp_wasm)s -w %(working_wasm)s ^^^^ |||| -Make sure to verify by eye that the output says something like this: +Make sure to verify by eye that the output says -At least one of the next two values should be 0: - 0 - 1 -The following value should be 1: - 1 - -(If it does not, then one possible issue is that the fuzzer fails to write a -valid binary. If so, you can print the output of the fuzzer's first command -(using -ttf / --translate-to-fuzz) in text form and run the reduction from that, -passing --text to the reducer.) +should be 0: 0 +should be 1: 1 You can also read "%(reduce_sh)s" which has been filled out for you and includes docs and suggestions. @@ -1455,8 +1209,7 @@ 'temp_wasm': os.path.abspath('t.wasm'), 'working_wasm': os.path.abspath('w.wasm'), 'wasm_reduce': in_bin('wasm-reduce'), - 'reduce_sh': os.path.abspath('reduce.sh'), - 'type_system_flag': TYPE_SYSTEM_FLAG}) + 'reduce_sh': os.path.abspath('reduce.sh')}) break if given_seed is not None: break diff -Nru binaryen-108/scripts/gen-s-parser.py binaryen-99/scripts/gen-s-parser.py --- binaryen-108/scripts/gen-s-parser.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/gen-s-parser.py 2021-01-07 20:01:06.000000000 +0000 @@ -281,7 +281,7 @@ ("v128.load", "makeLoad(s, Type::v128, /*isAtomic=*/false)"), ("v128.store", "makeStore(s, Type::v128, /*isAtomic=*/false)"), ("v128.const", "makeConst(s, Type::v128)"), - ("i8x16.shuffle", "makeSIMDShuffle(s)"), + ("v8x16.shuffle", "makeSIMDShuffle(s)"), ("i8x16.splat", "makeUnary(s, UnaryOp::SplatVecI8x16)"), ("i8x16.extract_lane_s", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI8x16, 16)"), ("i8x16.extract_lane_u", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI8x16, 16)"), @@ -333,11 +333,6 @@ ("i32x4.ge_s", "makeBinary(s, BinaryOp::GeSVecI32x4)"), ("i32x4.ge_u", "makeBinary(s, BinaryOp::GeUVecI32x4)"), ("i64x2.eq", "makeBinary(s, BinaryOp::EqVecI64x2)"), - ("i64x2.ne", "makeBinary(s, BinaryOp::NeVecI64x2)"), - ("i64x2.lt_s", "makeBinary(s, BinaryOp::LtSVecI64x2)"), - ("i64x2.gt_s", "makeBinary(s, BinaryOp::GtSVecI64x2)"), - ("i64x2.le_s", "makeBinary(s, BinaryOp::LeSVecI64x2)"), - ("i64x2.ge_s", "makeBinary(s, BinaryOp::GeSVecI64x2)"), ("f32x4.eq", "makeBinary(s, BinaryOp::EqVecF32x4)"), ("f32x4.ne", "makeBinary(s, BinaryOp::NeVecF32x4)"), ("f32x4.lt", "makeBinary(s, BinaryOp::LtVecF32x4)"), @@ -355,30 +350,35 @@ ("v128.or", "makeBinary(s, BinaryOp::OrVec128)"), ("v128.xor", "makeBinary(s, BinaryOp::XorVec128)"), ("v128.andnot", "makeBinary(s, BinaryOp::AndNotVec128)"), - ("v128.any_true", "makeUnary(s, UnaryOp::AnyTrueVec128)"), ("v128.bitselect", "makeSIMDTernary(s, SIMDTernaryOp::Bitselect)"), - ("v128.load8_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load8LaneVec128)"), - ("v128.load16_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load16LaneVec128)"), - ("v128.load32_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load32LaneVec128)"), - ("v128.load64_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load64LaneVec128)"), - ("v128.store8_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store8LaneVec128)"), - ("v128.store16_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store16LaneVec128)"), - ("v128.store32_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store32LaneVec128)"), - ("v128.store64_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store64LaneVec128)"), + ("v8x16.signselect", "makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec8x16)"), + ("v16x8.signselect", "makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec16x8)"), + ("v32x4.signselect", "makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec32x4)"), + ("v64x2.signselect", "makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec64x2)"), + ("v128.load8_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec8x16)"), + ("v128.load16_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec16x8)"), + ("v128.load32_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec32x4)"), + ("v128.load64_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec64x2)"), + ("v128.store8_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec8x16)"), + ("v128.store16_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec16x8)"), + ("v128.store32_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec32x4)"), + ("v128.store64_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec64x2)"), ("i8x16.popcnt", "makeUnary(s, UnaryOp::PopcntVecI8x16)"), ("i8x16.abs", "makeUnary(s, UnaryOp::AbsVecI8x16)"), ("i8x16.neg", "makeUnary(s, UnaryOp::NegVecI8x16)"), + ("i8x16.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI8x16)"), ("i8x16.all_true", "makeUnary(s, UnaryOp::AllTrueVecI8x16)"), ("i8x16.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI8x16)"), ("i8x16.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI8x16)"), ("i8x16.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI8x16)"), ("i8x16.shr_u", "makeSIMDShift(s, SIMDShiftOp::ShrUVecI8x16)"), ("i8x16.add", "makeBinary(s, BinaryOp::AddVecI8x16)"), - ("i8x16.add_sat_s", "makeBinary(s, BinaryOp::AddSatSVecI8x16)"), - ("i8x16.add_sat_u", "makeBinary(s, BinaryOp::AddSatUVecI8x16)"), + ("i8x16.add_saturate_s", "makeBinary(s, BinaryOp::AddSatSVecI8x16)"), + ("i8x16.add_saturate_u", "makeBinary(s, BinaryOp::AddSatUVecI8x16)"), ("i8x16.sub", "makeBinary(s, BinaryOp::SubVecI8x16)"), - ("i8x16.sub_sat_s", "makeBinary(s, BinaryOp::SubSatSVecI8x16)"), - ("i8x16.sub_sat_u", "makeBinary(s, BinaryOp::SubSatUVecI8x16)"), + ("i8x16.sub_saturate_s", "makeBinary(s, BinaryOp::SubSatSVecI8x16)"), + ("i8x16.sub_saturate_u", "makeBinary(s, BinaryOp::SubSatUVecI8x16)"), + ("i8x16.mul", "makeBinary(s, BinaryOp::MulVecI8x16)"), ("i8x16.min_s", "makeBinary(s, BinaryOp::MinSVecI8x16)"), ("i8x16.min_u", "makeBinary(s, BinaryOp::MinUVecI8x16)"), ("i8x16.max_s", "makeBinary(s, BinaryOp::MaxSVecI8x16)"), @@ -386,17 +386,18 @@ ("i8x16.avgr_u", "makeBinary(s, BinaryOp::AvgrUVecI8x16)"), ("i16x8.abs", "makeUnary(s, UnaryOp::AbsVecI16x8)"), ("i16x8.neg", "makeUnary(s, UnaryOp::NegVecI16x8)"), + ("i16x8.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI16x8)"), ("i16x8.all_true", "makeUnary(s, UnaryOp::AllTrueVecI16x8)"), ("i16x8.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI16x8)"), ("i16x8.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI16x8)"), ("i16x8.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI16x8)"), ("i16x8.shr_u", "makeSIMDShift(s, SIMDShiftOp::ShrUVecI16x8)"), ("i16x8.add", "makeBinary(s, BinaryOp::AddVecI16x8)"), - ("i16x8.add_sat_s", "makeBinary(s, BinaryOp::AddSatSVecI16x8)"), - ("i16x8.add_sat_u", "makeBinary(s, BinaryOp::AddSatUVecI16x8)"), + ("i16x8.add_saturate_s", "makeBinary(s, BinaryOp::AddSatSVecI16x8)"), + ("i16x8.add_saturate_u", "makeBinary(s, BinaryOp::AddSatUVecI16x8)"), ("i16x8.sub", "makeBinary(s, BinaryOp::SubVecI16x8)"), - ("i16x8.sub_sat_s", "makeBinary(s, BinaryOp::SubSatSVecI16x8)"), - ("i16x8.sub_sat_u", "makeBinary(s, BinaryOp::SubSatUVecI16x8)"), + ("i16x8.sub_saturate_s", "makeBinary(s, BinaryOp::SubSatSVecI16x8)"), + ("i16x8.sub_saturate_u", "makeBinary(s, BinaryOp::SubSatUVecI16x8)"), ("i16x8.mul", "makeBinary(s, BinaryOp::MulVecI16x8)"), ("i16x8.min_s", "makeBinary(s, BinaryOp::MinSVecI16x8)"), ("i16x8.min_u", "makeBinary(s, BinaryOp::MinUVecI16x8)"), @@ -410,6 +411,7 @@ ("i16x8.extmul_high_i8x16_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI16x8)"), ("i32x4.abs", "makeUnary(s, UnaryOp::AbsVecI32x4)"), ("i32x4.neg", "makeUnary(s, UnaryOp::NegVecI32x4)"), + ("i32x4.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI32x4)"), ("i32x4.all_true", "makeUnary(s, UnaryOp::AllTrueVecI32x4)"), ("i32x4.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI32x4)"), ("i32x4.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI32x4)"), @@ -427,9 +429,7 @@ ("i32x4.extmul_high_i16x8_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI32x4)"), ("i32x4.extmul_low_i16x8_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI32x4)"), ("i32x4.extmul_high_i16x8_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI32x4)"), - ("i64x2.abs", "makeUnary(s, UnaryOp::AbsVecI64x2)"), ("i64x2.neg", "makeUnary(s, UnaryOp::NegVecI64x2)"), - ("i64x2.all_true", "makeUnary(s, UnaryOp::AllTrueVecI64x2)"), ("i64x2.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI64x2)"), ("i64x2.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI64x2)"), ("i64x2.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI64x2)"), @@ -444,6 +444,8 @@ ("f32x4.abs", "makeUnary(s, UnaryOp::AbsVecF32x4)"), ("f32x4.neg", "makeUnary(s, UnaryOp::NegVecF32x4)"), ("f32x4.sqrt", "makeUnary(s, UnaryOp::SqrtVecF32x4)"), + ("f32x4.qfma", "makeSIMDTernary(s, SIMDTernaryOp::QFMAF32x4)"), + ("f32x4.qfms", "makeSIMDTernary(s, SIMDTernaryOp::QFMSF32x4)"), ("f32x4.add", "makeBinary(s, BinaryOp::AddVecF32x4)"), ("f32x4.sub", "makeBinary(s, BinaryOp::SubVecF32x4)"), ("f32x4.mul", "makeBinary(s, BinaryOp::MulVecF32x4)"), @@ -459,6 +461,8 @@ ("f64x2.abs", "makeUnary(s, UnaryOp::AbsVecF64x2)"), ("f64x2.neg", "makeUnary(s, UnaryOp::NegVecF64x2)"), ("f64x2.sqrt", "makeUnary(s, UnaryOp::SqrtVecF64x2)"), + ("f64x2.qfma", "makeSIMDTernary(s, SIMDTernaryOp::QFMAF64x2)"), + ("f64x2.qfms", "makeSIMDTernary(s, SIMDTernaryOp::QFMSF64x2)"), ("f64x2.add", "makeBinary(s, BinaryOp::AddVecF64x2)"), ("f64x2.sub", "makeBinary(s, BinaryOp::SubVecF64x2)"), ("f64x2.mul", "makeBinary(s, BinaryOp::MulVecF64x2)"), @@ -473,91 +477,58 @@ ("f64x2.nearest", "makeUnary(s, UnaryOp::NearestVecF64x2)"), ("i32x4.trunc_sat_f32x4_s", "makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4)"), ("i32x4.trunc_sat_f32x4_u", "makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4)"), + ("i64x2.trunc_sat_f64x2_s", "makeUnary(s, UnaryOp::TruncSatSVecF64x2ToVecI64x2)"), + ("i64x2.trunc_sat_f64x2_u", "makeUnary(s, UnaryOp::TruncSatUVecF64x2ToVecI64x2)"), ("f32x4.convert_i32x4_s", "makeUnary(s, UnaryOp::ConvertSVecI32x4ToVecF32x4)"), ("f32x4.convert_i32x4_u", "makeUnary(s, UnaryOp::ConvertUVecI32x4ToVecF32x4)"), - ("v128.load8_splat", "makeSIMDLoad(s, SIMDLoadOp::Load8SplatVec128)"), - ("v128.load16_splat", "makeSIMDLoad(s, SIMDLoadOp::Load16SplatVec128)"), - ("v128.load32_splat", "makeSIMDLoad(s, SIMDLoadOp::Load32SplatVec128)"), - ("v128.load64_splat", "makeSIMDLoad(s, SIMDLoadOp::Load64SplatVec128)"), - ("v128.load8x8_s", "makeSIMDLoad(s, SIMDLoadOp::Load8x8SVec128)"), - ("v128.load8x8_u", "makeSIMDLoad(s, SIMDLoadOp::Load8x8UVec128)"), - ("v128.load16x4_s", "makeSIMDLoad(s, SIMDLoadOp::Load16x4SVec128)"), - ("v128.load16x4_u", "makeSIMDLoad(s, SIMDLoadOp::Load16x4UVec128)"), - ("v128.load32x2_s", "makeSIMDLoad(s, SIMDLoadOp::Load32x2SVec128)"), - ("v128.load32x2_u", "makeSIMDLoad(s, SIMDLoadOp::Load32x2UVec128)"), - ("v128.load32_zero", "makeSIMDLoad(s, SIMDLoadOp::Load32ZeroVec128)"), - ("v128.load64_zero", "makeSIMDLoad(s, SIMDLoadOp::Load64ZeroVec128)"), + ("f64x2.convert_i64x2_s", "makeUnary(s, UnaryOp::ConvertSVecI64x2ToVecF64x2)"), + ("f64x2.convert_i64x2_u", "makeUnary(s, UnaryOp::ConvertUVecI64x2ToVecF64x2)"), + ("v8x16.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec8x16)"), + ("v16x8.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec16x8)"), + ("v32x4.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec32x4)"), + ("v64x2.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec64x2)"), + ("i16x8.load8x8_s", "makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec8x8ToVecI16x8)"), + ("i16x8.load8x8_u", "makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec8x8ToVecI16x8)"), + ("i32x4.load16x4_s", "makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec16x4ToVecI32x4)"), + ("i32x4.load16x4_u", "makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec16x4ToVecI32x4)"), + ("i64x2.load32x2_s", "makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec32x2ToVecI64x2)"), + ("i64x2.load32x2_u", "makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec32x2ToVecI64x2)"), + ("v128.load32_zero", "makeSIMDLoad(s, SIMDLoadOp::Load32Zero)"), + ("v128.load64_zero", "makeSIMDLoad(s, SIMDLoadOp::Load64Zero)"), ("i8x16.narrow_i16x8_s", "makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16)"), ("i8x16.narrow_i16x8_u", "makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16)"), ("i16x8.narrow_i32x4_s", "makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8)"), ("i16x8.narrow_i32x4_u", "makeBinary(s, BinaryOp::NarrowUVecI32x4ToVecI16x8)"), - ("i16x8.extend_low_i8x16_s", "makeUnary(s, UnaryOp::ExtendLowSVecI8x16ToVecI16x8)"), - ("i16x8.extend_high_i8x16_s", "makeUnary(s, UnaryOp::ExtendHighSVecI8x16ToVecI16x8)"), - ("i16x8.extend_low_i8x16_u", "makeUnary(s, UnaryOp::ExtendLowUVecI8x16ToVecI16x8)"), - ("i16x8.extend_high_i8x16_u", "makeUnary(s, UnaryOp::ExtendHighUVecI8x16ToVecI16x8)"), - ("i32x4.extend_low_i16x8_s", "makeUnary(s, UnaryOp::ExtendLowSVecI16x8ToVecI32x4)"), - ("i32x4.extend_high_i16x8_s", "makeUnary(s, UnaryOp::ExtendHighSVecI16x8ToVecI32x4)"), - ("i32x4.extend_low_i16x8_u", "makeUnary(s, UnaryOp::ExtendLowUVecI16x8ToVecI32x4)"), - ("i32x4.extend_high_i16x8_u", "makeUnary(s, UnaryOp::ExtendHighUVecI16x8ToVecI32x4)"), - ("i64x2.extend_low_i32x4_s", "makeUnary(s, UnaryOp::ExtendLowSVecI32x4ToVecI64x2)"), - ("i64x2.extend_high_i32x4_s", "makeUnary(s, UnaryOp::ExtendHighSVecI32x4ToVecI64x2)"), - ("i64x2.extend_low_i32x4_u", "makeUnary(s, UnaryOp::ExtendLowUVecI32x4ToVecI64x2)"), - ("i64x2.extend_high_i32x4_u", "makeUnary(s, UnaryOp::ExtendHighUVecI32x4ToVecI64x2)"), - ("i8x16.swizzle", "makeBinary(s, BinaryOp::SwizzleVecI8x16)"), + ("i16x8.widen_low_i8x16_s", "makeUnary(s, UnaryOp::WidenLowSVecI8x16ToVecI16x8)"), + ("i16x8.widen_high_i8x16_s", "makeUnary(s, UnaryOp::WidenHighSVecI8x16ToVecI16x8)"), + ("i16x8.widen_low_i8x16_u", "makeUnary(s, UnaryOp::WidenLowUVecI8x16ToVecI16x8)"), + ("i16x8.widen_high_i8x16_u", "makeUnary(s, UnaryOp::WidenHighUVecI8x16ToVecI16x8)"), + ("i32x4.widen_low_i16x8_s", "makeUnary(s, UnaryOp::WidenLowSVecI16x8ToVecI32x4)"), + ("i32x4.widen_high_i16x8_s", "makeUnary(s, UnaryOp::WidenHighSVecI16x8ToVecI32x4)"), + ("i32x4.widen_low_i16x8_u", "makeUnary(s, UnaryOp::WidenLowUVecI16x8ToVecI32x4)"), + ("i32x4.widen_high_i16x8_u", "makeUnary(s, UnaryOp::WidenHighUVecI16x8ToVecI32x4)"), + ("i64x2.widen_low_i32x4_s", "makeUnary(s, UnaryOp::WidenLowSVecI32x4ToVecI64x2)"), + ("i64x2.widen_high_i32x4_s", "makeUnary(s, UnaryOp::WidenHighSVecI32x4ToVecI64x2)"), + ("i64x2.widen_low_i32x4_u", "makeUnary(s, UnaryOp::WidenLowUVecI32x4ToVecI64x2)"), + ("i64x2.widen_high_i32x4_u", "makeUnary(s, UnaryOp::WidenHighUVecI32x4ToVecI64x2)"), + ("v8x16.swizzle", "makeBinary(s, BinaryOp::SwizzleVec8x16)"), ("i16x8.extadd_pairwise_i8x16_s", "makeUnary(s, UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8)"), ("i16x8.extadd_pairwise_i8x16_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8)"), ("i32x4.extadd_pairwise_i16x8_s", "makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4)"), ("i32x4.extadd_pairwise_i16x8_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4)"), - ("f64x2.convert_low_i32x4_s", "makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2)"), - ("f64x2.convert_low_i32x4_u", "makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2)"), - ("i32x4.trunc_sat_f64x2_s_zero", "makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4)"), - ("i32x4.trunc_sat_f64x2_u_zero", "makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4)"), - ("f32x4.demote_f64x2_zero", "makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4)"), - ("f64x2.promote_low_f32x4", "makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2)"), - - # relaxed SIMD ops - ("i8x16.relaxed_swizzle", "makeBinary(s, BinaryOp::RelaxedSwizzleVecI8x16)"), - ("i32x4.relaxed_trunc_f32x4_s", "makeUnary(s, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4)"), - ("i32x4.relaxed_trunc_f32x4_u", "makeUnary(s, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4)"), - ("i32x4.relaxed_trunc_f64x2_s_zero", "makeUnary(s, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4)"), - ("i32x4.relaxed_trunc_f64x2_u_zero", "makeUnary(s, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4)"), - ("f32x4.relaxed_fma", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF32x4)"), - ("f32x4.relaxed_fms", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF32x4)"), - ("f64x2.relaxed_fma", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF64x2)"), - ("f64x2.relaxed_fms", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF64x2)"), - ("i8x16.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI8x16)"), - ("i16x8.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI16x8)"), - ("i32x4.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI32x4)"), - ("i64x2.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI64x2)"), - ("f32x4.relaxed_min", "makeBinary(s, BinaryOp::RelaxedMinVecF32x4)"), - ("f32x4.relaxed_max", "makeBinary(s, BinaryOp::RelaxedMaxVecF32x4)"), - ("f64x2.relaxed_min", "makeBinary(s, BinaryOp::RelaxedMinVecF64x2)"), - ("f64x2.relaxed_max", "makeBinary(s, BinaryOp::RelaxedMaxVecF64x2)"), - ("i16x8.relaxed_q15mulr_s", "makeBinary(s, BinaryOp::RelaxedQ15MulrSVecI16x8)"), - ("i16x8.dot_i8x16_i7x16_s", "makeBinary(s, BinaryOp::DotI8x16I7x16SToVecI16x8)"), - ("i16x8.dot_i8x16_i7x16_u", "makeBinary(s, BinaryOp::DotI8x16I7x16UToVecI16x8)"), - ("i32x4.dot_i8x16_i7x16_add_s", "makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4)"), - ("i32x4.dot_i8x16_i7x16_add_u", "makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddUToVecI32x4)"), - + # prefetch instructions + ("prefetch.t", "makePrefetch(s, PrefetchOp::PrefetchTemporal)"), + ("prefetch.nt", "makePrefetch(s, PrefetchOp::PrefetchNontemporal)"), # reference types instructions + # TODO Add table instructions ("ref.null", "makeRefNull(s)"), - ("ref.is_null", "makeRefIs(s, RefIsNull)"), + ("ref.is_null", "makeRefIsNull(s)"), ("ref.func", "makeRefFunc(s)"), - ("ref.eq", "makeRefEq(s)"), - # table instructions - ("table.get", "makeTableGet(s)"), - ("table.set", "makeTableSet(s)"), - ("table.size", "makeTableSize(s)"), - ("table.grow", "makeTableGrow(s)"), - # TODO: - # table.init - # table.fill - # table.copy - # # exception handling instructions ("try", "makeTry(s)"), ("throw", "makeThrow(s)"), ("rethrow", "makeRethrow(s)"), + ("br_on_exn", "makeBrOnExn(s)"), # Multivalue pseudoinstructions ("tuple.make", "makeTupleMake(s)"), ("tuple.extract", "makeTupleExtract(s)"), @@ -566,56 +537,28 @@ ("call_ref", "makeCallRef(s, /*isReturn=*/false)"), ("return_call_ref", "makeCallRef(s, /*isReturn=*/true)"), # GC + ("ref.eq", "makeRefEq(s)"), ("i31.new", "makeI31New(s)"), ("i31.get_s", "makeI31Get(s, true)"), ("i31.get_u", "makeI31Get(s, false)"), ("ref.test", "makeRefTest(s)"), - ("ref.test_static", "makeRefTestStatic(s)"), ("ref.cast", "makeRefCast(s)"), - ("ref.cast_static", "makeRefCastStatic(s)"), - ("ref.cast_nop_static", "makeRefCastNopStatic(s)"), - ("br_on_null", "makeBrOn(s, BrOnNull)"), - ("br_on_non_null", "makeBrOn(s, BrOnNonNull)"), - ("br_on_cast", "makeBrOn(s, BrOnCast)"), - ("br_on_cast_static", "makeBrOnStatic(s, BrOnCast)"), - ("br_on_cast_fail", "makeBrOn(s, BrOnCastFail)"), - ("br_on_cast_static_fail", "makeBrOnStatic(s, BrOnCastFail)"), - ("br_on_func", "makeBrOn(s, BrOnFunc)"), - ("br_on_non_func", "makeBrOn(s, BrOnNonFunc)"), - ("br_on_data", "makeBrOn(s, BrOnData)"), - ("br_on_non_data", "makeBrOn(s, BrOnNonData)"), - ("br_on_i31", "makeBrOn(s, BrOnI31)"), - ("br_on_non_i31", "makeBrOn(s, BrOnNonI31)"), + ("br_on_cast", "makeBrOnCast(s)"), ("rtt.canon", "makeRttCanon(s)"), ("rtt.sub", "makeRttSub(s)"), - ("rtt.fresh_sub", "makeRttFreshSub(s)"), ("struct.new_with_rtt", "makeStructNew(s, false)"), ("struct.new_default_with_rtt", "makeStructNew(s, true)"), - ("struct.new", "makeStructNewStatic(s, false)"), - ("struct.new_default", "makeStructNewStatic(s, true)"), ("struct.get", "makeStructGet(s)"), ("struct.get_s", "makeStructGet(s, true)"), ("struct.get_u", "makeStructGet(s, false)"), ("struct.set", "makeStructSet(s)"), ("array.new_with_rtt", "makeArrayNew(s, false)"), ("array.new_default_with_rtt", "makeArrayNew(s, true)"), - ("array.new", "makeArrayNewStatic(s, false)"), - ("array.new_default", "makeArrayNewStatic(s, true)"), - ("array.init", "makeArrayInit(s)"), - ("array.init_static", "makeArrayInitStatic(s)"), - ("array.get", "makeArrayGet(s)"), - ("array.get_s", "makeArrayGet(s, true)"), - ("array.get_u", "makeArrayGet(s, false)"), - ("array.set", "makeArraySet(s)"), - ("array.len", "makeArrayLen(s)"), - ("array.copy", "makeArrayCopy(s)"), - ("ref.is_func", "makeRefIs(s, RefIsFunc)"), - ("ref.is_data", "makeRefIs(s, RefIsData)"), - ("ref.is_i31", "makeRefIs(s, RefIsI31)"), - ("ref.as_non_null", "makeRefAs(s, RefAsNonNull)"), - ("ref.as_func", "makeRefAs(s, RefAsFunc)"), - ("ref.as_data", "makeRefAs(s, RefAsData)"), - ("ref.as_i31", "makeRefAs(s, RefAsI31)"), + ("array.get", "makeArrayGet(s)"), + ("array.get_s", "makeArrayGet(s, true)"), + ("array.get_u", "makeArrayGet(s, false)"), + ("array.set", "makeArraySet(s)"), + ("array.len", "makeArrayLen(s)") ] diff -Nru binaryen-108/scripts/port_passes_tests_to_lit.py binaryen-99/scripts/port_passes_tests_to_lit.py --- binaryen-108/scripts/port_passes_tests_to_lit.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/port_passes_tests_to_lit.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2021 WebAssembly Community Group participants -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Automatically port legacy passes tests to be lit tests -""" - -import argparse -import glob -import os -import subprocess -import sys - - -script_dir = os.path.dirname(__file__) -test_dir = os.path.join(os.path.dirname(script_dir), 'test') - - -def warn(msg): - print(f'WARNING: {msg}', file=sys.stderr) - - -def port_test(args, test): - name = os.path.basename(test) - base = name.replace('.wast', '') - print('..', name) - - if not test.endswith('.wast'): - warn('Skipping because only .wast files are supported') - return - - dest = os.path.join(test_dir, 'lit', 'passes', name) - if not args.force and os.path.exists(dest): - warn('Skipping because destination file already exist') - return - - joined_passes = base - passes_file = os.path.join(test_dir, 'passes', base + '.passes') - if os.path.exists(passes_file): - with open(passes_file) as f: - joined_passes = f.read().strip() - - if 'translate-to-fuzz' in joined_passes or 'dwarf' in joined_passes: - warn('Skipping due to Windows issues') - return - - for bad in ['noprint', 'metrics', 'fuzz', 'print', 'emit', 'dump']: - if bad in joined_passes: - warn('Skipping due to nonstandard output') - return - - passes = joined_passes.split('_') - opts = [('--' + p if not p.startswith('O') and p != 'g' else '-' + p) - for p in passes] - - run_line = (f';; RUN: foreach %s %t wasm-opt {" ".join(opts)} -S -o -' - ' | filecheck %s') - - notice = (f';; NOTE: This test was ported using port_test.py and could be' - ' cleaned up.') - - with open(test, 'r') as src_file: - with open(dest, 'w') as dest_file: - print(notice, file=dest_file) - print('', file=dest_file) - print(run_line, file=dest_file) - print('', file=dest_file) - print(src_file.read(), file=dest_file, end='') - - update_script = os.path.join(script_dir, 'update_lit_checks.py') - subprocess.run([sys.executable, update_script, '-f', '--all-items', dest]) - - if not args.no_delete: - for f in glob.glob(test.replace('.wast', '.*')): - # Do not delete binary tests with the same name - if f.endswith('.wasm') or f.endswith('.bin.txt'): - continue - os.remove(f) - if args.git_add: - subprocess.run(['git', 'add', f]) - - if args.git_add: - subprocess.run(['git', 'add', dest]) - - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('-f', '--force', action='store_true', - help='Overwrite existing lit tests') - parser.add_argument('--no-delete', action='store_true', - help='Do not remove the old tests') - parser.add_argument('--git-add', action='store_true', - help='Stage changes') - parser.add_argument('tests', nargs='+', help='The test files to port') - args = parser.parse_args() - - for pattern in args.tests: - for test in glob.glob(pattern, recursive=True): - port_test(args, test) - - -if __name__ == '__main__': - main() diff -Nru binaryen-108/scripts/test/binaryenjs.py binaryen-99/scripts/test/binaryenjs.py --- binaryen-108/scripts/test/binaryenjs.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/test/binaryenjs.py 2021-01-07 20:01:06.000000000 +0000 @@ -33,7 +33,7 @@ if not s.endswith('.js'): continue print(s) - f = open('a.mjs', 'w') + f = open('a.js', 'w') # avoid stdout/stderr ordering issues in some js shells - use just stdout f.write(''' console.warn = console.error = console.log; @@ -45,7 +45,8 @@ f.write(support.js_test_wrap().replace('%TEST%', test_src)) f.close() - def test(cmd): + def test(engine): + cmd = [engine, 'a.js'] if 'fatal' not in s: out = support.run_command(cmd, stderr=subprocess.STDOUT) else: @@ -57,10 +58,10 @@ # run in all possible shells if shared.MOZJS: - test([shared.MOZJS, '-m', 'a.mjs']) + test(shared.MOZJS) if shared.NODEJS: if node_has_wasm or 'WebAssembly.' not in test_src: - test([shared.NODEJS, 'a.mjs']) + test(shared.NODEJS) else: print('Skipping ' + test_path + ' because WebAssembly might not be supported') @@ -79,17 +80,13 @@ for s in shared.get_tests(shared.get_test_dir('binaryen.js'), ['.js']): basename = os.path.basename(s) print(basename) - f = open('a.mjs', 'w') - # avoid stdout/stderr ordering issues in some js shells - use just stdout - f.write(''' - console.warn = console.error = console.log; - ''') + f = open('a.js', 'w') f.write(open(shared.BINARYEN_JS).read()) test_src = open(s).read() f.write(support.js_test_wrap().replace('%TEST%', test_src)) f.close() - - def update(cmd): + if shared.MOZJS or node_has_wasm or 'WebAssembly.' not in test_src: + cmd = [shared.MOZJS or shared.NODEJS, 'a.js'] if 'fatal' not in basename: out = support.run_command(cmd, stderr=subprocess.STDOUT) else: @@ -97,12 +94,6 @@ out = support.run_command(cmd, stderr=subprocess.STDOUT, expected_status=None) with open(s + '.txt', 'w') as o: o.write(out) - - # run in available shell - if shared.MOZJS: - update([shared.MOZJS, '-m', 'a.mjs']) - elif node_has_wasm or 'WebAssembly.' not in test_src: - update([shared.NODEJS, 'a.mjs']) else: print('Skipping ' + basename + ' because WebAssembly might not be supported') diff -Nru binaryen-108/scripts/test/generate_lld_tests.py binaryen-99/scripts/test/generate_lld_tests.py --- binaryen-108/scripts/test/generate_lld_tests.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/test/generate_lld_tests.py 2021-01-07 20:01:06.000000000 +0000 @@ -67,8 +67,6 @@ obj_path, '-o', wasm_path, '--allow-undefined', '--export', '__wasm_call_ctors', - '--export', '__start_em_asm', - '--export', '__stop_em_asm', '--global-base=568', ] # We had a regression where this test only worked if debug names diff -Nru binaryen-108/scripts/test/lld.py binaryen-99/scripts/test/lld.py --- binaryen-108/scripts/test/lld.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/test/lld.py 2021-01-07 20:01:06.000000000 +0000 @@ -26,8 +26,6 @@ ret += ['--side-module'] if 'standalone-wasm' in filename: ret += ['--standalone-wasm'] - if 'no-emit-metadata' in filename: - ret += ['--no-emit-metadata'] return ret @@ -59,7 +57,7 @@ actual = support.run_command(cmd) shared.fail_if_not_identical_to_file(actual, expected_file) - if ext == '.out' and '--no-emit-metadata' not in cmd: + if ext == '.out': start = actual.find('--BEGIN METADATA --\n') end = actual.find('-- END METADATA --\n') if start == -1 or end == -1: diff -Nru binaryen-108/scripts/test/shared.py binaryen-99/scripts/test/shared.py --- binaryen-108/scripts/test/shared.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/test/shared.py 2021-01-07 20:01:06.000000000 +0000 @@ -25,7 +25,7 @@ # The C++ standard whose features are required to build Binaryen. # Keep in sync with CMakeLists.txt CXX_STANDARD -cxx_standard = 17 +cxx_standard = 14 def parse_args(args): @@ -92,14 +92,6 @@ '--filter', dest='test_name_filter', default='', help=('Specifies a filter. Only tests whose paths contains this ' 'substring will be run')) - # This option is only for fuzz_opt.py - # TODO Allow each script to inherit the default set of options and add its - # own custom options on top of that - parser.add_argument( - '--auto-initial-contents', dest='auto_initial_contents', - action='store_true', default=False, - help='Select important initial contents automaticaly in fuzzer. ' - 'Default: disabled.') return parser.parse_args(args) @@ -207,6 +199,7 @@ WASM_OPT = [os.path.join(options.binaryen_bin, 'wasm-opt')] WASM_AS = [os.path.join(options.binaryen_bin, 'wasm-as')] WASM_DIS = [os.path.join(options.binaryen_bin, 'wasm-dis')] +ASM2WASM = [os.path.join(options.binaryen_bin, 'asm2wasm')] WASM2JS = [os.path.join(options.binaryen_bin, 'wasm2js')] WASM_CTOR_EVAL = [os.path.join(options.binaryen_bin, 'wasm-ctor-eval')] WASM_SHELL = [os.path.join(options.binaryen_bin, 'wasm-shell')] @@ -231,6 +224,7 @@ WASM_OPT = wrap_with_valgrind(WASM_OPT) WASM_AS = wrap_with_valgrind(WASM_AS) WASM_DIS = wrap_with_valgrind(WASM_DIS) + ASM2WASM = wrap_with_valgrind(ASM2WASM) WASM_SHELL = wrap_with_valgrind(WASM_SHELL) @@ -258,10 +252,10 @@ V8_OPTS = [ '--wasm-staging', '--experimental-wasm-eh', + '--experimental-wasm-simd', + '--experimental-wasm-reftypes', '--experimental-wasm-compilation-hints', - '--experimental-wasm-gc', - '--experimental-wasm-typed-funcref', - '--experimental-wasm-memory64' + '--experimental-wasm-return-call' ] # external tools @@ -372,16 +366,15 @@ return os.path.join(options.binaryen_test, name) -def get_tests(test_dir, extensions=[], recursive=False): +def get_tests(test_dir, extensions=[]): """Returns the list of test files in a given directory. 'extensions' is a list of file extensions. If 'extensions' is empty, returns all files. """ tests = [] - star = '**/*' if recursive else '*' if not extensions: - tests += glob.glob(os.path.join(test_dir, star), recursive=True) + tests += glob.glob(os.path.join(test_dir, '*')) for ext in extensions: - tests += glob.glob(os.path.join(test_dir, star + ext), recursive=True) + tests += glob.glob(os.path.join(test_dir, '*' + ext)) if options.test_name_filter: tests = fnmatch.filter(tests, options.test_name_filter) return sorted(tests) @@ -430,6 +423,7 @@ 'utf8-invalid-encoding.wast', # 'register' command + 'imports.wast', 'linking.wast', # Misc. unsupported constructs @@ -471,7 +465,7 @@ subprocess.check_call(cmd, stdout=subprocess.PIPE) assert os.path.exists('a.wasm') - cmd = WASM_DIS + ['a.wasm', '-o', 'ab.wast', '-all'] + cmd = WASM_DIS + ['a.wasm', '-o', 'ab.wast'] print(' ', ' '.join(cmd)) if os.path.exists('ab.wast'): os.unlink('ab.wast') @@ -497,8 +491,19 @@ cmd = WASM_OPT + [wast, '--print-minified', '-all'] print(' ', ' '.join(cmd)) subprocess.check_call(cmd, stdout=open('a.wast', 'w'), stderr=subprocess.PIPE) - subprocess.check_call(WASM_OPT + ['a.wast', '-all'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) + assert os.path.exists('a.wast') + subprocess.check_call(WASM_OPT + ['a.wast', '--print-minified', '-all'], + stdout=open('b.wast', 'w'), stderr=subprocess.PIPE) + assert os.path.exists('b.wast') + if verify_final_result: + expected = open('a.wast').read() + actual = open('b.wast').read() + if actual != expected: + fail(actual, expected) + if os.path.exists('a.wast'): + os.unlink('a.wast') + if os.path.exists('b.wast'): + os.unlink('b.wast') # run a check with BINARYEN_PASS_DEBUG set, to do full validation diff -Nru binaryen-108/scripts/test/support.py binaryen-99/scripts/test/support.py --- binaryen-108/scripts/test/support.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/test/support.py 2021-01-07 20:01:06.000000000 +0000 @@ -145,7 +145,7 @@ ret += [(chunk, [])] elif chunk.startswith('(assert_invalid'): continue - elif chunk.startswith(('(assert', '(invoke', '(register')): + elif chunk.startswith(('(assert', '(invoke')): # ret may be empty if there are some asserts before the first # module. in that case these are asserts *without* a module, which # are valid (they may check something that doesn't refer to a module @@ -199,9 +199,8 @@ # common wrapper code for JS tests, waiting for binaryen.js to become ready # and providing common utility used by all tests: return ''' - (async function __in_test_code__() { - var binaryen = await Binaryen() + binaryen.ready.then(function() { function assert(x) { if (!x) throw Error('Test assertion failed'); } %TEST% - })(); + }); ''' diff -Nru binaryen-108/scripts/test/wasm_opt.py binaryen-99/scripts/test/wasm_opt.py --- binaryen-108/scripts/test/wasm_opt.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/test/wasm_opt.py 2021-01-07 20:01:06.000000000 +0000 @@ -74,8 +74,7 @@ # also check pass-debug mode def check(): - # ignore stderr, as the pass-debug output is very verbose in CI - pass_debug = support.run_command(cmd, stderr=subprocess.PIPE) + pass_debug = support.run_command(cmd) shared.fail_if_not_identical(curr, pass_debug) shared.with_pass_debug(check) @@ -226,7 +225,7 @@ subprocess.check_call(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) assert os.path.exists('a.wasm') - cmd = shared.WASM_DIS + ['a.wasm', '-o', 'a.wast', '-all'] + cmd = shared.WASM_DIS + ['a.wasm', '-o', 'a.wast'] print(' '.join(cmd)) if os.path.exists('a.wast'): os.unlink('a.wast') diff -Nru binaryen-108/scripts/update_help_checks.py binaryen-99/scripts/update_help_checks.py --- binaryen-108/scripts/update_help_checks.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/update_help_checks.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2022 WebAssembly Community Group participants -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A test case update script for lit help checks. -""" - -import os -import subprocess - -import test.shared as shared - -script_dir = os.path.dirname(__file__) -root_dir = os.path.dirname(script_dir) -test_dir = os.path.join(root_dir, 'test', 'lit', 'help') - -TOOLS = ['wasm-opt', 'wasm-as', 'wasm-dis', 'wasm2js', 'wasm-ctor-eval', - 'wasm-shell', 'wasm-reduce', 'wasm-metadce', 'wasm-split', - 'wasm-fuzz-types', 'wasm-emscripten-finalize'] - - -def main(): - for tool in TOOLS: - tool_path = os.path.join(shared.options.binaryen_bin, tool) - command = [tool_path, '--help'] - print(command) - output = subprocess.check_output(command).decode('utf-8') - with open(os.path.join(test_dir, tool + '.test'), 'w') as out: - out.write(f';; RUN: {tool} --help | filecheck %s' + os.linesep) - first = True - for line in output.splitlines(): - if first: - out.write(f';; CHECK: {line}'.strip() + os.linesep) - first = False - else: - out.write(f';; CHECK-NEXT: {line}'.strip() + os.linesep) - - -if __name__ == '__main__': - main() diff -Nru binaryen-108/scripts/update_lit_checks.py binaryen-99/scripts/update_lit_checks.py --- binaryen-108/scripts/update_lit_checks.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/update_lit_checks.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,348 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2021 WebAssembly Community Group participants -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A test case update script. - -This script is a utility to update wasm-opt based lit tests with new FileCheck -patterns. It is based on LLVM's update_llc_test_checks.py script. -""" - -import argparse -import glob -import os -import re -import subprocess -import sys -import tempfile - -script_dir = os.path.dirname(__file__) -script_name = os.path.basename(__file__) - -NOTICE = (';; NOTE: Assertions have been generated by {script} and should not' + - ' be edited.') - -RUN_LINE_RE = re.compile(r'^\s*;;\s*RUN:\s*(.*)$') -CHECK_PREFIX_RE = re.compile(r'.*--check-prefix[= ](\S+).*') -MODULE_RE = re.compile(r'^\(module.*$', re.MULTILINE) - -ALL_ITEMS = '|'.join(['type', 'import', 'global', 'memory', 'data', 'table', - 'elem', 'tag', 'export', 'start', 'func']) -ITEM_NAME = r'\$?[^\s()]*|"[^\s()]*"' -ITEM_RE = re.compile(r'(^\s*)\((' + ALL_ITEMS + r')\s+(' + ITEM_NAME + ').*$', - re.MULTILINE) - -FUZZ_EXEC_FUNC = re.compile(r'^\[fuzz-exec\] calling (?P\S*)$') - - -def warn(msg): - print(f'warning: {msg}', file=sys.stderr) - - -def itertests(args): - """ - Yield (filename, lines) for each test specified in the command line args - """ - for pattern in args.tests: - tests = glob.glob(pattern, recursive=True) - if not tests: - warn(f'No tests matched {pattern}. Ignoring it.') - continue - for test in tests: - with open(test) as f: - lines = [line.rstrip() for line in f] - first_line = lines[0] if lines else '' - if script_name not in first_line and not args.force: - warn(f'Skipping test {test} which was not generated by ' - f'{script_name}. Use -f to override.') - continue - yield test, lines - - -def find_run_lines(test, lines): - line_matches = [RUN_LINE_RE.match(l) for l in lines] - matches = [match.group(1) for match in line_matches if match] - if not matches: - warn(f'No RUN lines found in {test}. Ignoring.') - return [] - run_lines = [matches[0]] - for line in matches[1:]: - if run_lines[-1].endswith('\\'): - run_lines[-1] = run_lines[-1].rstrip('\\') + ' ' + line - else: - run_lines.append(line) - return run_lines - - -def run_command(args, test, tmp, command): - env = dict(os.environ) - env['PATH'] = args.binaryen_bin + os.pathsep + env['PATH'] - command = command.replace('%s', test) - command = command.replace('%t', tmp) - command = command.replace('foreach', os.path.join(script_dir, 'foreach.py')) - return subprocess.check_output(command, shell=True, env=env).decode('utf-8') - - -def find_end(module, start): - # Find the index one past the closing parenthesis corresponding to the first - # open parenthesis at `start`. - assert module[start] == '(' - depth = 1 - for end in range(start + 1, len(module)): - if depth == 0: - break - elif module[end] == '(': - depth += 1 - elif module[end] == ')': - depth -= 1 - return end - - -def split_modules(text): - # Return a list of strings; one for each module - module_starts = [match.start() for match in MODULE_RE.finditer(text)] - if len(module_starts) < 2: - return [text] - first_module = text[:module_starts[1]] - modules = [first_module] - for i in range(1, len(module_starts) - 1): - module = text[module_starts[i]:module_starts[i + 1]] - modules.append(module) - last_module = text[module_starts[-1]:] - modules.append(last_module) - return modules - - -def parse_output_modules(text): - # Return a list containing, for each module in the text, a list of - # ((kind, name), [line]) for module items. - modules = [] - for module in split_modules(text): - items = [] - for match in ITEM_RE.finditer(module): - kind, name = match[2], match[3] - end = find_end(module, match.end(1)) - lines = module[match.start():end].split('\n') - items.append(((kind, name), lines)) - modules.append(items) - return modules - - -def parse_output_fuzz_exec(text): - # Returns the same data as `parse_output_modules`, but can't tell where - # module boundaries are, so always just returns items for a single module. - items = [] - for line in text.split('\n'): - func = FUZZ_EXEC_FUNC.match(line) - if func: - # Add quotes around the name because that is how it will be parsed - # in the input. - name = f'"{func.group("name")}"' - items.append((('func', name), [line])) - elif line: - assert items, 'unexpected non-invocation line' - items[-1][1].append(line) - return [items] - - -def get_command_output(args, kind, test, lines, tmp): - # Return list of maps from prefixes to lists of module items of the form - # ((kind, name), [line]). The outer list has an entry for each module. - command_output = [] - for line in find_run_lines(test, lines): - commands = [cmd.strip() for cmd in line.rsplit('|', 1)] - if (len(commands) > 2 or - (len(commands) == 2 and not commands[1].startswith('filecheck '))): - warn('pipes only supported for one command piped to `filecheck`') - filecheck_cmd = '' - if len(commands) > 1 and commands[1].startswith('filecheck '): - filecheck_cmd = commands[1] - commands = commands[:1] - - prefix = '' - if filecheck_cmd.startswith('filecheck '): - prefix_match = CHECK_PREFIX_RE.match(filecheck_cmd) - if prefix_match: - prefix = prefix_match.group(1) - else: - prefix = 'CHECK' - - output = run_command(args, test, tmp, commands[0]) - if prefix: - if kind == 'wat': - module_outputs = parse_output_modules(output) - elif kind == 'fuzz-exec': - module_outputs = parse_output_fuzz_exec(output) - else: - assert False, "unknown output kind" - for i in range(len(module_outputs)): - if len(command_output) == i: - command_output.append({}) - command_output[i][prefix] = module_outputs[i] - - return command_output - - -def update_test(args, test, lines, tmp): - # Do not update `args` directly because the changes should only apply to the - # current test. - all_items = args.all_items - output_kind = args.output - if lines and script_name in lines[0]: - # Apply previously used options for this file - if '--all-items' in lines[0]: - all_items = True - output = re.search(r'--output=(?P\S*)', lines[0]) - if output: - output_kind = output.group('kind') - # Skip the notice if it is already in the output - lines = lines[1:] - - command_output = get_command_output(args, output_kind, test, lines, tmp) - - prefixes = set(prefix - for module_output in command_output - for prefix in module_output.keys()) - check_line_re = re.compile(r'^\s*;;\s*(' + '|'.join(prefixes) + - r')(?:-NEXT|-LABEL|-NOT)?:.*$') - - # Filter out whitespace between check blocks - if lines: - filtered = [lines[0]] - for i in range(1, len(lines) - 1): - if lines[i] or not check_line_re.match(lines[i - 1]) or \ - not check_line_re.match(lines[i + 1]): - filtered.append(lines[i]) - filtered.append(lines[-1]) - lines = filtered - - named_items = [] - for line in lines: - match = ITEM_RE.match(line) - if match: - kind, name = match[2], match[3] - named_items.append((kind, name)) - - script = script_name - if all_items: - script += ' --all-items' - if output_kind != 'wat': - script += f' --output={output_kind}' - output_lines = [NOTICE.format(script=script)] - - def emit_checks(indent, prefix, lines): - def pad(line): - return line if not line or line.startswith(' ') else ' ' + line - output_lines.append(f'{indent};; {prefix}: {pad(lines[0])}') - for line in lines[1:]: - output_lines.append(f'{indent};; {prefix}-NEXT:{pad(line)}') - - input_modules = [m.split('\n') for m in split_modules('\n'.join(lines))] - if len(input_modules) > len(command_output): - warn('Fewer output modules than input modules:' - 'not all modules will get checks.') - - # Remove extra newlines at the end of modules - input_modules = [m[:-1] for m in input_modules[:-1]] + [input_modules[-1]] - - for module_idx in range(len(input_modules)): - output = command_output[module_idx] \ - if module_idx < len(command_output) else {} - - for line in input_modules[module_idx]: - # Skip pre-existing check lines; we will regenerate them. - if check_line_re.match(line): - continue - - match = ITEM_RE.match(line) - if not match: - output_lines.append(line) - continue - - indent, kind, name = match.groups() - - for prefix, items in output.items(): - # If the output for this prefix contains an item with this - # name, emit all the items up to and including the matching - # item - has_item = False - for kind_name, lines in items: - if name and (kind, name) == kind_name: - has_item = True - break - if has_item: - first = True - while True: - kind_name, lines = items.pop(0) - if all_items or kind_name in named_items: - if not first: - output_lines.append('') - first = False - emit_checks(indent, prefix, lines) - if name and (kind, name) == kind_name: - break - output_lines.append(line) - - # Output any remaining checks for each prefix - first = True - for prefix, items in output.items(): - for kind_name, lines in items: - if all_items or kind_name in named_items: - if not first: - output_lines.append('') - first = False - emit_checks('', prefix, lines) - - if args.dry_run: - print('\n'.join(output_lines)) - else: - with open(test, 'w') as f: - for line in output_lines: - f.write(line + '\n') - - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - '--binaryen-bin', dest='binaryen_bin', default='bin', - help=('Specifies the path to the Binaryen executables in the CMake build' - ' directory. Default: bin/ of current directory (i.e. assume an' - ' in-tree build).')) - parser.add_argument( - '--all-items', action='store_true', - help=('Emit checks for all module items, even those that do not appear' - ' in the input.')) - parser.add_argument( - '--output', choices=['wat', 'fuzz-exec'], default='wat', - help=('The kind of output test commands are expected to produce.')) - parser.add_argument( - '-f', '--force', action='store_true', - help=('Generate FileCheck patterns even for test files whose existing ' - 'patterns were not generated by this script.')) - parser.add_argument( - '--dry-run', action='store_true', - help=('Print the updated test file contents instead of changing the ' - 'test files')) - parser.add_argument('tests', nargs='+', help='The test files to update') - args = parser.parse_args() - args.binaryen_bin = os.path.abspath(args.binaryen_bin) - - tmp = tempfile.mktemp() - - for test, lines in itertests(args): - update_test(args, test, lines, tmp) - - -if __name__ == '__main__': - main() diff -Nru binaryen-108/scripts/wasm2js.js binaryen-99/scripts/wasm2js.js --- binaryen-108/scripts/wasm2js.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/scripts/wasm2js.js 2021-01-07 20:01:06.000000000 +0000 @@ -124,6 +124,14 @@ console.log('get_f64 ' + [loc, index, value]); return value; }, + get_externref: function(loc, index, value) { + console.log('get_externref ' + [loc, index, value]); + return value; + }, + get_exnref: function(loc, index, value) { + console.log('get_exnref ' + [loc, index, value]); + return value; + }, set_i32: function(loc, index, value) { console.log('set_i32 ' + [loc, index, value]); return value; @@ -141,6 +149,14 @@ console.log('set_f64 ' + [loc, index, value]); return value; }, + set_externref: function(loc, index, value) { + console.log('set_externref ' + [loc, index, value]); + return value; + }, + set_exnref: function(loc, index, value) { + console.log('set_exnref ' + [loc, index, value]); + return value; + }, load_ptr: function(loc, bytes, offset, ptr) { console.log('load_ptr ' + [loc, bytes, offset, ptr]); return ptr; @@ -155,7 +171,7 @@ return low; }, load_val_f32: function(loc, value) { - console.log('load_val_f32 ' + [loc, value]); + console.log('loaload_val_i32d_ptr ' + [loc, value]); return value; }, load_val_f64: function(loc, value) { @@ -176,87 +192,13 @@ return low; }, store_val_f32: function(loc, value) { - console.log('store_val_f32 ' + [loc, value]); + console.log('loastore_val_i32d_ptr ' + [loc, value]); return value; }, store_val_f64: function(loc, value) { console.log('store_val_f64 ' + [loc, value]); return value; }, - - struct_get_val_i32: function(loc, value) { - console.log('struct_get_val_i32 ' + [loc, value]); - return value; - }, - struct_get_val_i64: function(loc, value) { - console.log('struct_get_val_i64 ' + [loc, value]); - return value; - }, - struct_get_val_f32: function(loc, value) { - console.log('struct_get_val_f32 ' + [loc, value]); - return value; - }, - struct_get_val_f64: function(loc, value) { - console.log('struct_get_val_f64 ' + [loc, value]); - return value; - }, - struct_set_val_i32: function(loc, value) { - console.log('struct_set_val_i32 ' + [loc, value]); - return value; - }, - struct_set_val_i64: function(loc, value) { - console.log('struct_set_val_i64 ' + [loc, value]); - return value; - }, - struct_set_val_f32: function(loc, value) { - console.log('struct_set_val_f32 ' + [loc, value]); - return value; - }, - struct_set_val_f64: function(loc, value) { - console.log('struct_set_val_f64 ' + [loc, value]); - return value; - }, - - array_get_val_i32: function(loc, value) { - console.log('array_get_val_i32 ' + [loc, value]); - return value; - }, - array_get_val_i64: function(loc, value) { - console.log('array_get_val_i64 ' + [loc, value]); - return value; - }, - array_get_val_f32: function(loc, value) { - console.log('array_get_val_f32 ' + [loc, value]); - return value; - }, - array_get_val_f64: function(loc, value) { - console.log('array_get_val_f64 ' + [loc, value]); - return value; - }, - array_set_val_i32: function(loc, value) { - console.log('array_set_val_i32 ' + [loc, value]); - return value; - }, - array_set_val_i64: function(loc, value) { - console.log('array_set_val_i64 ' + [loc, value]); - return value; - }, - array_set_val_f32: function(loc, value) { - console.log('array_set_val_f32 ' + [loc, value]); - return value; - }, - array_set_val_f64: function(loc, value) { - console.log('array_set_val_f64 ' + [loc, value]); - return value; - }, - array_get_index: function(loc, value) { - console.log('array_get_index ' + [loc, value]); - return value; - }, - array_set_index: function(loc, value) { - console.log('array_set_index ' + [loc, value]); - return value; - }, }; var wasmMemory = new WebAssembly.Memory({ initial: 1 }); diff -Nru binaryen-108/src/abi/js.h binaryen-99/src/abi/js.h --- binaryen-108/src/abi/js.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/abi/js.h 2021-01-07 20:01:06.000000000 +0000 @@ -18,7 +18,6 @@ #define wasm_abi_abi_h #include "asmjs/shared-constants.h" -#include "wasm-builder.h" #include "wasm.h" namespace wasm { @@ -65,7 +64,9 @@ if (specific.is() && name != specific) { return; } - auto func = Builder::makeFunction(name, Signature(params, results), {}); + auto func = make_unique(); + func->name = name; + func->sig = Signature(params, results); func->module = ENV; func->base = name; wasm->addFunction(std::move(func)); diff -Nru binaryen-108/src/asmjs/asm_v_wasm.cpp binaryen-99/src/asmjs/asm_v_wasm.cpp --- binaryen-108/src/asmjs/asm_v_wasm.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/asmjs/asm_v_wasm.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -15,32 +15,32 @@ */ #include "asm_v_wasm.h" -#include "support/utilities.h" #include "wasm.h" namespace wasm { -JsType wasmToJsType(Type type) { +AsmType wasmToAsmType(Type type) { TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { case Type::i32: - return JS_INT; + return ASM_INT; case Type::f32: - return JS_FLOAT; + return ASM_FLOAT; case Type::f64: - return JS_DOUBLE; + return ASM_DOUBLE; case Type::i64: - return JS_INT64; + return ASM_INT64; case Type::v128: - WASM_UNREACHABLE("v128 not implemented yet"); + assert(false && "v128 not implemented yet"); case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: - WASM_UNREACHABLE("reference types are not supported by wasm2js"); + assert(false && "reference types are not supported by asm2wasm"); case Type::none: - return JS_NONE; + return ASM_NONE; case Type::unreachable: WASM_UNREACHABLE("invalid type"); } @@ -62,14 +62,16 @@ return 'V'; case Type::funcref: return 'F'; + case Type::externref: + return 'X'; + case Type::exnref: + return 'E'; case Type::anyref: return 'A'; case Type::eqref: return 'Q'; case Type::i31ref: return 'I'; - case Type::dataref: - return 'D'; case Type::none: return 'v'; case Type::unreachable: diff -Nru binaryen-108/src/asm_v_wasm.h binaryen-99/src/asm_v_wasm.h --- binaryen-108/src/asm_v_wasm.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/asm_v_wasm.h 2021-01-07 20:01:06.000000000 +0000 @@ -18,13 +18,15 @@ #define wasm_asm_v_wasm_h #include "emscripten-optimizer/optimizer.h" +#include "mixed_arena.h" #include "wasm.h" namespace wasm { -JsType wasmToJsType(Type type); +AsmType wasmToAsmType(Type type); char getSig(Type type); +std::string getSig(Function* func); std::string getSig(Type results, Type params); template diff -Nru binaryen-108/src/binaryen-c.cpp binaryen-99/src/binaryen-c.cpp --- binaryen-108/src/binaryen-c.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/binaryen-c.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -70,14 +70,14 @@ case Type::funcref: ret.func = x.isNull() ? nullptr : x.getFunc().c_str(); break; + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: assert(x.isNull() && "unexpected non-null reference type literal"); break; case Type::i31ref: WASM_UNREACHABLE("TODO: i31ref"); - case Type::dataref: - WASM_UNREACHABLE("TODO: dataref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -99,13 +99,13 @@ return Literal(x.v128); case Type::funcref: return Literal::makeFunc(x.func); + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: return Literal::makeNull(Type(x.type)); case Type::i31ref: WASM_UNREACHABLE("TODO: i31ref"); - case Type::dataref: - WASM_UNREACHABLE("TODO: dataref"); case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -130,7 +130,6 @@ // // Core types -// TODO: Deprecate BinaryenTypeExternref? BinaryenType BinaryenTypeNone(void) { return Type::none; } BinaryenType BinaryenTypeInt32(void) { return Type::i32; } @@ -139,18 +138,18 @@ BinaryenType BinaryenTypeFloat64(void) { return Type::f64; } BinaryenType BinaryenTypeVec128(void) { return Type::v128; } BinaryenType BinaryenTypeFuncref(void) { return Type::funcref; } -BinaryenType BinaryenTypeExternref(void) { return Type::anyref; } +BinaryenType BinaryenTypeExternref(void) { return Type::externref; } +BinaryenType BinaryenTypeExnref(void) { return Type::exnref; } BinaryenType BinaryenTypeAnyref(void) { return Type::anyref; } BinaryenType BinaryenTypeEqref(void) { return Type::eqref; } BinaryenType BinaryenTypeI31ref(void) { return Type::i31ref; } -BinaryenType BinaryenTypeDataref(void) { return Type::dataref; } BinaryenType BinaryenTypeUnreachable(void) { return Type::unreachable; } BinaryenType BinaryenTypeAuto(void) { return uintptr_t(-1); } -BinaryenType BinaryenTypeCreate(BinaryenType* types, BinaryenIndex numTypes) { +BinaryenType BinaryenTypeCreate(BinaryenType* types, uint32_t numTypes) { std::vector typeVec; typeVec.reserve(numTypes); - for (BinaryenIndex i = 0; i < numTypes; ++i) { + for (size_t i = 0; i < numTypes; ++i) { typeVec.push_back(Type(types[i])); } return Type(typeVec).getID(); @@ -184,7 +183,7 @@ return Expression::Id::CLASS_TO_VISIT##Id; \ } -#include "wasm-delegations.def" +#include "wasm-delegations.h" // External kinds @@ -200,8 +199,8 @@ BinaryenExternalKind BinaryenExternalGlobal(void) { return static_cast(ExternalKind::Global); } -BinaryenExternalKind BinaryenExternalTag(void) { - return static_cast(ExternalKind::Tag); +BinaryenExternalKind BinaryenExternalEvent(void) { + return static_cast(ExternalKind::Event); } // Features @@ -245,15 +244,6 @@ BinaryenFeatures BinaryenFeatureMemory64(void) { return static_cast(FeatureSet::Memory64); } -BinaryenFeatures BinaryenFeatureTypedFunctionReferences(void) { - return static_cast(FeatureSet::TypedFunctionReferences); -} -BinaryenFeatures BinaryenFeatureRelaxedSIMD(void) { - return static_cast(FeatureSet::RelaxedSIMD); -} -BinaryenFeatures BinaryenFeatureExtendedConst(void) { - return static_cast(FeatureSet::ExtendedConst); -} BinaryenFeatures BinaryenFeatureAll(void) { return static_cast(FeatureSet::All); } @@ -513,12 +503,6 @@ BinaryenOp BinaryenLeUVecI32x4(void) { return LeUVecI32x4; } BinaryenOp BinaryenGeSVecI32x4(void) { return GeSVecI32x4; } BinaryenOp BinaryenGeUVecI32x4(void) { return GeUVecI32x4; } -BinaryenOp BinaryenEqVecI64x2(void) { return EqVecI64x2; } -BinaryenOp BinaryenNeVecI64x2(void) { return NeVecI64x2; } -BinaryenOp BinaryenLtSVecI64x2(void) { return LtSVecI64x2; } -BinaryenOp BinaryenGtSVecI64x2(void) { return GtSVecI64x2; } -BinaryenOp BinaryenLeSVecI64x2(void) { return LeSVecI64x2; } -BinaryenOp BinaryenGeSVecI64x2(void) { return GeSVecI64x2; } BinaryenOp BinaryenEqVecF32x4(void) { return EqVecF32x4; } BinaryenOp BinaryenNeVecF32x4(void) { return NeVecF32x4; } BinaryenOp BinaryenLtVecF32x4(void) { return LtVecF32x4; } @@ -537,12 +521,11 @@ BinaryenOp BinaryenXorVec128(void) { return XorVec128; } BinaryenOp BinaryenAndNotVec128(void) { return AndNotVec128; } BinaryenOp BinaryenBitselectVec128(void) { return Bitselect; } -BinaryenOp BinaryenAnyTrueVec128(void) { return AnyTrueVec128; } BinaryenOp BinaryenAbsVecI8x16(void) { return AbsVecI8x16; } BinaryenOp BinaryenNegVecI8x16(void) { return NegVecI8x16; } +BinaryenOp BinaryenAnyTrueVecI8x16(void) { return AnyTrueVecI8x16; } BinaryenOp BinaryenAllTrueVecI8x16(void) { return AllTrueVecI8x16; } BinaryenOp BinaryenBitmaskVecI8x16(void) { return BitmaskVecI8x16; } -BinaryenOp BinaryenPopcntVecI8x16(void) { return PopcntVecI8x16; } BinaryenOp BinaryenShlVecI8x16(void) { return ShlVecI8x16; } BinaryenOp BinaryenShrSVecI8x16(void) { return ShrSVecI8x16; } BinaryenOp BinaryenShrUVecI8x16(void) { return ShrUVecI8x16; } @@ -552,6 +535,7 @@ BinaryenOp BinaryenSubVecI8x16(void) { return SubVecI8x16; } BinaryenOp BinaryenSubSatSVecI8x16(void) { return SubSatSVecI8x16; } BinaryenOp BinaryenSubSatUVecI8x16(void) { return SubSatUVecI8x16; } +BinaryenOp BinaryenMulVecI8x16(void) { return MulVecI8x16; } BinaryenOp BinaryenMinSVecI8x16(void) { return MinSVecI8x16; } BinaryenOp BinaryenMinUVecI8x16(void) { return MinUVecI8x16; } BinaryenOp BinaryenMaxSVecI8x16(void) { return MaxSVecI8x16; } @@ -559,6 +543,7 @@ BinaryenOp BinaryenAvgrUVecI8x16(void) { return AvgrUVecI8x16; } BinaryenOp BinaryenAbsVecI16x8(void) { return AbsVecI16x8; } BinaryenOp BinaryenNegVecI16x8(void) { return NegVecI16x8; } +BinaryenOp BinaryenAnyTrueVecI16x8(void) { return AnyTrueVecI16x8; } BinaryenOp BinaryenAllTrueVecI16x8(void) { return AllTrueVecI16x8; } BinaryenOp BinaryenBitmaskVecI16x8(void) { return BitmaskVecI16x8; } BinaryenOp BinaryenShlVecI16x8(void) { return ShlVecI16x8; } @@ -576,13 +561,9 @@ BinaryenOp BinaryenMaxSVecI16x8(void) { return MaxSVecI16x8; } BinaryenOp BinaryenMaxUVecI16x8(void) { return MaxUVecI16x8; } BinaryenOp BinaryenAvgrUVecI16x8(void) { return AvgrUVecI16x8; } -BinaryenOp BinaryenQ15MulrSatSVecI16x8(void) { return Q15MulrSatSVecI16x8; } -BinaryenOp BinaryenExtMulLowSVecI16x8(void) { return ExtMulLowSVecI16x8; } -BinaryenOp BinaryenExtMulHighSVecI16x8(void) { return ExtMulHighSVecI16x8; } -BinaryenOp BinaryenExtMulLowUVecI16x8(void) { return ExtMulLowUVecI16x8; } -BinaryenOp BinaryenExtMulHighUVecI16x8(void) { return ExtMulHighUVecI16x8; } BinaryenOp BinaryenAbsVecI32x4(void) { return AbsVecI32x4; } BinaryenOp BinaryenNegVecI32x4(void) { return NegVecI32x4; } +BinaryenOp BinaryenAnyTrueVecI32x4(void) { return AnyTrueVecI32x4; } BinaryenOp BinaryenAllTrueVecI32x4(void) { return AllTrueVecI32x4; } BinaryenOp BinaryenBitmaskVecI32x4(void) { return BitmaskVecI32x4; } BinaryenOp BinaryenShlVecI32x4(void) { return ShlVecI32x4; } @@ -598,27 +579,18 @@ BinaryenOp BinaryenDotSVecI16x8ToVecI32x4(void) { return DotSVecI16x8ToVecI32x4; } -BinaryenOp BinaryenExtMulLowSVecI32x4(void) { return ExtMulLowSVecI32x4; } -BinaryenOp BinaryenExtMulHighSVecI32x4(void) { return ExtMulHighSVecI32x4; } -BinaryenOp BinaryenExtMulLowUVecI32x4(void) { return ExtMulLowUVecI32x4; } -BinaryenOp BinaryenExtMulHighUVecI32x4(void) { return ExtMulHighUVecI32x4; } -BinaryenOp BinaryenAbsVecI64x2(void) { return AbsVecI64x2; } BinaryenOp BinaryenNegVecI64x2(void) { return NegVecI64x2; } -BinaryenOp BinaryenAllTrueVecI64x2(void) { return AllTrueVecI64x2; } -BinaryenOp BinaryenBitmaskVecI64x2(void) { return BitmaskVecI64x2; } BinaryenOp BinaryenShlVecI64x2(void) { return ShlVecI64x2; } BinaryenOp BinaryenShrSVecI64x2(void) { return ShrSVecI64x2; } BinaryenOp BinaryenShrUVecI64x2(void) { return ShrUVecI64x2; } BinaryenOp BinaryenAddVecI64x2(void) { return AddVecI64x2; } BinaryenOp BinaryenSubVecI64x2(void) { return SubVecI64x2; } BinaryenOp BinaryenMulVecI64x2(void) { return MulVecI64x2; } -BinaryenOp BinaryenExtMulLowSVecI64x2(void) { return ExtMulLowSVecI64x2; } -BinaryenOp BinaryenExtMulHighSVecI64x2(void) { return ExtMulHighSVecI64x2; } -BinaryenOp BinaryenExtMulLowUVecI64x2(void) { return ExtMulLowUVecI64x2; } -BinaryenOp BinaryenExtMulHighUVecI64x2(void) { return ExtMulHighUVecI64x2; } BinaryenOp BinaryenAbsVecF32x4(void) { return AbsVecF32x4; } BinaryenOp BinaryenNegVecF32x4(void) { return NegVecF32x4; } BinaryenOp BinaryenSqrtVecF32x4(void) { return SqrtVecF32x4; } +BinaryenOp BinaryenQFMAVecF32x4(void) { return QFMAF32x4; } +BinaryenOp BinaryenQFMSVecF32x4(void) { return QFMSF32x4; } BinaryenOp BinaryenAddVecF32x4(void) { return AddVecF32x4; } BinaryenOp BinaryenSubVecF32x4(void) { return SubVecF32x4; } BinaryenOp BinaryenMulVecF32x4(void) { return MulVecF32x4; } @@ -634,6 +606,8 @@ BinaryenOp BinaryenAbsVecF64x2(void) { return AbsVecF64x2; } BinaryenOp BinaryenNegVecF64x2(void) { return NegVecF64x2; } BinaryenOp BinaryenSqrtVecF64x2(void) { return SqrtVecF64x2; } +BinaryenOp BinaryenQFMAVecF64x2(void) { return QFMAF64x2; } +BinaryenOp BinaryenQFMSVecF64x2(void) { return QFMSF64x2; } BinaryenOp BinaryenAddVecF64x2(void) { return AddVecF64x2; } BinaryenOp BinaryenSubVecF64x2(void) { return SubVecF64x2; } BinaryenOp BinaryenMulVecF64x2(void) { return MulVecF64x2; } @@ -646,125 +620,89 @@ BinaryenOp BinaryenFloorVecF64x2(void) { return FloorVecF64x2; } BinaryenOp BinaryenTruncVecF64x2(void) { return TruncVecF64x2; } BinaryenOp BinaryenNearestVecF64x2(void) { return NearestVecF64x2; } -BinaryenOp BinaryenExtAddPairwiseSVecI8x16ToI16x8(void) { - return ExtAddPairwiseSVecI8x16ToI16x8; -} -BinaryenOp BinaryenExtAddPairwiseUVecI8x16ToI16x8(void) { - return ExtAddPairwiseUVecI8x16ToI16x8; -} -BinaryenOp BinaryenExtAddPairwiseSVecI16x8ToI32x4(void) { - return ExtAddPairwiseSVecI16x8ToI32x4; -} -BinaryenOp BinaryenExtAddPairwiseUVecI16x8ToI32x4(void) { - return ExtAddPairwiseUVecI16x8ToI32x4; -} BinaryenOp BinaryenTruncSatSVecF32x4ToVecI32x4(void) { return TruncSatSVecF32x4ToVecI32x4; } BinaryenOp BinaryenTruncSatUVecF32x4ToVecI32x4(void) { return TruncSatUVecF32x4ToVecI32x4; } +BinaryenOp BinaryenTruncSatSVecF64x2ToVecI64x2(void) { + return TruncSatSVecF64x2ToVecI64x2; +} +BinaryenOp BinaryenTruncSatUVecF64x2ToVecI64x2(void) { + return TruncSatUVecF64x2ToVecI64x2; +} BinaryenOp BinaryenConvertSVecI32x4ToVecF32x4(void) { return ConvertSVecI32x4ToVecF32x4; } BinaryenOp BinaryenConvertUVecI32x4ToVecF32x4(void) { return ConvertUVecI32x4ToVecF32x4; } -BinaryenOp BinaryenLoad8SplatVec128(void) { return Load8SplatVec128; } -BinaryenOp BinaryenLoad16SplatVec128(void) { return Load16SplatVec128; } -BinaryenOp BinaryenLoad32SplatVec128(void) { return Load32SplatVec128; } -BinaryenOp BinaryenLoad64SplatVec128(void) { return Load64SplatVec128; } -BinaryenOp BinaryenLoad8x8SVec128(void) { return Load8x8SVec128; } -BinaryenOp BinaryenLoad8x8UVec128(void) { return Load8x8UVec128; } -BinaryenOp BinaryenLoad16x4SVec128(void) { return Load16x4SVec128; } -BinaryenOp BinaryenLoad16x4UVec128(void) { return Load16x4UVec128; } -BinaryenOp BinaryenLoad32x2SVec128(void) { return Load32x2SVec128; } -BinaryenOp BinaryenLoad32x2UVec128(void) { return Load32x2UVec128; } -BinaryenOp BinaryenLoad32ZeroVec128(void) { return Load32ZeroVec128; } -BinaryenOp BinaryenLoad64ZeroVec128(void) { return Load64ZeroVec128; } -BinaryenOp BinaryenLoad8LaneVec128(void) { return Load8LaneVec128; } -BinaryenOp BinaryenLoad16LaneVec128(void) { return Load16LaneVec128; } -BinaryenOp BinaryenLoad32LaneVec128(void) { return Load32LaneVec128; } -BinaryenOp BinaryenLoad64LaneVec128(void) { return Load64LaneVec128; } -BinaryenOp BinaryenStore8LaneVec128(void) { return Store8LaneVec128; } -BinaryenOp BinaryenStore16LaneVec128(void) { return Store16LaneVec128; } -BinaryenOp BinaryenStore32LaneVec128(void) { return Store32LaneVec128; } -BinaryenOp BinaryenStore64LaneVec128(void) { return Store64LaneVec128; } -BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void) { - return NarrowSVecI16x8ToVecI8x16; +BinaryenOp BinaryenConvertSVecI64x2ToVecF64x2(void) { + return ConvertSVecI64x2ToVecF64x2; } -BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void) { - return NarrowUVecI16x8ToVecI8x16; -} -BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void) { - return NarrowSVecI32x4ToVecI16x8; +BinaryenOp BinaryenConvertUVecI64x2ToVecF64x2(void) { + return ConvertUVecI64x2ToVecF64x2; } -BinaryenOp BinaryenNarrowUVecI32x4ToVecI16x8(void) { - return NarrowUVecI32x4ToVecI16x8; +BinaryenOp BinaryenLoadSplatVec8x16(void) { return LoadSplatVec8x16; } +BinaryenOp BinaryenLoadSplatVec16x8(void) { return LoadSplatVec16x8; } +BinaryenOp BinaryenLoadSplatVec32x4(void) { return LoadSplatVec32x4; } +BinaryenOp BinaryenLoadSplatVec64x2(void) { return LoadSplatVec64x2; } +BinaryenOp BinaryenLoadExtSVec8x8ToVecI16x8(void) { + return LoadExtSVec8x8ToVecI16x8; } -BinaryenOp BinaryenExtendLowSVecI8x16ToVecI16x8(void) { - return ExtendLowSVecI8x16ToVecI16x8; +BinaryenOp BinaryenLoadExtUVec8x8ToVecI16x8(void) { + return LoadExtUVec8x8ToVecI16x8; } -BinaryenOp BinaryenExtendHighSVecI8x16ToVecI16x8(void) { - return ExtendHighSVecI8x16ToVecI16x8; +BinaryenOp BinaryenLoadExtSVec16x4ToVecI32x4(void) { + return LoadExtSVec16x4ToVecI32x4; } -BinaryenOp BinaryenExtendLowUVecI8x16ToVecI16x8(void) { - return ExtendLowUVecI8x16ToVecI16x8; +BinaryenOp BinaryenLoadExtUVec16x4ToVecI32x4(void) { + return LoadExtUVec16x4ToVecI32x4; } -BinaryenOp BinaryenExtendHighUVecI8x16ToVecI16x8(void) { - return ExtendHighUVecI8x16ToVecI16x8; +BinaryenOp BinaryenLoadExtSVec32x2ToVecI64x2(void) { + return LoadExtSVec32x2ToVecI64x2; } -BinaryenOp BinaryenExtendLowSVecI16x8ToVecI32x4(void) { - return ExtendLowSVecI16x8ToVecI32x4; +BinaryenOp BinaryenLoadExtUVec32x2ToVecI64x2(void) { + return LoadExtUVec32x2ToVecI64x2; } -BinaryenOp BinaryenExtendHighSVecI16x8ToVecI32x4(void) { - return ExtendHighSVecI16x8ToVecI32x4; -} -BinaryenOp BinaryenExtendLowUVecI16x8ToVecI32x4(void) { - return ExtendLowUVecI16x8ToVecI32x4; +BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void) { + return NarrowSVecI16x8ToVecI8x16; } -BinaryenOp BinaryenExtendHighUVecI16x8ToVecI32x4(void) { - return ExtendHighUVecI16x8ToVecI32x4; +BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void) { + return NarrowUVecI16x8ToVecI8x16; } -BinaryenOp BinaryenExtendLowSVecI32x4ToVecI64x2(void) { - return ExtendLowSVecI32x4ToVecI64x2; +BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void) { + return NarrowSVecI32x4ToVecI16x8; } -BinaryenOp BinaryenExtendHighSVecI32x4ToVecI64x2(void) { - return ExtendHighSVecI32x4ToVecI64x2; +BinaryenOp BinaryenNarrowUVecI32x4ToVecI16x8(void) { + return NarrowUVecI32x4ToVecI16x8; } -BinaryenOp BinaryenExtendLowUVecI32x4ToVecI64x2(void) { - return ExtendLowUVecI32x4ToVecI64x2; +BinaryenOp BinaryenWidenLowSVecI8x16ToVecI16x8(void) { + return WidenLowSVecI8x16ToVecI16x8; } -BinaryenOp BinaryenExtendHighUVecI32x4ToVecI64x2(void) { - return ExtendHighUVecI32x4ToVecI64x2; +BinaryenOp BinaryenWidenHighSVecI8x16ToVecI16x8(void) { + return WidenHighSVecI8x16ToVecI16x8; } -BinaryenOp BinaryenConvertLowSVecI32x4ToVecF64x2(void) { - return ConvertLowSVecI32x4ToVecF64x2; +BinaryenOp BinaryenWidenLowUVecI8x16ToVecI16x8(void) { + return WidenLowUVecI8x16ToVecI16x8; } -BinaryenOp BinaryenConvertLowUVecI32x4ToVecF64x2(void) { - return ConvertLowUVecI32x4ToVecF64x2; +BinaryenOp BinaryenWidenHighUVecI8x16ToVecI16x8(void) { + return WidenHighUVecI8x16ToVecI16x8; } -BinaryenOp BinaryenTruncSatZeroSVecF64x2ToVecI32x4(void) { - return TruncSatZeroSVecF64x2ToVecI32x4; +BinaryenOp BinaryenWidenLowSVecI16x8ToVecI32x4(void) { + return WidenLowSVecI16x8ToVecI32x4; } -BinaryenOp BinaryenTruncSatZeroUVecF64x2ToVecI32x4(void) { - return TruncSatZeroUVecF64x2ToVecI32x4; +BinaryenOp BinaryenWidenHighSVecI16x8ToVecI32x4(void) { + return WidenHighSVecI16x8ToVecI32x4; } -BinaryenOp BinaryenDemoteZeroVecF64x2ToVecF32x4(void) { - return DemoteZeroVecF64x2ToVecF32x4; +BinaryenOp BinaryenWidenLowUVecI16x8ToVecI32x4(void) { + return WidenLowUVecI16x8ToVecI32x4; } -BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void) { - return PromoteLowVecF32x4ToVecF64x2; +BinaryenOp BinaryenWidenHighUVecI16x8ToVecI32x4(void) { + return WidenHighUVecI16x8ToVecI32x4; } -BinaryenOp BinaryenSwizzleVecI8x16(void) { return SwizzleVecI8x16; } -BinaryenOp BinaryenRefIsNull(void) { return RefIsNull; } -BinaryenOp BinaryenRefIsFunc(void) { return RefIsFunc; } -BinaryenOp BinaryenRefIsData(void) { return RefIsData; } -BinaryenOp BinaryenRefIsI31(void) { return RefIsI31; } -BinaryenOp BinaryenRefAsNonNull(void) { return RefAsNonNull; }; -BinaryenOp BinaryenRefAsFunc(void) { return RefAsFunc; } -BinaryenOp BinaryenRefAsData(void) { return RefAsData; }; -BinaryenOp BinaryenRefAsI31(void) { return RefAsI31; }; +BinaryenOp BinaryenSwizzleVec8x16(void) { return SwizzleVec8x16; } BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, const char* name, @@ -789,10 +727,12 @@ BinaryenExpressionRef condition, BinaryenExpressionRef ifTrue, BinaryenExpressionRef ifFalse) { - return static_cast(Builder(*(Module*)module) - .makeIf((Expression*)condition, - (Expression*)ifTrue, - (Expression*)ifFalse)); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->condition = (Expression*)condition; + ret->ifTrue = (Expression*)ifTrue; + ret->ifFalse = (Expression*)ifFalse; + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenLoop(BinaryenModuleRef module, const char* name, @@ -859,7 +799,6 @@ } static BinaryenExpressionRef makeBinaryenCallIndirect(BinaryenModuleRef module, - const char* table, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, @@ -867,84 +806,100 @@ BinaryenType results, bool isReturn) { auto* ret = ((Module*)module)->allocator.alloc(); - ret->table = table; ret->target = (Expression*)target; for (BinaryenIndex i = 0; i < numOperands; i++) { ret->operands.push_back((Expression*)operands[i]); } - ret->heapType = Signature(Type(params), Type(results)); + ret->sig = Signature(Type(params), Type(results)); ret->type = Type(results); ret->isReturn = isReturn; ret->finalize(); return static_cast(ret); } BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, - const char* table, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenType params, BinaryenType results) { return makeBinaryenCallIndirect( - module, table, target, operands, numOperands, params, results, false); + module, target, operands, numOperands, params, results, false); } BinaryenExpressionRef BinaryenReturnCallIndirect(BinaryenModuleRef module, - const char* table, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenType params, BinaryenType results) { return makeBinaryenCallIndirect( - module, table, target, operands, numOperands, params, results, true); + module, target, operands, numOperands, params, results, true); } BinaryenExpressionRef BinaryenLocalGet(BinaryenModuleRef module, BinaryenIndex index, BinaryenType type) { - return static_cast( - Builder(*(Module*)module).makeLocalGet(index, Type(type))); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->index = index; + ret->type = Type(type); + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenLocalSet(BinaryenModuleRef module, BinaryenIndex index, BinaryenExpressionRef value) { - return static_cast( - Builder(*(Module*)module).makeLocalSet(index, (Expression*)value)); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->index = index; + ret->value = (Expression*)value; + ret->makeSet(); + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenLocalTee(BinaryenModuleRef module, BinaryenIndex index, BinaryenExpressionRef value, BinaryenType type) { - return static_cast( - Builder(*(Module*)module) - .makeLocalTee(index, (Expression*)value, Type(type))); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->index = index; + ret->value = (Expression*)value; + ret->makeTee(Type(type)); + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenGlobalGet(BinaryenModuleRef module, const char* name, BinaryenType type) { - return static_cast( - Builder(*(Module*)module).makeGlobalGet(name, Type(type))); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->name = name; + ret->type = Type(type); + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenGlobalSet(BinaryenModuleRef module, const char* name, BinaryenExpressionRef value) { - return static_cast( - Builder(*(Module*)module).makeGlobalSet(name, (Expression*)value)); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->name = name; + ret->value = (Expression*)value; + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, - bool signed_, + int8_t signed_, uint32_t offset, uint32_t align, BinaryenType type, BinaryenExpressionRef ptr) { - return static_cast(Builder(*(Module*)module) - .makeLoad(bytes, - !!signed_, - offset, - align ? align : bytes, - (Expression*)ptr, - Type(type))); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->isAtomic = false; + ret->bytes = bytes; + ret->signed_ = !!signed_; + ret->offset = offset; + ret->align = align ? align : bytes; + ret->type = Type(type); + ret->ptr = (Expression*)ptr; + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenStore(BinaryenModuleRef module, uint32_t bytes, @@ -953,13 +908,16 @@ BinaryenExpressionRef ptr, BinaryenExpressionRef value, BinaryenType type) { - return static_cast(Builder(*(Module*)module) - .makeStore(bytes, - offset, - align ? align : bytes, - (Expression*)ptr, - (Expression*)value, - Type(type))); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->isAtomic = false; + ret->bytes = bytes; + ret->offset = offset; + ret->align = align ? align : bytes; + ret->ptr = (Expression*)ptr; + ret->value = (Expression*)value; + ret->valueType = Type(type); + ret->finalize(); + return static_cast(ret); } BinaryenExpressionRef BinaryenConst(BinaryenModuleRef module, BinaryenLiteral value) { @@ -998,7 +956,9 @@ } BinaryenExpressionRef BinaryenDrop(BinaryenModuleRef module, BinaryenExpressionRef value) { - auto* ret = Builder(*(Module*)module).makeDrop((Expression*)value); + auto* ret = ((Module*)module)->allocator.alloc(); + ret->value = (Expression*)value; + ret->finalize(); return static_cast(ret); } BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module, @@ -1016,10 +976,11 @@ return static_cast(ret); } BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module) { - return static_cast(Builder(*(Module*)module).makeNop()); + return static_cast(((Module*)module)->allocator.alloc()); } BinaryenExpressionRef BinaryenUnreachable(BinaryenModuleRef module) { - return static_cast(Builder(*(Module*)module).makeUnreachable()); + return static_cast( + ((Module*)module)->allocator.alloc()); } BinaryenExpressionRef BinaryenAtomicLoad(BinaryenModuleRef module, uint32_t bytes, @@ -1150,22 +1111,6 @@ .makeSIMDLoad( SIMDLoadOp(op), Address(offset), Address(align), (Expression*)ptr)); } -BinaryenExpressionRef BinaryenSIMDLoadStoreLane(BinaryenModuleRef module, - BinaryenOp op, - uint32_t offset, - uint32_t align, - uint8_t index, - BinaryenExpressionRef ptr, - BinaryenExpressionRef vec) { - return static_cast( - Builder(*(Module*)module) - .makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp(op), - Address(offset), - Address(align), - index, - (Expression*)ptr, - (Expression*)vec)); -} BinaryenExpressionRef BinaryenMemoryInit(BinaryenModuleRef module, uint32_t segment, BinaryenExpressionRef dest, @@ -1233,26 +1178,17 @@ return static_cast(Builder(*(Module*)module).makeRefNull(type_)); } -BinaryenExpressionRef BinaryenRefIs(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef value) { - return static_cast( - Builder(*(Module*)module).makeRefIs(RefIsOp(op), (Expression*)value)); -} - -BinaryenExpressionRef BinaryenRefAs(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef value) { +BinaryenExpressionRef BinaryenRefIsNull(BinaryenModuleRef module, + BinaryenExpressionRef value) { return static_cast( - Builder(*(Module*)module).makeRefAs(RefAsOp(op), (Expression*)value)); + Builder(*(Module*)module).makeRefIsNull((Expression*)value)); } BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module, const char* func, BinaryenType type) { - // TODO: consider changing the C API to receive a heap type Type type_(type); return static_cast( - Builder(*(Module*)module).makeRefFunc(func, type_.getHeapType())); + Builder(*(Module*)module).makeRefFunc(func, type_)); } BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module, @@ -1262,71 +1198,16 @@ Builder(*(Module*)module).makeRefEq((Expression*)left, (Expression*)right)); } -BinaryenExpressionRef BinaryenTableGet(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef index, - BinaryenType type) { - return static_cast( - Builder(*(Module*)module) - .makeTableGet(name, (Expression*)index, Type(type))); -} - -BinaryenExpressionRef BinaryenTableSet(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef index, - BinaryenExpressionRef value) { - return static_cast( - Builder(*(Module*)module) - .makeTableSet(name, (Expression*)index, (Expression*)value)); -} - -BinaryenExpressionRef BinaryenTableSize(BinaryenModuleRef module, - const char* name) { - return static_cast( - Builder(*(Module*)module).makeTableSize(name)); -} - -BinaryenExpressionRef BinaryenTableGrow(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef value, - BinaryenExpressionRef delta) { - if (value == nullptr) { - auto tableType = (*(Module*)module).getTableOrNull(name)->type; - value = BinaryenRefNull(module, (BinaryenType)tableType.getID()); - } - return static_cast( - Builder(*(Module*)module) - .makeTableGrow(name, (Expression*)value, (Expression*)delta)); -} - BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module, - const char* name, BinaryenExpressionRef body, - const char** catchTags, - BinaryenIndex numCatchTags, - BinaryenExpressionRef* catchBodies, - BinaryenIndex numCatchBodies, - const char* delegateTarget) { - auto* ret = ((Module*)module)->allocator.alloc(); - if (name) { - ret->name = name; - } - ret->body = (Expression*)body; - for (BinaryenIndex i = 0; i < numCatchTags; i++) { - ret->catchTags.push_back(catchTags[i]); - } - for (BinaryenIndex i = 0; i < numCatchBodies; i++) { - ret->catchBodies.push_back((Expression*)catchBodies[i]); - } - if (delegateTarget) { - ret->delegateTarget = delegateTarget; - } - ret->finalize(); - return static_cast(ret); + BinaryenExpressionRef catchBody) { + return static_cast( + Builder(*(Module*)module) + .makeTry((Expression*)body, (Expression*)catchBody)); } BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module, - const char* tag, + const char* event, BinaryenExpressionRef* operands, BinaryenIndex numOperands) { std::vector args; @@ -1334,13 +1215,24 @@ args.push_back((Expression*)operands[i]); } return static_cast( - Builder(*(Module*)module).makeThrow(tag, args)); + Builder(*(Module*)module).makeThrow(event, args)); } BinaryenExpressionRef BinaryenRethrow(BinaryenModuleRef module, - const char* target) { + BinaryenExpressionRef exnref) { return static_cast( - Builder(*(Module*)module).makeRethrow(target)); + Builder(*(Module*)module).makeRethrow((Expression*)exnref)); +} + +BinaryenExpressionRef BinaryenBrOnExn(BinaryenModuleRef module, + const char* name, + const char* eventName, + BinaryenExpressionRef exnref) { + auto* wasm = (Module*)module; + auto* event = wasm->getEventOrNull(eventName); + assert(event && "br_on_exn's event must exist"); + return static_cast( + Builder(*wasm).makeBrOnExn(name, event, (Expression*)exnref)); } BinaryenExpressionRef BinaryenI31New(BinaryenModuleRef module, @@ -1351,7 +1243,7 @@ BinaryenExpressionRef BinaryenI31Get(BinaryenModuleRef module, BinaryenExpressionRef i31, - bool signed_) { + int signed_) { return static_cast( Builder(*(Module*)module).makeI31Get((Expression*)i31, signed_ != 0)); } @@ -1689,12 +1581,12 @@ assert(expression->is()); return static_cast(expression)->operands.removeAt(index); } -bool BinaryenCallIsReturn(BinaryenExpressionRef expr) { +int BinaryenCallIsReturn(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->isReturn; } -void BinaryenCallSetReturn(BinaryenExpressionRef expr, bool isReturn) { +void BinaryenCallSetReturn(BinaryenExpressionRef expr, int isReturn) { auto* expression = (Expression*)expr; assert(expression->is()); static_cast(expression)->isReturn = isReturn != 0; @@ -1713,19 +1605,6 @@ assert(targetExpr); static_cast(expression)->target = (Expression*)targetExpr; } -const char* BinaryenCallIndirectGetTable(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->table.c_str(); -} -void BinaryenCallIndirectSetTable(BinaryenExpressionRef expr, - const char* table) { - Name name(table); - auto* expression = (Expression*)expr; - - assert(expression->is()); - static_cast(expression)->table = name; -} BinaryenIndex BinaryenCallIndirectGetNumOperands(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); @@ -1776,12 +1655,12 @@ assert(expression->is()); return static_cast(expression)->operands.removeAt(index); } -bool BinaryenCallIndirectIsReturn(BinaryenExpressionRef expr) { +int BinaryenCallIndirectIsReturn(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->isReturn; } -void BinaryenCallIndirectSetReturn(BinaryenExpressionRef expr, bool isReturn) { +void BinaryenCallIndirectSetReturn(BinaryenExpressionRef expr, int isReturn) { auto* expression = (Expression*)expr; assert(expression->is()); static_cast(expression)->isReturn = isReturn != 0; @@ -1789,28 +1668,24 @@ BinaryenType BinaryenCallIndirectGetParams(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); - return static_cast(expression) - ->heapType.getSignature() - .params.getID(); + return static_cast(expression)->sig.params.getID(); } void BinaryenCallIndirectSetParams(BinaryenExpressionRef expr, BinaryenType params) { - auto* call = ((Expression*)expr)->cast(); - call->heapType = - Signature(Type(params), call->heapType.getSignature().results); + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->sig.params = Type(params); } BinaryenType BinaryenCallIndirectGetResults(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); - return static_cast(expression) - ->heapType.getSignature() - .results.getID(); + return static_cast(expression)->sig.results.getID(); } void BinaryenCallIndirectSetResults(BinaryenExpressionRef expr, BinaryenType results) { - auto* call = ((Expression*)expr)->cast(); - call->heapType = - Signature(call->heapType.getSignature().params, Type(results)); + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->sig.results = Type(results); } // LocalGet BinaryenIndex BinaryenLocalGetGetIndex(BinaryenExpressionRef expr) { @@ -1824,7 +1699,7 @@ static_cast(expression)->index = index; } // LocalSet -bool BinaryenLocalSetIsTee(BinaryenExpressionRef expr) { +int BinaryenLocalSetIsTee(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->isTee(); @@ -1888,114 +1763,6 @@ assert(valueExpr); static_cast(expression)->value = (Expression*)valueExpr; } -// TableGet -const char* BinaryenTableGetGetTable(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->table.c_str(); -} -void BinaryenTableGetSetTable(BinaryenExpressionRef expr, const char* table) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(table); - static_cast(expression)->table = table; -} -BinaryenExpressionRef BinaryenTableGetGetIndex(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->index; -} -void BinaryenTableGetSetIndex(BinaryenExpressionRef expr, - BinaryenExpressionRef indexExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(indexExpr); - static_cast(expression)->index = (Expression*)indexExpr; -} -// TableSet -const char* BinaryenTableSetGetTable(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->table.c_str(); -} -void BinaryenTableSetSetTable(BinaryenExpressionRef expr, const char* table) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(table); - static_cast(expression)->table = table; -} -BinaryenExpressionRef BinaryenTableSetGetIndex(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->index; -} -void BinaryenTableSetSetIndex(BinaryenExpressionRef expr, - BinaryenExpressionRef indexExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(indexExpr); - static_cast(expression)->index = (Expression*)indexExpr; -} -BinaryenExpressionRef BinaryenTableSetGetValue(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->value; -} -void BinaryenTableSetSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(valueExpr); - static_cast(expression)->value = (Expression*)valueExpr; -} -// TableSize -const char* BinaryenTableSizeGetTable(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->table.c_str(); -} -void BinaryenTableSizeSetTable(BinaryenExpressionRef expr, const char* table) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(table); - static_cast(expression)->table = table; -} -// TableGrow -const char* BinaryenTableGrowGetTable(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->table.c_str(); -} -void BinaryenTableGrowSetTable(BinaryenExpressionRef expr, const char* table) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(table); - static_cast(expression)->table = table; -} -BinaryenExpressionRef BinaryenTableGrowGetValue(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->value; -} -void BinaryenTableGrowSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(valueExpr); - static_cast(expression)->value = (Expression*)valueExpr; -} -BinaryenExpressionRef BinaryenTableGrowGetDelta(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->delta; -} -void BinaryenTableGrowSetDelta(BinaryenExpressionRef expr, - BinaryenExpressionRef deltaExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(deltaExpr); - static_cast(expression)->delta = (Expression*)deltaExpr; -} // MemoryGrow BinaryenExpressionRef BinaryenMemoryGrowGetDelta(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; @@ -2010,22 +1777,22 @@ static_cast(expression)->delta = (Expression*)deltaExpr; } // Load -bool BinaryenLoadIsAtomic(BinaryenExpressionRef expr) { +int BinaryenLoadIsAtomic(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->isAtomic; } -void BinaryenLoadSetAtomic(BinaryenExpressionRef expr, bool isAtomic) { +void BinaryenLoadSetAtomic(BinaryenExpressionRef expr, int isAtomic) { auto* expression = (Expression*)expr; assert(expression->is()); static_cast(expression)->isAtomic = isAtomic != 0; } -bool BinaryenLoadIsSigned(BinaryenExpressionRef expr) { +int BinaryenLoadIsSigned(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->signed_; } -void BinaryenLoadSetSigned(BinaryenExpressionRef expr, bool isSigned) { +void BinaryenLoadSetSigned(BinaryenExpressionRef expr, int isSigned) { auto* expression = (Expression*)expr; assert(expression->is()); static_cast(expression)->signed_ = isSigned != 0; @@ -2073,12 +1840,12 @@ static_cast(expression)->ptr = (Expression*)ptrExpr; } // Store -bool BinaryenStoreIsAtomic(BinaryenExpressionRef expr) { +int BinaryenStoreIsAtomic(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->isAtomic; } -void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, bool isAtomic) { +void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, int isAtomic) { auto* expression = (Expression*)expr; assert(expression->is()); static_cast(expression)->isAtomic = isAtomic != 0; @@ -2795,81 +2562,6 @@ assert(ptrExpr); static_cast(expression)->ptr = (Expression*)ptrExpr; } -// SIMDLoadStoreLane -BinaryenOp BinaryenSIMDLoadStoreLaneGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->op; -} -void BinaryenSIMDLoadStoreLaneSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->op = SIMDLoadStoreLaneOp(op); -} -uint32_t BinaryenSIMDLoadStoreLaneGetOffset(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->offset; -} -void BinaryenSIMDLoadStoreLaneSetOffset(BinaryenExpressionRef expr, - uint32_t offset) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->offset = offset; -} -uint32_t BinaryenSIMDLoadStoreLaneGetAlign(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->align; -} -void BinaryenSIMDLoadStoreLaneSetAlign(BinaryenExpressionRef expr, - uint32_t align) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->align = align; -} -uint8_t BinaryenSIMDLoadStoreLaneGetIndex(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->index; -} -void BinaryenSIMDLoadStoreLaneSetIndex(BinaryenExpressionRef expr, - uint8_t index) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->index = index; -} -BinaryenExpressionRef -BinaryenSIMDLoadStoreLaneGetPtr(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->ptr; -} -void BinaryenSIMDLoadStoreLaneSetPtr(BinaryenExpressionRef expr, - BinaryenExpressionRef ptrExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(ptrExpr); - static_cast(expression)->ptr = (Expression*)ptrExpr; -} -BinaryenExpressionRef -BinaryenSIMDLoadStoreLaneGetVec(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->vec; -} -void BinaryenSIMDLoadStoreLaneSetVec(BinaryenExpressionRef expr, - BinaryenExpressionRef vecExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(vecExpr); - static_cast(expression)->vec = (Expression*)vecExpr; -} -bool BinaryenSIMDLoadStoreLaneIsStore(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->isStore(); -} // MemoryInit uint32_t BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; @@ -3003,51 +2695,18 @@ assert(sizeExpr); static_cast(expression)->size = (Expression*)sizeExpr; } -// RefIs -BinaryenOp BinaryenRefIsGetOp(BinaryenExpressionRef expr) { +// RefIsNull +BinaryenExpressionRef BinaryenRefIsNullGetValue(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->op; + assert(expression->is()); + return static_cast(expression)->value; } -void BinaryenRefIsSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->op = RefIsOp(op); -} -BinaryenExpressionRef BinaryenRefIsGetValue(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->value; -} -void BinaryenRefIsSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(valueExpr); - static_cast(expression)->value = (Expression*)valueExpr; -} -// RefAs -BinaryenOp BinaryenRefAsGetOp(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->op; -} -void BinaryenRefAsSetOp(BinaryenExpressionRef expr, BinaryenOp op) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->op = RefAsOp(op); -} -BinaryenExpressionRef BinaryenRefAsGetValue(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->value; -} -void BinaryenRefAsSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr) { +void BinaryenRefIsNullSetValue(BinaryenExpressionRef expr, + BinaryenExpressionRef valueExpr) { auto* expression = (Expression*)expr; - assert(expression->is()); + assert(expression->is()); assert(valueExpr); - static_cast(expression)->value = (Expression*)valueExpr; + static_cast(expression)->value = (Expression*)valueExpr; } // RefFunc const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr) { @@ -3084,16 +2743,6 @@ static_cast(expression)->right = (Expression*)right; } // Try -const char* BinaryenTryGetName(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->name.c_str(); -} -void BinaryenTrySetName(BinaryenExpressionRef expr, const char* name) { - auto* expression = (Expression*)expr; - assert(expression->is()); - static_cast(expression)->name = name; -} BinaryenExpressionRef BinaryenTryGetBody(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); @@ -3106,128 +2755,28 @@ assert(bodyExpr); static_cast(expression)->body = (Expression*)bodyExpr; } -BinaryenIndex BinaryenTryGetNumCatchTags(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->catchTags.size(); -} -BinaryenIndex BinaryenTryGetNumCatchBodies(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->catchBodies.size(); -} -const char* BinaryenTryGetCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(index < static_cast(expression)->catchTags.size()); - return static_cast(expression)->catchTags[index].c_str(); -} -void BinaryenTrySetCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index, - const char* catchTag) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(index < static_cast(expression)->catchTags.size()); - assert(catchTag); - static_cast(expression)->catchTags[index] = catchTag; -} -BinaryenIndex BinaryenTryAppendCatchTag(BinaryenExpressionRef expr, - const char* catchTag) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(catchTag); - auto& list = static_cast(expression)->catchTags; - auto index = list.size(); - list.push_back(catchTag); - return index; -} -void BinaryenTryInsertCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index, - const char* catchTag) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(catchTag); - static_cast(expression)->catchTags.insertAt(index, catchTag); -} -const char* BinaryenTryRemoveCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->catchTags.removeAt(index).c_str(); -} -BinaryenExpressionRef BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr, - BinaryenIndex index) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(index < static_cast(expression)->catchBodies.size()); - return static_cast(expression)->catchBodies[index]; -} -void BinaryenTrySetCatchBodyAt(BinaryenExpressionRef expr, - BinaryenIndex index, - BinaryenExpressionRef catchExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(index < static_cast(expression)->catchBodies.size()); - assert(catchExpr); - static_cast(expression)->catchBodies[index] = (Expression*)catchExpr; -} -BinaryenIndex BinaryenTryAppendCatchBody(BinaryenExpressionRef expr, - BinaryenExpressionRef catchExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(catchExpr); - auto& list = static_cast(expression)->catchBodies; - auto index = list.size(); - list.push_back((Expression*)catchExpr); - return index; -} -void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr, - BinaryenIndex index, - BinaryenExpressionRef catchExpr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - assert(catchExpr); - static_cast(expression) - ->catchBodies.insertAt(index, (Expression*)catchExpr); -} -BinaryenExpressionRef BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr, - BinaryenIndex index) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->catchBodies.removeAt(index); -} -bool BinaryenTryHasCatchAll(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->hasCatchAll(); -} -const char* BinaryenTryGetDelegateTarget(BinaryenExpressionRef expr) { - auto* expression = (Expression*)expr; - assert(expression->is()); - return static_cast(expression)->delegateTarget.c_str(); -} -void BinaryenTrySetDelegateTarget(BinaryenExpressionRef expr, - const char* delegateTarget) { +BinaryenExpressionRef BinaryenTryGetCatchBody(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); - static_cast(expression)->delegateTarget = delegateTarget; + return static_cast(expression)->catchBody; } -bool BinaryenTryIsDelegate(BinaryenExpressionRef expr) { +void BinaryenTrySetCatchBody(BinaryenExpressionRef expr, + BinaryenExpressionRef catchBodyExpr) { auto* expression = (Expression*)expr; assert(expression->is()); - return static_cast(expression)->isDelegate(); + assert(catchBodyExpr); + static_cast(expression)->catchBody = (Expression*)catchBodyExpr; } // Throw -const char* BinaryenThrowGetTag(BinaryenExpressionRef expr) { +const char* BinaryenThrowGetEvent(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); - return static_cast(expression)->tag.c_str(); + return static_cast(expression)->event.c_str(); } -void BinaryenThrowSetTag(BinaryenExpressionRef expr, const char* tagName) { +void BinaryenThrowSetEvent(BinaryenExpressionRef expr, const char* eventName) { auto* expression = (Expression*)expr; assert(expression->is()); - static_cast(expression)->tag = tagName; + static_cast(expression)->event = eventName; } BinaryenIndex BinaryenThrowGetNumOperands(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; @@ -3276,15 +2825,51 @@ return static_cast(expression)->operands.removeAt(index); } // Rethrow -const char* BinaryenRethrowGetTarget(BinaryenExpressionRef expr) { +BinaryenExpressionRef BinaryenRethrowGetExnref(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); - return static_cast(expression)->target.c_str(); + return static_cast(expression)->exnref; } -void BinaryenRethrowSetTarget(BinaryenExpressionRef expr, const char* target) { +void BinaryenRethrowSetExnref(BinaryenExpressionRef expr, + BinaryenExpressionRef exnrefExpr) { auto* expression = (Expression*)expr; assert(expression->is()); - static_cast(expression)->target = target; + assert(exnrefExpr); + static_cast(expression)->exnref = (Expression*)exnrefExpr; +} +// BrOnExn +const char* BinaryenBrOnExnGetEvent(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->event.c_str(); +} +void BinaryenBrOnExnSetEvent(BinaryenExpressionRef expr, + const char* eventName) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->event = eventName; +} +const char* BinaryenBrOnExnGetName(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->name.c_str(); +} +void BinaryenBrOnExnSetName(BinaryenExpressionRef expr, const char* name) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->name = name; +} +BinaryenExpressionRef BinaryenBrOnExnGetExnref(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast(expression)->exnref; +} +void BinaryenBrOnExnSetExnref(BinaryenExpressionRef expr, + BinaryenExpressionRef exnrefExpr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + assert(exnrefExpr); + static_cast(expression)->exnref = (Expression*)exnrefExpr; } // TupleMake BinaryenIndex BinaryenTupleMakeGetNumOperands(BinaryenExpressionRef expr) { @@ -3385,12 +2970,12 @@ assert(i31Expr); static_cast(expression)->i31 = (Expression*)i31Expr; } -bool BinaryenI31GetIsSigned(BinaryenExpressionRef expr) { +int BinaryenI31GetIsSigned(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); return static_cast(expression)->signed_; } -void BinaryenI31GetSetSigned(BinaryenExpressionRef expr, bool signed_) { +void BinaryenI31GetSetSigned(BinaryenExpressionRef expr, int signed_) { auto* expression = (Expression*)expr; assert(expression->is()); static_cast(expression)->signed_ = signed_ != 0; @@ -3407,8 +2992,7 @@ BinaryenExpressionRef body) { auto* ret = new Function; ret->setExplicitName(name); - // TODO: Take a HeapType rather than params and results. - ret->type = Signature(Type(params), Type(results)); + ret->sig = Signature(Type(params), Type(results)); for (BinaryenIndex i = 0; i < numVarTypes; i++) { ret->vars.push_back(Type(varTypes[i])); } @@ -3447,12 +3031,12 @@ BinaryenGlobalRef BinaryenAddGlobal(BinaryenModuleRef module, const char* name, BinaryenType type, - bool mutable_, + int8_t mutable_, BinaryenExpressionRef init) { auto* ret = new Global(); ret->setExplicitName(name); ret->type = Type(type); - ret->mutable_ = mutable_; + ret->mutable_ = !!mutable_; ret->init = (Expression*)init; ((Module*)module)->addGlobal(ret); return ret; @@ -3476,24 +3060,26 @@ return globals[index].get(); } -// Tags +// Events -BinaryenTagRef BinaryenAddTag(BinaryenModuleRef module, - const char* name, - BinaryenType params, - BinaryenType results) { - auto* ret = new Tag(); +BinaryenEventRef BinaryenAddEvent(BinaryenModuleRef module, + const char* name, + uint32_t attribute, + BinaryenType params, + BinaryenType results) { + auto* ret = new Event(); ret->setExplicitName(name); + ret->attribute = attribute; ret->sig = Signature(Type(params), Type(results)); - ((Module*)module)->addTag(ret); + ((Module*)module)->addEvent(ret); return ret; } -BinaryenTagRef BinaryenGetTag(BinaryenModuleRef module, const char* name) { - return ((Module*)module)->getTagOrNull(name); +BinaryenEventRef BinaryenGetEvent(BinaryenModuleRef module, const char* name) { + return ((Module*)module)->getEventOrNull(name); } -void BinaryenRemoveTag(BinaryenModuleRef module, const char* name) { - ((Module*)module)->removeTag(name); +void BinaryenRemoveEvent(BinaryenModuleRef module, const char* name) { + ((Module*)module)->removeEvent(name); } // Imports @@ -3508,19 +3094,16 @@ ret->name = internalName; ret->module = externalModuleName; ret->base = externalBaseName; - // TODO: Take a HeapType rather than params and results. - ret->type = Signature(Type(params), Type(results)); + ret->sig = Signature(Type(params), Type(results)); ((Module*)module)->addFunction(ret); } void BinaryenAddTableImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char* externalBaseName) { - auto table = std::make_unique(); - table->name = internalName; - table->module = externalModuleName; - table->base = externalBaseName; - ((Module*)module)->addTable(std::move(table)); + auto& table = ((Module*)module)->table; + table.module = externalModuleName; + table.base = externalBaseName; } void BinaryenAddMemoryImport(BinaryenModuleRef module, const char* internalName, @@ -3537,27 +3120,28 @@ const char* externalModuleName, const char* externalBaseName, BinaryenType globalType, - bool mutable_) { + int mutable_) { auto* ret = new Global(); ret->name = internalName; ret->module = externalModuleName; ret->base = externalBaseName; ret->type = Type(globalType); - ret->mutable_ = mutable_; + ret->mutable_ = mutable_ != 0; ((Module*)module)->addGlobal(ret); } -void BinaryenAddTagImport(BinaryenModuleRef module, - const char* internalName, - const char* externalModuleName, - const char* externalBaseName, - BinaryenType params, - BinaryenType results) { - auto* ret = new Tag(); +void BinaryenAddEventImport(BinaryenModuleRef module, + const char* internalName, + const char* externalModuleName, + const char* externalBaseName, + uint32_t attribute, + BinaryenType params, + BinaryenType results) { + auto* ret = new Event(); ret->name = internalName; ret->module = externalModuleName; ret->base = externalBaseName; ret->sig = Signature(Type(params), Type(results)); - ((Module*)module)->addTag(ret); + ((Module*)module)->addEvent(ret); } // Exports @@ -3607,13 +3191,13 @@ ((Module*)module)->addExport(ret); return ret; } -BinaryenExportRef BinaryenAddTagExport(BinaryenModuleRef module, - const char* internalName, - const char* externalName) { +BinaryenExportRef BinaryenAddEventExport(BinaryenModuleRef module, + const char* internalName, + const char* externalName) { auto* ret = new Export(); ret->value = internalName; ret->name = externalName; - ret->kind = ExternalKind::Tag; + ret->kind = ExternalKind::Event; ((Module*)module)->addExport(ret); return ret; } @@ -3636,110 +3220,57 @@ return exports[index].get(); } -BinaryenTableRef BinaryenAddTable(BinaryenModuleRef module, - const char* name, - BinaryenIndex initial, - BinaryenIndex maximum, - BinaryenType tableType) { - auto table = Builder::makeTable(name, Type(tableType), initial, maximum); - table->hasExplicitName = true; - return ((Module*)module)->addTable(std::move(table)); -} -void BinaryenRemoveTable(BinaryenModuleRef module, const char* table) { - ((Module*)module)->removeTable(table); -} -BinaryenIndex BinaryenGetNumTables(BinaryenModuleRef module) { - return ((Module*)module)->tables.size(); -} -BinaryenTableRef BinaryenGetTable(BinaryenModuleRef module, const char* name) { - return ((Module*)module)->getTableOrNull(name); -} -BinaryenTableRef BinaryenGetTableByIndex(BinaryenModuleRef module, - BinaryenIndex index) { - const auto& tables = ((Module*)module)->tables; - if (tables.size() <= index) { - Fatal() << "invalid table index."; - } - return tables[index].get(); -} -BinaryenElementSegmentRef -BinaryenAddActiveElementSegment(BinaryenModuleRef module, - const char* table, - const char* name, - const char** funcNames, - BinaryenIndex numFuncNames, - BinaryenExpressionRef offset) { - auto segment = std::make_unique(table, (Expression*)offset); - segment->setExplicitName(name); - for (BinaryenIndex i = 0; i < numFuncNames; i++) { - auto* func = ((Module*)module)->getFunctionOrNull(funcNames[i]); - if (func == nullptr) { - Fatal() << "invalid function '" << funcNames[i] << "'."; - } - segment->data.push_back( - Builder(*(Module*)module).makeRefFunc(funcNames[i], func->type)); - } - return ((Module*)module)->addElementSegment(std::move(segment)); -} -BinaryenElementSegmentRef -BinaryenAddPassiveElementSegment(BinaryenModuleRef module, - const char* name, - const char** funcNames, - BinaryenIndex numFuncNames) { - auto segment = std::make_unique(); - segment->setExplicitName(name); +// Function table. One per module + +void BinaryenSetFunctionTable(BinaryenModuleRef module, + BinaryenIndex initial, + BinaryenIndex maximum, + const char** funcNames, + BinaryenIndex numFuncNames, + BinaryenExpressionRef offset) { + Table::Segment segment((Expression*)offset); for (BinaryenIndex i = 0; i < numFuncNames; i++) { - auto* func = ((Module*)module)->getFunctionOrNull(funcNames[i]); - if (func == nullptr) { - Fatal() << "invalid function '" << funcNames[i] << "'."; - } - segment->data.push_back( - Builder(*(Module*)module).makeRefFunc(funcNames[i], func->type)); + segment.data.push_back(funcNames[i]); } - return ((Module*)module)->addElementSegment(std::move(segment)); -} -void BinaryenRemoveElementSegment(BinaryenModuleRef module, const char* name) { - ((Module*)module)->removeElementSegment(name); + auto& table = ((Module*)module)->table; + table.initial = initial; + table.max = maximum; + table.exists = true; + table.segments.push_back(segment); } -BinaryenElementSegmentRef BinaryenGetElementSegment(BinaryenModuleRef module, - const char* name) { - return ((Module*)module)->getElementSegmentOrNull(name); -} -BinaryenElementSegmentRef -BinaryenGetElementSegmentByIndex(BinaryenModuleRef module, - BinaryenIndex index) { - const auto& elementSegments = ((Module*)module)->elementSegments; - if (elementSegments.size() <= index) { - Fatal() << "invalid table index."; - } - return elementSegments[index].get(); + +int BinaryenIsFunctionTableImported(BinaryenModuleRef module) { + return ((Module*)module)->table.imported(); } -BinaryenIndex BinaryenGetNumElementSegments(BinaryenModuleRef module) { - return ((Module*)module)->elementSegments.size(); +BinaryenIndex BinaryenGetNumFunctionTableSegments(BinaryenModuleRef module) { + return ((Module*)module)->table.segments.size(); } BinaryenExpressionRef -BinaryenElementSegmentGetOffset(BinaryenElementSegmentRef elem) { - if (((ElementSegment*)elem)->table.isNull()) { - Fatal() << "elem segment is passive."; - } - return ((ElementSegment*)elem)->offset; -} -BinaryenIndex BinaryenElementSegmentGetLength(BinaryenElementSegmentRef elem) { - return ((ElementSegment*)elem)->data.size(); -} -const char* BinaryenElementSegmentGetData(BinaryenElementSegmentRef elem, - BinaryenIndex dataId) { - const auto& data = ((ElementSegment*)elem)->data; - if (data.size() <= dataId) { - Fatal() << "invalid segment data id."; - } - if (data[dataId]->is()) { - return NULL; - } else if (auto* get = data[dataId]->dynCast()) { - return get->func.c_str(); - } else { - Fatal() << "invalid expression in segment data."; +BinaryenGetFunctionTableSegmentOffset(BinaryenModuleRef module, + BinaryenIndex segmentId) { + const auto& segments = ((Module*)module)->table.segments; + if (segments.size() <= segmentId) { + Fatal() << "invalid function table segment id."; + } + return segments[segmentId].offset; +} +BinaryenIndex BinaryenGetFunctionTableSegmentLength(BinaryenModuleRef module, + BinaryenIndex segmentId) { + const auto& segments = ((Module*)module)->table.segments; + if (segments.size() <= segmentId) { + Fatal() << "invalid function table segment id."; + } + return segments[segmentId].data.size(); +} +const char* BinaryenGetFunctionTableSegmentData(BinaryenModuleRef module, + BinaryenIndex segmentId, + BinaryenIndex dataId) { + const auto& segments = ((Module*)module)->table.segments; + if (segments.size() <= segmentId || + segments[segmentId].data.size() <= dataId) { + Fatal() << "invalid function table segment or data id."; } + return segments[segmentId].data[dataId].c_str(); } // Memory. One per module @@ -3749,11 +3280,11 @@ BinaryenIndex maximum, const char* exportName, const char** segments, - bool* segmentPassive, + int8_t* segmentPassive, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, - bool shared) { + uint8_t shared) { auto* wasm = (Module*)module; wasm->memory.initial = initial; wasm->memory.max = int32_t(maximum); // Make sure -1 extends. @@ -3820,8 +3351,8 @@ } return segments[id].data.size(); } -bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module, - BinaryenIndex id) { +int BinaryenGetMemorySegmentPassive(BinaryenModuleRef module, + BinaryenIndex id) { const auto& segments = ((Module*)module)->memory.segments; if (segments.size() <= id) { Fatal() << "invalid segment id."; @@ -3891,8 +3422,8 @@ glue.emitPost(); } -bool BinaryenModuleValidate(BinaryenModuleRef module) { - return WasmValidator().validate(*(Module*)module); +int BinaryenModuleValidate(BinaryenModuleRef module) { + return WasmValidator().validate(*(Module*)module) ? 1 : 0; } void BinaryenModuleOptimize(BinaryenModuleRef module) { @@ -3902,10 +3433,6 @@ passRunner.run(); } -void BinaryenModuleUpdateMaps(BinaryenModuleRef module) { - ((Module*)module)->updateMaps(); -} - int BinaryenGetOptimizeLevel(void) { return globalPassOptions.optimizeLevel; } void BinaryenSetOptimizeLevel(int level) { @@ -3918,29 +3445,21 @@ globalPassOptions.shrinkLevel = level; } -bool BinaryenGetDebugInfo(void) { return globalPassOptions.debugInfo; } +int BinaryenGetDebugInfo(void) { return globalPassOptions.debugInfo; } -void BinaryenSetDebugInfo(bool on) { globalPassOptions.debugInfo = on != 0; } +void BinaryenSetDebugInfo(int on) { globalPassOptions.debugInfo = on != 0; } -bool BinaryenGetLowMemoryUnused(void) { +int BinaryenGetLowMemoryUnused(void) { return globalPassOptions.lowMemoryUnused; } -void BinaryenSetLowMemoryUnused(bool on) { +void BinaryenSetLowMemoryUnused(int on) { globalPassOptions.lowMemoryUnused = on != 0; } -bool BinaryenGetZeroFilledMemory(void) { - return globalPassOptions.zeroFilledMemory; -} - -void BinaryenSetZeroFilledMemory(bool on) { - globalPassOptions.zeroFilledMemory = on != 0; -} - -bool BinaryenGetFastMath(void) { return globalPassOptions.fastMath; } +int BinaryenGetFastMath(void) { return globalPassOptions.fastMath; } -void BinaryenSetFastMath(bool value) { globalPassOptions.fastMath = value; } +void BinaryenSetFastMath(int value) { globalPassOptions.fastMath = value != 0; } const char* BinaryenGetPassArgument(const char* key) { assert(key); @@ -3988,11 +3507,11 @@ globalPassOptions.inlining.oneCallerInlineMaxSize = size; } -bool BinaryenGetAllowInliningFunctionsWithLoops(void) { +int BinaryenGetAllowInliningFunctionsWithLoops(void) { return globalPassOptions.inlining.allowFunctionsWithLoops; } -void BinaryenSetAllowInliningFunctionsWithLoops(bool enabled) { +void BinaryenSetAllowInliningFunctionsWithLoops(int enabled) { globalPassOptions.inlining.allowFunctionsWithLoops = enabled; } @@ -4095,11 +3614,7 @@ char* BinaryenModuleAllocateAndWriteText(BinaryenModuleRef module) { std::stringstream ss; - bool colors = Colors::isEnabled(); - - Colors::setEnabled(false); // do not use colors for writing ss << *(Module*)module; - Colors::setEnabled(colors); // restore colors state const std::string out = ss.str(); const int len = out.length() + 1; @@ -4114,8 +3629,7 @@ buffer.resize(inputSize); std::copy_n(input, inputSize, buffer.begin()); try { - // TODO: allow providing features in the C API - WasmBinaryBuilder parser(*wasm, FeatureSet::MVP, buffer); + WasmBinaryBuilder parser(*wasm, buffer); parser.read(); } catch (ParseException& p) { p.dump(std::cerr); @@ -4126,7 +3640,7 @@ void BinaryenModuleInterpret(BinaryenModuleRef module) { ShellExternalInterface interface; - ModuleRunner instance(*(Module*)module, &interface, {}); + ModuleInstance instance(*(Module*)module, &interface); } BinaryenIndex BinaryenModuleAddDebugInfoFileName(BinaryenModuleRef module, @@ -4149,16 +3663,14 @@ // ========== Function Operations ========== // -// TODO: add BinaryenFunctionGetType - const char* BinaryenFunctionGetName(BinaryenFunctionRef func) { return ((Function*)func)->name.c_str(); } BinaryenType BinaryenFunctionGetParams(BinaryenFunctionRef func) { - return ((Function*)func)->getParams().getID(); + return ((Function*)func)->sig.params.getID(); } BinaryenType BinaryenFunctionGetResults(BinaryenFunctionRef func) { - return ((Function*)func)->getResults().getID(); + return ((Function*)func)->sig.results.getID(); } BinaryenIndex BinaryenFunctionGetNumVars(BinaryenFunctionRef func) { return ((Function*)func)->vars.size(); @@ -4172,8 +3684,8 @@ BinaryenIndex BinaryenFunctionGetNumLocals(BinaryenFunctionRef func) { return ((Function*)func)->getNumLocals(); } -bool BinaryenFunctionHasLocalName(BinaryenFunctionRef func, - BinaryenIndex index) { +int BinaryenFunctionHasLocalName(BinaryenFunctionRef func, + BinaryenIndex index) { return ((Function*)func)->hasLocalName(index); } const char* BinaryenFunctionGetLocalName(BinaryenFunctionRef func, @@ -4224,53 +3736,6 @@ } // -// =========== Table operations =========== -// - -const char* BinaryenTableGetName(BinaryenTableRef table) { - return ((Table*)table)->name.c_str(); -} -void BinaryenTableSetName(BinaryenTableRef table, const char* name) { - ((Table*)table)->name = name; -} -BinaryenIndex BinaryenTableGetInitial(BinaryenTableRef table) { - return ((Table*)table)->initial; -} -void BinaryenTableSetInitial(BinaryenTableRef table, BinaryenIndex initial) { - ((Table*)table)->initial = initial; -} -bool BinaryenTableHasMax(BinaryenTableRef table) { - return ((Table*)table)->hasMax(); -} -BinaryenIndex BinaryenTableGetMax(BinaryenTableRef table) { - return ((Table*)table)->max; -} -void BinaryenTableSetMax(BinaryenTableRef table, BinaryenIndex max) { - ((Table*)table)->max = max; -} - -// -// =========== ElementSegment operations =========== -// -const char* BinaryenElementSegmentGetName(BinaryenElementSegmentRef elem) { - return ((ElementSegment*)elem)->name.c_str(); -} -void BinaryenElementSegmentSetName(BinaryenElementSegmentRef elem, - const char* name) { - ((ElementSegment*)elem)->name = name; -} -const char* BinaryenElementSegmentGetTable(BinaryenElementSegmentRef elem) { - return ((ElementSegment*)elem)->table.c_str(); -} -void BinaryenElementSegmentSetTable(BinaryenElementSegmentRef elem, - const char* table) { - ((ElementSegment*)elem)->table = table; -} -bool BinaryenElementSegmentIsPassive(BinaryenElementSegmentRef elem) { - return ((ElementSegment*)elem)->table.isNull(); -} - -// // =========== Global operations =========== // @@ -4280,7 +3745,7 @@ BinaryenType BinaryenGlobalGetType(BinaryenGlobalRef global) { return ((Global*)global)->type.getID(); } -bool BinaryenGlobalIsMutable(BinaryenGlobalRef global) { +int BinaryenGlobalIsMutable(BinaryenGlobalRef global) { return ((Global*)global)->mutable_; } BinaryenExpressionRef BinaryenGlobalGetInitExpr(BinaryenGlobalRef global) { @@ -4288,18 +3753,21 @@ } // -// =========== Tag operations =========== +// =========== Event operations =========== // -const char* BinaryenTagGetName(BinaryenTagRef tag) { - return ((Tag*)tag)->name.c_str(); +const char* BinaryenEventGetName(BinaryenEventRef event) { + return ((Event*)event)->name.c_str(); +} +int BinaryenEventGetAttribute(BinaryenEventRef event) { + return ((Event*)event)->attribute; } -BinaryenType BinaryenTagGetParams(BinaryenTagRef tag) { - return ((Tag*)tag)->sig.params.getID(); +BinaryenType BinaryenEventGetParams(BinaryenEventRef event) { + return ((Event*)event)->sig.params.getID(); } -BinaryenType BinaryenTagGetResults(BinaryenTagRef tag) { - return ((Tag*)tag)->sig.results.getID(); +BinaryenType BinaryenEventGetResults(BinaryenEventRef event) { + return ((Event*)event)->sig.results.getID(); } // @@ -4314,14 +3782,6 @@ return ""; } } -const char* BinaryenTableImportGetModule(BinaryenTableRef import) { - auto* table = (Table*)import; - if (table->imported()) { - return table->module.c_str(); - } else { - return ""; - } -} const char* BinaryenGlobalImportGetModule(BinaryenGlobalRef import) { auto* global = (Global*)import; if (global->imported()) { @@ -4330,10 +3790,10 @@ return ""; } } -const char* BinaryenTagImportGetModule(BinaryenTagRef import) { - auto* tag = (Tag*)import; - if (tag->imported()) { - return tag->module.c_str(); +const char* BinaryenEventImportGetModule(BinaryenEventRef import) { + auto* event = (Event*)import; + if (event->imported()) { + return event->module.c_str(); } else { return ""; } @@ -4346,14 +3806,6 @@ return ""; } } -const char* BinaryenTableImportGetBase(BinaryenTableRef import) { - auto* table = (Table*)import; - if (table->imported()) { - return table->base.c_str(); - } else { - return ""; - } -} const char* BinaryenGlobalImportGetBase(BinaryenGlobalRef import) { auto* global = (Global*)import; if (global->imported()) { @@ -4362,10 +3814,10 @@ return ""; } } -const char* BinaryenTagImportGetBase(BinaryenTagRef import) { - auto* tag = (Tag*)import; - if (tag->imported()) { - return tag->base.c_str(); +const char* BinaryenEventImportGetBase(BinaryenEventRef import) { + auto* event = (Event*)import; + if (event->imported()) { + return event->base.c_str(); } else { return ""; } @@ -4437,22 +3889,10 @@ return static_cast( EffectAnalyzer::SideEffects::WritesMemory); } -BinaryenSideEffects BinaryenSideEffectReadsTable(void) { - return static_cast( - EffectAnalyzer::SideEffects::ReadsTable); -} -BinaryenSideEffects BinaryenSideEffectWritesTable(void) { - return static_cast( - EffectAnalyzer::SideEffects::WritesTable); -} BinaryenSideEffects BinaryenSideEffectImplicitTrap(void) { return static_cast( EffectAnalyzer::SideEffects::ImplicitTrap); } -BinaryenSideEffects BinaryenSideEffectTrapsNeverHappen(void) { - return static_cast( - EffectAnalyzer::SideEffects::TrapsNeverHappen); -} BinaryenSideEffects BinaryenSideEffectIsAtomic(void) { return static_cast( EffectAnalyzer::SideEffects::IsAtomic); @@ -4468,9 +3908,10 @@ return static_cast(EffectAnalyzer::SideEffects::Any); } -BinaryenSideEffects BinaryenExpressionGetSideEffects(BinaryenExpressionRef expr, - BinaryenModuleRef module) { - return EffectAnalyzer(globalPassOptions, *(Module*)module, (Expression*)expr) +BinaryenSideEffects +BinaryenExpressionGetSideEffects(BinaryenExpressionRef expr, + BinaryenFeatures features) { + return EffectAnalyzer(globalPassOptions, features, (Expression*)expr) .getSideEffects(); } @@ -4570,9 +4011,9 @@ new CExpressionRunner((Module*)module, flags, maxDepth, maxLoopIterations)); } -bool ExpressionRunnerSetLocalValue(ExpressionRunnerRef runner, - BinaryenIndex index, - BinaryenExpressionRef value) { +int ExpressionRunnerSetLocalValue(ExpressionRunnerRef runner, + BinaryenIndex index, + BinaryenExpressionRef value) { auto* R = (CExpressionRunner*)runner; auto setFlow = R->visit(value); if (!setFlow.breaking()) { @@ -4582,9 +4023,9 @@ return 0; } -bool ExpressionRunnerSetGlobalValue(ExpressionRunnerRef runner, - const char* name, - BinaryenExpressionRef value) { +int ExpressionRunnerSetGlobalValue(ExpressionRunnerRef runner, + const char* name, + BinaryenExpressionRef value) { auto* R = (CExpressionRunner*)runner; auto setFlow = R->visit(value); if (!setFlow.breaking()) { @@ -4614,11 +4055,15 @@ // ========= Utilities ========= // -void BinaryenSetColorsEnabled(bool enabled) { Colors::setEnabled(enabled); } +void BinaryenSetColorsEnabled(int enabled) { Colors::setEnabled(enabled); } -bool BinaryenAreColorsEnabled() { return Colors::isEnabled(); } +int BinaryenAreColorsEnabled() { return Colors::isEnabled(); } #ifdef __EMSCRIPTEN__ +// Override atexit - we don't need any global ctors to actually run, and +// otherwise we get clutter in the output in debug builds +int atexit(void (*function)(void)) { return 0; } + // Internal binaryen.js APIs // Returns the size of a Literal object. diff -Nru binaryen-108/src/binaryen-c.h binaryen-99/src/binaryen-c.h --- binaryen-108/src/binaryen-c.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/binaryen-c.h 2021-01-07 20:01:06.000000000 +0000 @@ -43,7 +43,6 @@ #ifndef wasm_binaryen_c_h #define wasm_binaryen_c_h -#include #include #include @@ -101,16 +100,16 @@ BINARYEN_API BinaryenType BinaryenTypeVec128(void); BINARYEN_API BinaryenType BinaryenTypeFuncref(void); BINARYEN_API BinaryenType BinaryenTypeExternref(void); +BINARYEN_API BinaryenType BinaryenTypeExnref(void); BINARYEN_API BinaryenType BinaryenTypeAnyref(void); BINARYEN_API BinaryenType BinaryenTypeEqref(void); BINARYEN_API BinaryenType BinaryenTypeI31ref(void); -BINARYEN_API BinaryenType BinaryenTypeDataref(void); BINARYEN_API BinaryenType BinaryenTypeUnreachable(void); // Not a real type. Used as the last parameter to BinaryenBlock to let // the API figure out the type instead of providing one. BINARYEN_API BinaryenType BinaryenTypeAuto(void); BINARYEN_API BinaryenType BinaryenTypeCreate(BinaryenType* valueTypes, - BinaryenIndex numTypes); + uint32_t numTypes); BINARYEN_API uint32_t BinaryenTypeArity(BinaryenType t); BINARYEN_API void BinaryenTypeExpand(BinaryenType t, BinaryenType* buf); @@ -130,7 +129,7 @@ #define DELEGATE(CLASS_TO_VISIT) \ BINARYEN_API BinaryenExpressionId Binaryen##CLASS_TO_VISIT##Id(void); -#include "wasm-delegations.def" +#include "wasm-delegations.h" // External kinds (call to get the value of each; you can cache them) @@ -140,7 +139,7 @@ BINARYEN_API BinaryenExternalKind BinaryenExternalTable(void); BINARYEN_API BinaryenExternalKind BinaryenExternalMemory(void); BINARYEN_API BinaryenExternalKind BinaryenExternalGlobal(void); -BINARYEN_API BinaryenExternalKind BinaryenExternalTag(void); +BINARYEN_API BinaryenExternalKind BinaryenExternalEvent(void); // Features. Call to get the value of each; you can cache them. Use bitwise // operators to combine and test particular features. @@ -160,9 +159,6 @@ BINARYEN_API BinaryenFeatures BinaryenFeatureMultivalue(void); BINARYEN_API BinaryenFeatures BinaryenFeatureGC(void); BINARYEN_API BinaryenFeatures BinaryenFeatureMemory64(void); -BINARYEN_API BinaryenFeatures BinaryenFeatureTypedFunctionReferences(void); -BINARYEN_API BinaryenFeatures BinaryenFeatureRelaxedSIMD(void); -BINARYEN_API BinaryenFeatures BinaryenFeatureExtendedConst(void); BINARYEN_API BinaryenFeatures BinaryenFeatureAll(void); // Modules @@ -196,6 +192,7 @@ double f64; uint8_t v128[16]; const char* func; + // TODO: exn }; }; @@ -411,12 +408,6 @@ BINARYEN_API BinaryenOp BinaryenLeUVecI32x4(void); BINARYEN_API BinaryenOp BinaryenGeSVecI32x4(void); BINARYEN_API BinaryenOp BinaryenGeUVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenEqVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenNeVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenLtSVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenGtSVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenLeSVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenGeSVecI64x2(void); BINARYEN_API BinaryenOp BinaryenEqVecF32x4(void); BINARYEN_API BinaryenOp BinaryenNeVecF32x4(void); BINARYEN_API BinaryenOp BinaryenLtVecF32x4(void); @@ -435,10 +426,10 @@ BINARYEN_API BinaryenOp BinaryenXorVec128(void); BINARYEN_API BinaryenOp BinaryenAndNotVec128(void); BINARYEN_API BinaryenOp BinaryenBitselectVec128(void); -BINARYEN_API BinaryenOp BinaryenAnyTrueVec128(void); -BINARYEN_API BinaryenOp BinaryenPopcntVecI8x16(void); +// TODO: Add i8x16.popcnt to C and JS APIs once merged to the proposal BINARYEN_API BinaryenOp BinaryenAbsVecI8x16(void); BINARYEN_API BinaryenOp BinaryenNegVecI8x16(void); +BINARYEN_API BinaryenOp BinaryenAnyTrueVecI8x16(void); BINARYEN_API BinaryenOp BinaryenAllTrueVecI8x16(void); BINARYEN_API BinaryenOp BinaryenBitmaskVecI8x16(void); BINARYEN_API BinaryenOp BinaryenShlVecI8x16(void); @@ -450,6 +441,7 @@ BINARYEN_API BinaryenOp BinaryenSubVecI8x16(void); BINARYEN_API BinaryenOp BinaryenSubSatSVecI8x16(void); BINARYEN_API BinaryenOp BinaryenSubSatUVecI8x16(void); +BINARYEN_API BinaryenOp BinaryenMulVecI8x16(void); BINARYEN_API BinaryenOp BinaryenMinSVecI8x16(void); BINARYEN_API BinaryenOp BinaryenMinUVecI8x16(void); BINARYEN_API BinaryenOp BinaryenMaxSVecI8x16(void); @@ -457,6 +449,7 @@ BINARYEN_API BinaryenOp BinaryenAvgrUVecI8x16(void); BINARYEN_API BinaryenOp BinaryenAbsVecI16x8(void); BINARYEN_API BinaryenOp BinaryenNegVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenAnyTrueVecI16x8(void); BINARYEN_API BinaryenOp BinaryenAllTrueVecI16x8(void); BINARYEN_API BinaryenOp BinaryenBitmaskVecI16x8(void); BINARYEN_API BinaryenOp BinaryenShlVecI16x8(void); @@ -474,13 +467,11 @@ BINARYEN_API BinaryenOp BinaryenMaxSVecI16x8(void); BINARYEN_API BinaryenOp BinaryenMaxUVecI16x8(void); BINARYEN_API BinaryenOp BinaryenAvgrUVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenQ15MulrSatSVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtMulLowSVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtMulHighSVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtMulLowUVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtMulHighUVecI16x8(void); +// TODO: Add i16x8.q15mulr_sat_s to C and JS APIs once merged to the proposal +// TODO: Add extending multiplications to APIs once they are merged as well BINARYEN_API BinaryenOp BinaryenAbsVecI32x4(void); BINARYEN_API BinaryenOp BinaryenNegVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenAnyTrueVecI32x4(void); BINARYEN_API BinaryenOp BinaryenAllTrueVecI32x4(void); BINARYEN_API BinaryenOp BinaryenBitmaskVecI32x4(void); BINARYEN_API BinaryenOp BinaryenShlVecI32x4(void); @@ -494,27 +485,18 @@ BINARYEN_API BinaryenOp BinaryenMaxSVecI32x4(void); BINARYEN_API BinaryenOp BinaryenMaxUVecI32x4(void); BINARYEN_API BinaryenOp BinaryenDotSVecI16x8ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtMulLowSVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtMulHighSVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtMulLowUVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtMulHighUVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenAbsVecI64x2(void); BINARYEN_API BinaryenOp BinaryenNegVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenAllTrueVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenBitmaskVecI64x2(void); BINARYEN_API BinaryenOp BinaryenShlVecI64x2(void); BINARYEN_API BinaryenOp BinaryenShrSVecI64x2(void); BINARYEN_API BinaryenOp BinaryenShrUVecI64x2(void); BINARYEN_API BinaryenOp BinaryenAddVecI64x2(void); BINARYEN_API BinaryenOp BinaryenSubVecI64x2(void); BINARYEN_API BinaryenOp BinaryenMulVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtMulLowSVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtMulHighSVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtMulLowUVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtMulHighUVecI64x2(void); BINARYEN_API BinaryenOp BinaryenAbsVecF32x4(void); BINARYEN_API BinaryenOp BinaryenNegVecF32x4(void); BINARYEN_API BinaryenOp BinaryenSqrtVecF32x4(void); +BINARYEN_API BinaryenOp BinaryenQFMAVecF32x4(void); +BINARYEN_API BinaryenOp BinaryenQFMSVecF32x4(void); BINARYEN_API BinaryenOp BinaryenAddVecF32x4(void); BINARYEN_API BinaryenOp BinaryenSubVecF32x4(void); BINARYEN_API BinaryenOp BinaryenMulVecF32x4(void); @@ -530,6 +512,8 @@ BINARYEN_API BinaryenOp BinaryenAbsVecF64x2(void); BINARYEN_API BinaryenOp BinaryenNegVecF64x2(void); BINARYEN_API BinaryenOp BinaryenSqrtVecF64x2(void); +BINARYEN_API BinaryenOp BinaryenQFMAVecF64x2(void); +BINARYEN_API BinaryenOp BinaryenQFMSVecF64x2(void); BINARYEN_API BinaryenOp BinaryenAddVecF64x2(void); BINARYEN_API BinaryenOp BinaryenSubVecF64x2(void); BINARYEN_API BinaryenOp BinaryenMulVecF64x2(void); @@ -542,65 +526,39 @@ BINARYEN_API BinaryenOp BinaryenFloorVecF64x2(void); BINARYEN_API BinaryenOp BinaryenTruncVecF64x2(void); BINARYEN_API BinaryenOp BinaryenNearestVecF64x2(void); -BINARYEN_API BinaryenOp BinaryenExtAddPairwiseSVecI8x16ToI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtAddPairwiseUVecI8x16ToI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtAddPairwiseSVecI16x8ToI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtAddPairwiseUVecI16x8ToI32x4(void); +// TODO: Add extending pairwise adds to C and JS APIs once merged BINARYEN_API BinaryenOp BinaryenTruncSatSVecF32x4ToVecI32x4(void); BINARYEN_API BinaryenOp BinaryenTruncSatUVecF32x4ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenTruncSatSVecF64x2ToVecI64x2(void); +BINARYEN_API BinaryenOp BinaryenTruncSatUVecF64x2ToVecI64x2(void); BINARYEN_API BinaryenOp BinaryenConvertSVecI32x4ToVecF32x4(void); BINARYEN_API BinaryenOp BinaryenConvertUVecI32x4ToVecF32x4(void); -BINARYEN_API BinaryenOp BinaryenLoad8SplatVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad16SplatVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad32SplatVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad64SplatVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad8x8SVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad8x8UVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad16x4SVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad16x4UVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad32x2SVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad32x2UVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad32ZeroVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad64ZeroVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad8LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad16LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad32LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenLoad64LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenStore8LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenStore16LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenStore32LaneVec128(void); -BINARYEN_API BinaryenOp BinaryenStore64LaneVec128(void); +BINARYEN_API BinaryenOp BinaryenConvertSVecI64x2ToVecF64x2(void); +BINARYEN_API BinaryenOp BinaryenConvertUVecI64x2ToVecF64x2(void); +BINARYEN_API BinaryenOp BinaryenLoadSplatVec8x16(void); +BINARYEN_API BinaryenOp BinaryenLoadSplatVec16x8(void); +BINARYEN_API BinaryenOp BinaryenLoadSplatVec32x4(void); +BINARYEN_API BinaryenOp BinaryenLoadSplatVec64x2(void); +BINARYEN_API BinaryenOp BinaryenLoadExtSVec8x8ToVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenLoadExtUVec8x8ToVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenLoadExtSVec16x4ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenLoadExtUVec16x4ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenLoadExtSVec32x2ToVecI64x2(void); +BINARYEN_API BinaryenOp BinaryenLoadExtUVec32x2ToVecI64x2(void); +// TODO: Add Load{32,64}Zero to C and JS APIs once merged to proposal BINARYEN_API BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void); BINARYEN_API BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void); BINARYEN_API BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void); BINARYEN_API BinaryenOp BinaryenNarrowUVecI32x4ToVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtendLowSVecI8x16ToVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtendHighSVecI8x16ToVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtendLowUVecI8x16ToVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtendHighUVecI8x16ToVecI16x8(void); -BINARYEN_API BinaryenOp BinaryenExtendLowSVecI16x8ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtendHighSVecI16x8ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtendLowUVecI16x8ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtendHighUVecI16x8ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenExtendLowSVecI32x4ToVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtendHighSVecI32x4ToVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtendLowUVecI32x4ToVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenExtendHighUVecI32x4ToVecI64x2(void); -BINARYEN_API BinaryenOp BinaryenConvertLowSVecI32x4ToVecF64x2(void); -BINARYEN_API BinaryenOp BinaryenConvertLowUVecI32x4ToVecF64x2(void); -BINARYEN_API BinaryenOp BinaryenTruncSatZeroSVecF64x2ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenTruncSatZeroUVecF64x2ToVecI32x4(void); -BINARYEN_API BinaryenOp BinaryenDemoteZeroVecF64x2ToVecF32x4(void); -BINARYEN_API BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void); -BINARYEN_API BinaryenOp BinaryenSwizzleVecI8x16(void); -BINARYEN_API BinaryenOp BinaryenRefIsNull(void); -BINARYEN_API BinaryenOp BinaryenRefIsFunc(void); -BINARYEN_API BinaryenOp BinaryenRefIsData(void); -BINARYEN_API BinaryenOp BinaryenRefIsI31(void); -BINARYEN_API BinaryenOp BinaryenRefAsNonNull(void); -BINARYEN_API BinaryenOp BinaryenRefAsFunc(void); -BINARYEN_API BinaryenOp BinaryenRefAsData(void); -BINARYEN_API BinaryenOp BinaryenRefAsI31(void); +BINARYEN_API BinaryenOp BinaryenWidenLowSVecI8x16ToVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenWidenHighSVecI8x16ToVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenWidenLowUVecI8x16ToVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenWidenHighUVecI8x16ToVecI16x8(void); +BINARYEN_API BinaryenOp BinaryenWidenLowSVecI16x8ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenWidenHighSVecI16x8ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenWidenLowUVecI16x8ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenWidenHighUVecI16x8ToVecI32x4(void); +BINARYEN_API BinaryenOp BinaryenSwizzleVec8x16(void); BINARYEN_REF(Expression); @@ -647,7 +605,6 @@ BinaryenType returnType); BINARYEN_API BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, - const char* table, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, @@ -661,7 +618,6 @@ BinaryenType returnType); BINARYEN_API BinaryenExpressionRef BinaryenReturnCallIndirect(BinaryenModuleRef module, - const char* table, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, @@ -700,7 +656,7 @@ // to bytes) BINARYEN_API BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, - bool signed_, + int8_t signed_, uint32_t offset, uint32_t align, BinaryenType type, @@ -813,14 +769,6 @@ uint32_t align, BinaryenExpressionRef ptr); BINARYEN_API BinaryenExpressionRef -BinaryenSIMDLoadStoreLane(BinaryenModuleRef module, - BinaryenOp op, - uint32_t offset, - uint32_t align, - uint8_t index, - BinaryenExpressionRef ptr, - BinaryenExpressionRef vec); -BINARYEN_API BinaryenExpressionRef BinaryenMemoryInit(BinaryenModuleRef module, uint32_t segment, BinaryenExpressionRef dest, @@ -840,51 +788,29 @@ BinaryenExpressionRef size); BINARYEN_API BinaryenExpressionRef BinaryenRefNull(BinaryenModuleRef module, BinaryenType type); -BINARYEN_API BinaryenExpressionRef BinaryenRefIs(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef value); -BINARYEN_API BinaryenExpressionRef BinaryenRefAs(BinaryenModuleRef module, - BinaryenOp op, - BinaryenExpressionRef value); +BINARYEN_API BinaryenExpressionRef +BinaryenRefIsNull(BinaryenModuleRef module, BinaryenExpressionRef value); BINARYEN_API BinaryenExpressionRef BinaryenRefFunc(BinaryenModuleRef module, const char* func, BinaryenType type); BINARYEN_API BinaryenExpressionRef BinaryenRefEq(BinaryenModuleRef module, BinaryenExpressionRef left, BinaryenExpressionRef right); -BINARYEN_API BinaryenExpressionRef BinaryenTableGet(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef index, - BinaryenType type); -BINARYEN_API BinaryenExpressionRef -BinaryenTableSet(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef index, - BinaryenExpressionRef value); -BINARYEN_API BinaryenExpressionRef BinaryenTableSize(BinaryenModuleRef module, - const char* name); -BINARYEN_API BinaryenExpressionRef -BinaryenTableGrow(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef value, - BinaryenExpressionRef delta); -// Try: name can be NULL. delegateTarget should be NULL in try-catch. -BINARYEN_API BinaryenExpressionRef -BinaryenTry(BinaryenModuleRef module, - const char* name, - BinaryenExpressionRef body, - const char** catchTags, - BinaryenIndex numCatchTags, - BinaryenExpressionRef* catchBodies, - BinaryenIndex numCatchBodies, - const char* delegateTarget); +BINARYEN_API BinaryenExpressionRef BinaryenTry(BinaryenModuleRef module, + BinaryenExpressionRef body, + BinaryenExpressionRef catchBody); BINARYEN_API BinaryenExpressionRef BinaryenThrow(BinaryenModuleRef module, - const char* tag, + const char* event, BinaryenExpressionRef* operands, BinaryenIndex numOperands); -BINARYEN_API BinaryenExpressionRef BinaryenRethrow(BinaryenModuleRef module, - const char* target); +BINARYEN_API BinaryenExpressionRef +BinaryenRethrow(BinaryenModuleRef module, BinaryenExpressionRef exnref); +BINARYEN_API BinaryenExpressionRef +BinaryenBrOnExn(BinaryenModuleRef module, + const char* name, + const char* eventName, + BinaryenExpressionRef exnref); BINARYEN_API BinaryenExpressionRef BinaryenTupleMake(BinaryenModuleRef module, BinaryenExpressionRef* operands, @@ -897,7 +823,7 @@ BinaryenExpressionRef value); BINARYEN_API BinaryenExpressionRef BinaryenI31Get(BinaryenModuleRef module, BinaryenExpressionRef i31, - bool signed_); + int signed_); // TODO (gc): ref.test // TODO (gc): ref.cast // TODO (gc): br_on_cast @@ -1098,10 +1024,10 @@ BINARYEN_API BinaryenExpressionRef BinaryenCallRemoveOperandAt(BinaryenExpressionRef expr, BinaryenIndex index); // Gets whether the specified `call` expression is a tail call. -BINARYEN_API bool BinaryenCallIsReturn(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenCallIsReturn(BinaryenExpressionRef expr); // Sets whether the specified `call` expression is a tail call. BINARYEN_API void BinaryenCallSetReturn(BinaryenExpressionRef expr, - bool isReturn); + int isReturn); // CallIndirect @@ -1112,12 +1038,6 @@ BINARYEN_API void BinaryenCallIndirectSetTarget(BinaryenExpressionRef expr, BinaryenExpressionRef targetExpr); -// Gets the table name of a `call_indirect` expression. -BINARYEN_API const char* -BinaryenCallIndirectGetTable(BinaryenExpressionRef expr); -// Sets the table name of a `call_indirect` expression. -BINARYEN_API void BinaryenCallIndirectSetTable(BinaryenExpressionRef expr, - const char* table); // Gets the number of operands of a `call_indirect` expression. BINARYEN_API BinaryenIndex BinaryenCallIndirectGetNumOperands(BinaryenExpressionRef expr); @@ -1148,10 +1068,10 @@ BINARYEN_API BinaryenExpressionRef BinaryenCallIndirectRemoveOperandAt( BinaryenExpressionRef expr, BinaryenIndex index); // Gets whether the specified `call_indirect` expression is a tail call. -BINARYEN_API bool BinaryenCallIndirectIsReturn(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenCallIndirectIsReturn(BinaryenExpressionRef expr); // Sets whether the specified `call_indirect` expression is a tail call. BINARYEN_API void BinaryenCallIndirectSetReturn(BinaryenExpressionRef expr, - bool isReturn); + int isReturn); // Gets the parameter types of the specified `call_indirect` expression. BINARYEN_API BinaryenType BinaryenCallIndirectGetParams(BinaryenExpressionRef expr); @@ -1177,7 +1097,7 @@ // Gets whether a `local.set` tees its value (is a `local.tee`). True if the // expression has a type other than `none`. -BINARYEN_API bool BinaryenLocalSetIsTee(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenLocalSetIsTee(BinaryenExpressionRef expr); // Gets the local index of a `local.set` or `local.tee` expression. BINARYEN_API BinaryenIndex BinaryenLocalSetGetIndex(BinaryenExpressionRef expr); // Sets the local index of a `local.set` or `local.tee` expression. @@ -1212,67 +1132,6 @@ BINARYEN_API void BinaryenGlobalSetSetValue(BinaryenExpressionRef expr, BinaryenExpressionRef valueExpr); -// TableGet - -// Gets the name of the table being accessed by a `table.get` expression. -BINARYEN_API const char* BinaryenTableGetGetTable(BinaryenExpressionRef expr); -// Sets the name of the table being accessed by a `table.get` expression. -BINARYEN_API void BinaryenTableGetSetTable(BinaryenExpressionRef expr, - const char* table); -// Gets the index expression of a `table.get` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenTableGetGetIndex(BinaryenExpressionRef expr); -// Sets the index expression of a `table.get` expression. -BINARYEN_API void BinaryenTableGetSetIndex(BinaryenExpressionRef expr, - BinaryenExpressionRef indexExpr); - -// TableSet - -// Gets the name of the table being accessed by a `table.set` expression. -BINARYEN_API const char* BinaryenTableSetGetTable(BinaryenExpressionRef expr); -// Sets the name of the table being accessed by a `table.set` expression. -BINARYEN_API void BinaryenTableSetSetTable(BinaryenExpressionRef expr, - const char* table); -// Gets the index expression of a `table.set` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenTableSetGetIndex(BinaryenExpressionRef expr); -// Sets the index expression of a `table.set` expression. -BINARYEN_API void BinaryenTableSetSetIndex(BinaryenExpressionRef expr, - BinaryenExpressionRef indexExpr); -// Gets the value expression of a `table.set` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenTableSetGetValue(BinaryenExpressionRef expr); -// Sets the value expression of a `table.set` expression. -BINARYEN_API void BinaryenTableSetSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr); - -// TableSize - -// Gets the name of the table being accessed by a `table.size` expression. -BINARYEN_API const char* BinaryenTableSizeGetTable(BinaryenExpressionRef expr); -// Sets the name of the table being accessed by a `table.size` expression. -BINARYEN_API void BinaryenTableSizeSetTable(BinaryenExpressionRef expr, - const char* table); - -// TableGrow - -// Gets the name of the table being accessed by a `table.grow` expression. -BINARYEN_API const char* BinaryenTableGrowGetTable(BinaryenExpressionRef expr); -// Sets the name of the table being accessed by a `table.grow` expression. -BINARYEN_API void BinaryenTableGrowSetTable(BinaryenExpressionRef expr, - const char* table); -// Gets the value expression of a `table.grow` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenTableGrowGetValue(BinaryenExpressionRef expr); -// Sets the value expression of a `table.grow` expression. -BINARYEN_API void BinaryenTableGrowSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr); -// Gets the delta of a `table.grow` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenTableGrowGetDelta(BinaryenExpressionRef expr); -// Sets the delta of a `table.grow` expression. -BINARYEN_API void BinaryenTableGrowSetDelta(BinaryenExpressionRef expr, - BinaryenExpressionRef deltaExpr); // MemoryGrow // Gets the delta of a `memory.grow` expression. @@ -1280,20 +1139,20 @@ BinaryenMemoryGrowGetDelta(BinaryenExpressionRef expr); // Sets the delta of a `memory.grow` expression. BINARYEN_API void BinaryenMemoryGrowSetDelta(BinaryenExpressionRef expr, - BinaryenExpressionRef deltaExpr); + BinaryenExpressionRef delta); // Load // Gets whether a `load` expression is atomic (is an `atomic.load`). -BINARYEN_API bool BinaryenLoadIsAtomic(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenLoadIsAtomic(BinaryenExpressionRef expr); // Sets whether a `load` expression is atomic (is an `atomic.load`). BINARYEN_API void BinaryenLoadSetAtomic(BinaryenExpressionRef expr, - bool isAtomic); + int isAtomic); // Gets whether a `load` expression operates on a signed value (`_s`). -BINARYEN_API bool BinaryenLoadIsSigned(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenLoadIsSigned(BinaryenExpressionRef expr); // Sets whether a `load` expression operates on a signed value (`_s`). BINARYEN_API void BinaryenLoadSetSigned(BinaryenExpressionRef expr, - bool isSigned); + int isSigned); // Gets the constant offset of a `load` expression. BINARYEN_API uint32_t BinaryenLoadGetOffset(BinaryenExpressionRef expr); // Sets the constant offset of a `load` expression. @@ -1319,10 +1178,10 @@ // Store // Gets whether a `store` expression is atomic (is an `atomic.store`). -BINARYEN_API bool BinaryenStoreIsAtomic(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenStoreIsAtomic(BinaryenExpressionRef expr); // Sets whether a `store` expression is atomic (is an `atomic.store`). BINARYEN_API void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, - bool isAtomic); + int isAtomic); // Gets the number of bytes stored by a `store` expression. BINARYEN_API uint32_t BinaryenStoreGetBytes(BinaryenExpressionRef expr); // Sets the number of bytes stored by a `store` expression. @@ -1733,50 +1592,6 @@ BINARYEN_API void BinaryenSIMDLoadSetPtr(BinaryenExpressionRef expr, BinaryenExpressionRef ptrExpr); -// SIMDLoadStoreLane - -// Gets the operation being performed by a SIMD load/store lane expression. -BINARYEN_API BinaryenOp -BinaryenSIMDLoadStoreLaneGetOp(BinaryenExpressionRef expr); -// Sets the operation being performed by a SIMD load/store lane expression. -BINARYEN_API void BinaryenSIMDLoadStoreLaneSetOp(BinaryenExpressionRef expr, - BinaryenOp op); -// Gets the constant offset of a SIMD load/store lane expression. -BINARYEN_API uint32_t -BinaryenSIMDLoadStoreLaneGetOffset(BinaryenExpressionRef expr); -// Sets the constant offset of a SIMD load/store lane expression. -BINARYEN_API void BinaryenSIMDLoadStoreLaneSetOffset(BinaryenExpressionRef expr, - uint32_t offset); -// Gets the byte alignment of a SIMD load/store lane expression. -BINARYEN_API uint32_t -BinaryenSIMDLoadStoreLaneGetAlign(BinaryenExpressionRef expr); -// Sets the byte alignment of a SIMD load/store lane expression. -BINARYEN_API void BinaryenSIMDLoadStoreLaneSetAlign(BinaryenExpressionRef expr, - uint32_t align); -// Gets the lane index of a SIMD load/store lane expression. -BINARYEN_API uint8_t -BinaryenSIMDLoadStoreLaneGetIndex(BinaryenExpressionRef expr); -// Sets the lane index of a SIMD load/store lane expression. -BINARYEN_API void BinaryenSIMDLoadStoreLaneSetIndex(BinaryenExpressionRef expr, - uint8_t index); -// Gets the pointer expression of a SIMD load/store lane expression. -BINARYEN_API BinaryenExpressionRef -BinaryenSIMDLoadStoreLaneGetPtr(BinaryenExpressionRef expr); -// Sets the pointer expression of a SIMD load/store lane expression. -BINARYEN_API void -BinaryenSIMDLoadStoreLaneSetPtr(BinaryenExpressionRef expr, - BinaryenExpressionRef ptrExpr); -// Gets the vector expression of a SIMD load/store lane expression. -BINARYEN_API BinaryenExpressionRef -BinaryenSIMDLoadStoreLaneGetVec(BinaryenExpressionRef expr); -// Sets the vector expression of a SIMD load/store lane expression. -BINARYEN_API void -BinaryenSIMDLoadStoreLaneSetVec(BinaryenExpressionRef expr, - BinaryenExpressionRef vecExpr); -// Gets whether a SIMD load/store lane expression performs a store. Otherwise it -// performs a load. -BINARYEN_API bool BinaryenSIMDLoadStoreLaneIsStore(BinaryenExpressionRef expr); - // MemoryInit // Gets the index of the segment being initialized by a `memory.init` @@ -1807,9 +1622,9 @@ // DataDrop -// Gets the index of the segment being dropped by a `data.drop` expression. +// Gets the index of the segment being dropped by a `memory.drop` expression. BINARYEN_API uint32_t BinaryenDataDropGetSegment(BinaryenExpressionRef expr); -// Sets the index of the segment being dropped by a `data.drop` expression. +// Sets the index of the segment being dropped by a `memory.drop` expression. BINARYEN_API void BinaryenDataDropSetSegment(BinaryenExpressionRef expr, uint32_t segmentIndex); @@ -1859,31 +1674,14 @@ BINARYEN_API void BinaryenMemoryFillSetSize(BinaryenExpressionRef expr, BinaryenExpressionRef sizeExpr); -// RefIs - -// Gets the operation performed by a `ref.is_*` expression. -BINARYEN_API BinaryenOp BinaryenRefIsGetOp(BinaryenExpressionRef expr); -// Sets the operation performed by a `ref.is_*` expression. -BINARYEN_API void BinaryenRefIsSetOp(BinaryenExpressionRef expr, BinaryenOp op); -// Gets the value expression tested by a `ref.is_*` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenRefIsGetValue(BinaryenExpressionRef expr); -// Sets the value expression tested by a `ref.is_*` expression. -BINARYEN_API void BinaryenRefIsSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr); +// RefIsNull -// RefAs - -// Gets the operation performed by a `ref.as_*` expression. -BINARYEN_API BinaryenOp BinaryenRefAsGetOp(BinaryenExpressionRef expr); -// Sets the operation performed by a `ref.as_*` expression. -BINARYEN_API void BinaryenRefAsSetOp(BinaryenExpressionRef expr, BinaryenOp op); -// Gets the value expression tested by a `ref.as_*` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenRefAsGetValue(BinaryenExpressionRef expr); -// Sets the value expression tested by a `ref.as_*` expression. -BINARYEN_API void BinaryenRefAsSetValue(BinaryenExpressionRef expr, - BinaryenExpressionRef valueExpr); +// Gets the value expression tested to be null of a `ref.is_null` expression. +BINARYEN_API BinaryenExpressionRef +BinaryenRefIsNullGetValue(BinaryenExpressionRef expr); +// Sets the value expression tested to be null of a `ref.is_null` expression. +BINARYEN_API void BinaryenRefIsNullSetValue(BinaryenExpressionRef expr, + BinaryenExpressionRef valueExpr); // RefFunc @@ -1910,83 +1708,26 @@ // Try -// Gets the name (label) of a `try` expression. -BINARYEN_API const char* BinaryenTryGetName(BinaryenExpressionRef expr); -// Sets the name (label) of a `try` expression. -BINARYEN_API void BinaryenTrySetName(BinaryenExpressionRef expr, - const char* name); // Gets the body expression of a `try` expression. BINARYEN_API BinaryenExpressionRef BinaryenTryGetBody(BinaryenExpressionRef expr); // Sets the body expression of a `try` expression. BINARYEN_API void BinaryenTrySetBody(BinaryenExpressionRef expr, BinaryenExpressionRef bodyExpr); -// Gets the number of catch blocks (= the number of catch tags) of a `try` -// expression. -BINARYEN_API BinaryenIndex -BinaryenTryGetNumCatchTags(BinaryenExpressionRef expr); -// Gets the number of catch/catch_all blocks of a `try` expression. -BINARYEN_API BinaryenIndex -BinaryenTryGetNumCatchBodies(BinaryenExpressionRef expr); -// Gets the catch tag at the specified index of a `try` expression. -BINARYEN_API const char* BinaryenTryGetCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index); -// Sets the catch tag at the specified index of a `try` expression. -BINARYEN_API void BinaryenTrySetCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index, - const char* catchTag); -// Appends a catch tag to a `try` expression, returning its insertion index. -BINARYEN_API BinaryenIndex BinaryenTryAppendCatchTag(BinaryenExpressionRef expr, - const char* catchTag); -// Inserts a catch tag at the specified index of a `try` expression, moving -// existing catch tags including the one previously at that index one index up. -BINARYEN_API void BinaryenTryInsertCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index, - const char* catchTag); -// Removes the catch tag at the specified index of a `try` expression, moving -// all subsequent catch tags one index down. Returns the tag. -BINARYEN_API const char* BinaryenTryRemoveCatchTagAt(BinaryenExpressionRef expr, - BinaryenIndex index); -// Gets the catch body expression at the specified index of a `try` expression. -BINARYEN_API BinaryenExpressionRef -BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index); -// Sets the catch body expression at the specified index of a `try` expression. -BINARYEN_API void BinaryenTrySetCatchBodyAt(BinaryenExpressionRef expr, - BinaryenIndex index, - BinaryenExpressionRef catchExpr); -// Appends a catch expression to a `try` expression, returning its insertion -// index. -BINARYEN_API BinaryenIndex BinaryenTryAppendCatchBody( - BinaryenExpressionRef expr, BinaryenExpressionRef catchExpr); -// Inserts a catch expression at the specified index of a `try` expression, -// moving existing catch bodies including the one previously at that index one -// index up. -BINARYEN_API void BinaryenTryInsertCatchBodyAt(BinaryenExpressionRef expr, - BinaryenIndex index, - BinaryenExpressionRef catchExpr); -// Removes the catch expression at the specified index of a `try` expression, -// moving all subsequent catch bodies one index down. Returns the catch -// expression. +// Gets the catch body expression of a `try` expression. BINARYEN_API BinaryenExpressionRef -BinaryenTryRemoveCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index); -// Gets whether a `try` expression has a catch_all clause. -BINARYEN_API bool BinaryenTryHasCatchAll(BinaryenExpressionRef expr); -// Gets the target label of a `delegate`. -BINARYEN_API const char* -BinaryenTryGetDelegateTarget(BinaryenExpressionRef expr); -// Sets the target label of a `delegate`. -BINARYEN_API void BinaryenTrySetDelegateTarget(BinaryenExpressionRef expr, - const char* delegateTarget); -// Gets whether a `try` expression is a try-delegate. -BINARYEN_API bool BinaryenTryIsDelegate(BinaryenExpressionRef expr); +BinaryenTryGetCatchBody(BinaryenExpressionRef expr); +// Sets the catch body expression of a `try` expression. +BINARYEN_API void BinaryenTrySetCatchBody(BinaryenExpressionRef expr, + BinaryenExpressionRef catchBodyExpr); // Throw -// Gets the name of the tag being thrown by a `throw` expression. -BINARYEN_API const char* BinaryenThrowGetTag(BinaryenExpressionRef expr); -// Sets the name of the tag being thrown by a `throw` expression. -BINARYEN_API void BinaryenThrowSetTag(BinaryenExpressionRef expr, - const char* tagName); +// Gets the name of the event being thrown by a `throw` expression. +BINARYEN_API const char* BinaryenThrowGetEvent(BinaryenExpressionRef expr); +// Sets the name of the event being thrown by a `throw` expression. +BINARYEN_API void BinaryenThrowSetEvent(BinaryenExpressionRef expr, + const char* eventName); // Gets the number of operands of a `throw` expression. BINARYEN_API BinaryenIndex BinaryenThrowGetNumOperands(BinaryenExpressionRef expr); @@ -2016,11 +1757,31 @@ // Rethrow -// Gets the target catch's corresponding try label of a `rethrow` expression. -BINARYEN_API const char* BinaryenRethrowGetTarget(BinaryenExpressionRef expr); -// Sets the target catch's corresponding try label of a `rethrow` expression. -BINARYEN_API void BinaryenRethrowSetTarget(BinaryenExpressionRef expr, - const char* target); +// Gets the exception reference expression of a `rethrow` expression. +BINARYEN_API BinaryenExpressionRef +BinaryenRethrowGetExnref(BinaryenExpressionRef expr); +// Sets the exception reference expression of a `rethrow` expression. +BINARYEN_API void BinaryenRethrowSetExnref(BinaryenExpressionRef expr, + BinaryenExpressionRef exnrefExpr); + +// BrOnExn + +// Gets the name of the event triggering a `br_on_exn` expression. +BINARYEN_API const char* BinaryenBrOnExnGetEvent(BinaryenExpressionRef expr); +// Sets the name of the event triggering a `br_on_exn` expression. +BINARYEN_API void BinaryenBrOnExnSetEvent(BinaryenExpressionRef expr, + const char* eventName); +// Gets the name (target label) of a `br_on_exn` expression. +BINARYEN_API const char* BinaryenBrOnExnGetName(BinaryenExpressionRef expr); +// Sets the name (target label) of a `br_on_exn` expression. +BINARYEN_API void BinaryenBrOnExnSetName(BinaryenExpressionRef expr, + const char* name); +// Gets the expression reference expression of a `br_on_exn` expression. +BINARYEN_API BinaryenExpressionRef +BinaryenBrOnExnGetExnref(BinaryenExpressionRef expr); +// Sets the expression reference expression of a `br_on_exn` expression. +BINARYEN_API void BinaryenBrOnExnSetExnref(BinaryenExpressionRef expr, + BinaryenExpressionRef exnrefExpr); // TupleMake @@ -2085,10 +1846,10 @@ BINARYEN_API void BinaryenI31GetSetI31(BinaryenExpressionRef expr, BinaryenExpressionRef i31Expr); // Gets whether an `i31.get` expression returns a signed value (`_s`). -BINARYEN_API bool BinaryenI31GetIsSigned(BinaryenExpressionRef expr); +BINARYEN_API int BinaryenI31GetIsSigned(BinaryenExpressionRef expr); // Sets whether an `i31.get` expression returns a signed value (`_s`). BINARYEN_API void BinaryenI31GetSetSigned(BinaryenExpressionRef expr, - bool signed_); + int signed_); // Functions @@ -2146,13 +1907,14 @@ const char* externalModuleName, const char* externalBaseName, BinaryenType globalType, - bool mutable_); -BINARYEN_API void BinaryenAddTagImport(BinaryenModuleRef module, - const char* internalName, - const char* externalModuleName, - const char* externalBaseName, - BinaryenType params, - BinaryenType results); + int mutable_); +BINARYEN_API void BinaryenAddEventImport(BinaryenModuleRef module, + const char* internalName, + const char* externalModuleName, + const char* externalBaseName, + uint32_t attribute, + BinaryenType params, + BinaryenType results); // Exports @@ -2174,10 +1936,10 @@ // Adds a global export to the module. BINARYEN_API BinaryenExportRef BinaryenAddGlobalExport( BinaryenModuleRef module, const char* internalName, const char* externalName); -// Adds a tag export to the module. -BINARYEN_API BinaryenExportRef BinaryenAddTagExport(BinaryenModuleRef module, - const char* internalName, - const char* externalName); +// Adds an event export to the module. +BINARYEN_API BinaryenExportRef BinaryenAddEventExport(BinaryenModuleRef module, + const char* internalName, + const char* externalName); // Gets an export reference by external name. Returns NULL if the export does // not exist. BINARYEN_API BinaryenExportRef BinaryenGetExport(BinaryenModuleRef module, @@ -2199,7 +1961,7 @@ BINARYEN_API BinaryenGlobalRef BinaryenAddGlobal(BinaryenModuleRef module, const char* name, BinaryenType type, - bool mutable_, + int8_t mutable_, BinaryenExpressionRef init); // Gets a global reference by name. Returns NULL if the global does not exist. BINARYEN_API BinaryenGlobalRef BinaryenGetGlobal(BinaryenModuleRef module, @@ -2213,77 +1975,56 @@ BINARYEN_API BinaryenGlobalRef BinaryenGetGlobalByIndex(BinaryenModuleRef module, BinaryenIndex index); -// Tags +// Events -BINARYEN_REF(Tag); +BINARYEN_REF(Event); -// Adds a tag to the module. -BINARYEN_API BinaryenTagRef BinaryenAddTag(BinaryenModuleRef module, - const char* name, - BinaryenType params, - BinaryenType results); -// Gets a tag reference by name. Returns NULL if the tag does not exist. -BINARYEN_API BinaryenTagRef BinaryenGetTag(BinaryenModuleRef module, - const char* name); -// Removes a tag by name. -BINARYEN_API void BinaryenRemoveTag(BinaryenModuleRef module, const char* name); - -// Tables - -BINARYEN_REF(Table); - -BINARYEN_API BinaryenTableRef BinaryenAddTable(BinaryenModuleRef module, - const char* table, - BinaryenIndex initial, - BinaryenIndex maximum, - BinaryenType tableType); -BINARYEN_API void BinaryenRemoveTable(BinaryenModuleRef module, - const char* table); -BINARYEN_API BinaryenIndex BinaryenGetNumTables(BinaryenModuleRef module); -BINARYEN_API BinaryenTableRef BinaryenGetTable(BinaryenModuleRef module, +// Adds an event to the module. +BINARYEN_API BinaryenEventRef BinaryenAddEvent(BinaryenModuleRef module, + const char* name, + uint32_t attribute, + BinaryenType params, + BinaryenType results); +// Gets an event reference by name. Returns NULL if the event does not exist. +BINARYEN_API BinaryenEventRef BinaryenGetEvent(BinaryenModuleRef module, const char* name); -BINARYEN_API BinaryenTableRef BinaryenGetTableByIndex(BinaryenModuleRef module, - BinaryenIndex index); - -// Elem segments +// Removes an event by name. +BINARYEN_API void BinaryenRemoveEvent(BinaryenModuleRef module, + const char* name); -BINARYEN_REF(ElementSegment); +// Function table. One per module -BINARYEN_API BinaryenElementSegmentRef -BinaryenAddActiveElementSegment(BinaryenModuleRef module, - const char* table, - const char* name, - const char** funcNames, - BinaryenIndex numFuncNames, - BinaryenExpressionRef offset); -BINARYEN_API BinaryenElementSegmentRef -BinaryenAddPassiveElementSegment(BinaryenModuleRef module, - const char* name, - const char** funcNames, - BinaryenIndex numFuncNames); -BINARYEN_API void BinaryenRemoveElementSegment(BinaryenModuleRef module, - const char* name); +// TODO: Add support for multiple segments in BinaryenSetFunctionTable. +BINARYEN_API void BinaryenSetFunctionTable(BinaryenModuleRef module, + BinaryenIndex initial, + BinaryenIndex maximum, + const char** funcNames, + BinaryenIndex numFuncNames, + BinaryenExpressionRef offset); +BINARYEN_API int BinaryenIsFunctionTableImported(BinaryenModuleRef module); BINARYEN_API BinaryenIndex -BinaryenGetNumElementSegments(BinaryenModuleRef module); -BINARYEN_API BinaryenElementSegmentRef -BinaryenGetElementSegment(BinaryenModuleRef module, const char* name); -BINARYEN_API BinaryenElementSegmentRef -BinaryenGetElementSegmentByIndex(BinaryenModuleRef module, BinaryenIndex index); +BinaryenGetNumFunctionTableSegments(BinaryenModuleRef module); +BINARYEN_API BinaryenExpressionRef BinaryenGetFunctionTableSegmentOffset( + BinaryenModuleRef module, BinaryenIndex segmentId); +BINARYEN_API BinaryenIndex BinaryenGetFunctionTableSegmentLength( + BinaryenModuleRef module, BinaryenIndex segmentId); +BINARYEN_API const char* BinaryenGetFunctionTableSegmentData( + BinaryenModuleRef module, BinaryenIndex segmentId, BinaryenIndex dataId); // Memory. One per module -// Each memory has data in segments, a start offset in segmentOffsets, and a +// Each segment has data in segments, a start offset in segmentOffsets, and a // size in segmentSizes. exportName can be NULL BINARYEN_API void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char** segments, - bool* segmentPassive, + int8_t* segmentPassive, BinaryenExpressionRef* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments, - bool shared); + uint8_t shared); // Memory segments. Query utilities. @@ -2292,8 +2033,8 @@ BinaryenGetMemorySegmentByteOffset(BinaryenModuleRef module, BinaryenIndex id); BINARYEN_API size_t BinaryenGetMemorySegmentByteLength(BinaryenModuleRef module, BinaryenIndex id); -BINARYEN_API bool BinaryenGetMemorySegmentPassive(BinaryenModuleRef module, - BinaryenIndex id); +BINARYEN_API int BinaryenGetMemorySegmentPassive(BinaryenModuleRef module, + BinaryenIndex id); BINARYEN_API void BinaryenCopyMemorySegmentData(BinaryenModuleRef module, BinaryenIndex id, char* buffer); @@ -2326,16 +2067,12 @@ // Validate a module, showing errors on problems. // @return 0 if an error occurred, 1 if validated succesfully -BINARYEN_API bool BinaryenModuleValidate(BinaryenModuleRef module); +BINARYEN_API int BinaryenModuleValidate(BinaryenModuleRef module); // Runs the standard optimization passes on the module. Uses the currently set // global optimize and shrink level. BINARYEN_API void BinaryenModuleOptimize(BinaryenModuleRef module); -// Updates the internal name mapping logic in a module. This must be called -// after renaming module elements. -BINARYEN_API void BinaryenModuleUpdateMaps(BinaryenModuleRef module); - // Gets the currently set optimize level. Applies to all modules, globally. // 0, 1, 2 correspond to -O0, -O1, -O2 (default), etc. BINARYEN_API int BinaryenGetOptimizeLevel(void); @@ -2354,36 +2091,29 @@ // Gets whether generating debug information is currently enabled or not. // Applies to all modules, globally. -BINARYEN_API bool BinaryenGetDebugInfo(void); +BINARYEN_API int BinaryenGetDebugInfo(void); // Enables or disables debug information in emitted binaries. // Applies to all modules, globally. -BINARYEN_API void BinaryenSetDebugInfo(bool on); +BINARYEN_API void BinaryenSetDebugInfo(int on); // Gets whether the low 1K of memory can be considered unused when optimizing. // Applies to all modules, globally. -BINARYEN_API bool BinaryenGetLowMemoryUnused(void); +BINARYEN_API int BinaryenGetLowMemoryUnused(void); // Enables or disables whether the low 1K of memory can be considered unused // when optimizing. Applies to all modules, globally. -BINARYEN_API void BinaryenSetLowMemoryUnused(bool on); - -// Gets whether to assume that an imported memory is zero-initialized. -BINARYEN_API bool BinaryenGetZeroFilledMemory(void); - -// Enables or disables whether to assume that an imported memory is -// zero-initialized. -BINARYEN_API void BinaryenSetZeroFilledMemory(bool on); +BINARYEN_API void BinaryenSetLowMemoryUnused(int on); // Gets whether fast math optimizations are enabled, ignoring for example // corner cases of floating-point math like NaN changes. // Applies to all modules, globally. -BINARYEN_API bool BinaryenGetFastMath(void); +BINARYEN_API int BinaryenGetFastMath(void); // Enables or disables fast math optimizations, ignoring for example // corner cases of floating-point math like NaN changes. // Applies to all modules, globally. -BINARYEN_API void BinaryenSetFastMath(bool value); +BINARYEN_API void BinaryenSetFastMath(int value); // Gets the value of the specified arbitrary pass argument. // Applies to all modules, globally. @@ -2423,11 +2153,11 @@ // Gets whether functions with loops are allowed to be inlined. // Applies to all modules, globally. -BINARYEN_API bool BinaryenGetAllowInliningFunctionsWithLoops(void); +BINARYEN_API int BinaryenGetAllowInliningFunctionsWithLoops(void); // Sets whether functions with loops are allowed to be inlined. // Applies to all modules, globally. -BINARYEN_API void BinaryenSetAllowInliningFunctionsWithLoops(bool enabled); +BINARYEN_API void BinaryenSetAllowInliningFunctionsWithLoops(int enabled); // Runs the specified passes on the module. Uses the currently set global // optimize and shrink level. @@ -2535,8 +2265,8 @@ BINARYEN_API BinaryenIndex BinaryenFunctionGetNumLocals(BinaryenFunctionRef func); // Tests if the local at the specified index has a name. -BINARYEN_API bool BinaryenFunctionHasLocalName(BinaryenFunctionRef func, - BinaryenIndex index); +BINARYEN_API int BinaryenFunctionHasLocalName(BinaryenFunctionRef func, + BinaryenIndex index); // Gets the name of the local at the specified index. BINARYEN_API const char* BinaryenFunctionGetLocalName(BinaryenFunctionRef func, BinaryenIndex index); @@ -2572,58 +2302,6 @@ BinaryenIndex columnNumber); // -// ========== Table Operations ========== -// - -// Gets the name of the specified `Table`. -BINARYEN_API const char* BinaryenTableGetName(BinaryenTableRef table); -// Sets the name of the specified `Table`. -BINARYEN_API void BinaryenTableSetName(BinaryenTableRef table, - const char* name); -// Gets the initial number of pages of the specified `Table`. -BINARYEN_API BinaryenIndex BinaryenTableGetInitial(BinaryenTableRef table); -// Sets the initial number of pages of the specified `Table`. -BINARYEN_API void BinaryenTableSetInitial(BinaryenTableRef table, - BinaryenIndex initial); -// Tests whether the specified `Table` has a maximum number of pages. -BINARYEN_API bool BinaryenTableHasMax(BinaryenTableRef table); -// Gets the maximum number of pages of the specified `Table`. -BINARYEN_API BinaryenIndex BinaryenTableGetMax(BinaryenTableRef table); -// Sets the maximum number of pages of the specified `Table`. -BINARYEN_API void BinaryenTableSetMax(BinaryenTableRef table, - BinaryenIndex max); - -// -// ========== Elem Segment Operations ========== -// - -// Gets the name of the specified `ElementSegment`. -BINARYEN_API const char* -BinaryenElementSegmentGetName(BinaryenElementSegmentRef elem); -// Sets the name of the specified `ElementSegment`. -BINARYEN_API void BinaryenElementSegmentSetName(BinaryenElementSegmentRef elem, - const char* name); -// Gets the table name of the specified `ElementSegment`. -BINARYEN_API const char* -BinaryenElementSegmentGetTable(BinaryenElementSegmentRef elem); -// Sets the table name of the specified `ElementSegment`. -BINARYEN_API void BinaryenElementSegmentSetTable(BinaryenElementSegmentRef elem, - const char* table); -// Gets the segment offset in case of active segments -BINARYEN_API BinaryenExpressionRef -BinaryenElementSegmentGetOffset(BinaryenElementSegmentRef elem); -// Gets the length of items in the segment -BINARYEN_API BinaryenIndex -BinaryenElementSegmentGetLength(BinaryenElementSegmentRef elem); -// Gets the item at the specified index -BINARYEN_API const char* -BinaryenElementSegmentGetData(BinaryenElementSegmentRef elem, - BinaryenIndex dataId); -// Returns true if the specified elem segment is passive -BINARYEN_API bool -BinaryenElementSegmentIsPassive(BinaryenElementSegmentRef elem); - -// // ========== Global Operations ========== // @@ -2633,21 +2311,23 @@ // be `NULL` if the signature is implicit. BINARYEN_API BinaryenType BinaryenGlobalGetType(BinaryenGlobalRef global); // Returns true if the specified `Global` is mutable. -BINARYEN_API bool BinaryenGlobalIsMutable(BinaryenGlobalRef global); +BINARYEN_API int BinaryenGlobalIsMutable(BinaryenGlobalRef global); // Gets the initialization expression of the specified `Global`. BINARYEN_API BinaryenExpressionRef BinaryenGlobalGetInitExpr(BinaryenGlobalRef global); // -// ========== Tag Operations ========== +// ========== Event Operations ========== // -// Gets the name of the specified `Tag`. -BINARYEN_API const char* BinaryenTagGetName(BinaryenTagRef tag); -// Gets the parameters type of the specified `Tag`. -BINARYEN_API BinaryenType BinaryenTagGetParams(BinaryenTagRef tag); -// Gets the results type of the specified `Tag`. -BINARYEN_API BinaryenType BinaryenTagGetResults(BinaryenTagRef tag); +// Gets the name of the specified `Event`. +BINARYEN_API const char* BinaryenEventGetName(BinaryenEventRef event); +// Gets the attribute of the specified `Event`. +BINARYEN_API int BinaryenEventGetAttribute(BinaryenEventRef event); +// Gets the parameters type of the specified `Event`. +BINARYEN_API BinaryenType BinaryenEventGetParams(BinaryenEventRef event); +// Gets the results type of the specified `Event`. +BINARYEN_API BinaryenType BinaryenEventGetResults(BinaryenEventRef event); // // ========== Import Operations ========== @@ -2656,16 +2336,14 @@ // Gets the external module name of the specified import. BINARYEN_API const char* BinaryenFunctionImportGetModule(BinaryenFunctionRef import); -BINARYEN_API const char* BinaryenTableImportGetModule(BinaryenTableRef import); BINARYEN_API const char* BinaryenGlobalImportGetModule(BinaryenGlobalRef import); -BINARYEN_API const char* BinaryenTagImportGetModule(BinaryenTagRef import); +BINARYEN_API const char* BinaryenEventImportGetModule(BinaryenEventRef import); // Gets the external base name of the specified import. BINARYEN_API const char* BinaryenFunctionImportGetBase(BinaryenFunctionRef import); -BINARYEN_API const char* BinaryenTableImportGetBase(BinaryenTableRef import); BINARYEN_API const char* BinaryenGlobalImportGetBase(BinaryenGlobalRef import); -BINARYEN_API const char* BinaryenTagImportGetBase(BinaryenTagRef import); +BINARYEN_API const char* BinaryenEventImportGetBase(BinaryenEventRef import); // // ========== Export Operations ========== @@ -2703,17 +2381,14 @@ BINARYEN_API BinaryenSideEffects BinaryenSideEffectWritesGlobal(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectReadsMemory(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectWritesMemory(void); -BINARYEN_API BinaryenSideEffects BinaryenSideEffectReadsTable(void); -BINARYEN_API BinaryenSideEffects BinaryenSideEffectWritesTable(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectImplicitTrap(void); -BINARYEN_API BinaryenSideEffects BinaryenSideEffectTrapsNeverHappen(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectIsAtomic(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectThrows(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectDanglingPop(void); BINARYEN_API BinaryenSideEffects BinaryenSideEffectAny(void); BINARYEN_API BinaryenSideEffects BinaryenExpressionGetSideEffects( - BinaryenExpressionRef expr, BinaryenModuleRef module); + BinaryenExpressionRef expr, BinaryenFeatures features); // // ========== CFG / Relooper ========== @@ -2819,17 +2494,17 @@ // effects. For example, if the expression also sets a local, this side effect // will also happen (not affected by any flags). Returns `true` if the // expression actually evaluates to a constant. -BINARYEN_API bool ExpressionRunnerSetLocalValue(ExpressionRunnerRef runner, - BinaryenIndex index, - BinaryenExpressionRef value); +BINARYEN_API int ExpressionRunnerSetLocalValue(ExpressionRunnerRef runner, + BinaryenIndex index, + BinaryenExpressionRef value); // Sets a known global value to use. Order matters if expressions have side // effects. For example, if the expression also sets a local, this side effect // will also happen (not affected by any flags). Returns `true` if the // expression actually evaluates to a constant. -BINARYEN_API bool ExpressionRunnerSetGlobalValue(ExpressionRunnerRef runner, - const char* name, - BinaryenExpressionRef value); +BINARYEN_API int ExpressionRunnerSetGlobalValue(ExpressionRunnerRef runner, + const char* name, + BinaryenExpressionRef value); // Runs the expression and returns the constant value expression it evaluates // to, if any. Otherwise returns `NULL`. Also disposes the runner. @@ -2841,10 +2516,10 @@ // // Enable or disable coloring for the Wasm printer -BINARYEN_API void BinaryenSetColorsEnabled(bool enabled); +BINARYEN_API void BinaryenSetColorsEnabled(int enabled); // Query whether color is enable for the Wasm printer -BINARYEN_API bool BinaryenAreColorsEnabled(); +BINARYEN_API int BinaryenAreColorsEnabled(); #ifdef __cplusplus } // extern "C" #endif diff -Nru binaryen-108/src/cfg/cfg-traversal.h binaryen-99/src/cfg/cfg-traversal.h --- binaryen-108/src/cfg/cfg-traversal.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/cfg/cfg-traversal.h 2021-01-07 20:01:06.000000000 +0000 @@ -30,7 +30,6 @@ #ifndef cfg_traversal_h #define cfg_traversal_h -#include "ir/branch-utils.h" #include "wasm-traversal.h" #include "wasm.h" @@ -46,37 +45,14 @@ std::vector out, in; }; - // The entry block at the function's start. This always exists. - BasicBlock* entry; - - // The exit block at the end, where control flow reaches the end of the - // function. If the function has a control flow path that flows out (that is, - // exits the function without a return or an unreachable or such), then that - // control flow path ends in this block. In particular, if the function flows - // out a value (as opposed to only returning values using an explicit return) - // then that value would be at the end of this block. - // Put another way, this block has a control flow edge out of the function, - // and that edge is not because of a return. (Hence an analysis that cares - // about reaching the end of the function must not only look for returns, but - // also the end of this block.) - // Note: It is possible for this block to not exist, if the function ends in - // a return or an unreachable. - BasicBlock* exit; + BasicBlock* entry; // the entry block // override this with code to create a BasicBlock if necessary BasicBlock* makeBasicBlock() { return new BasicBlock(); } // internal details - // The list of basic blocks in the function. - // - // This is populated in reverse postorder, that is, a block appears after all - // those that dominate it. This is trivial to do given wasm's structured - // control flow: we simply create blocks only after the things that can reach - // them (the only nontrivial things are loops, but if the dominator was before - // the loop, then again, we would have created it before the loop body). - std::vector> basicBlocks; - + std::vector> basicBlocks; // all the blocks // blocks that are the tops of loops, i.e., have backedges to them std::vector loopTops; @@ -93,34 +69,14 @@ std::vector ifStack; // stack of the first blocks of loops std::vector loopStack; - // stack of the last blocks of try bodies std::vector tryStack; - // Stack of the blocks that contain a throwing instruction, and therefore they - // can reach the first blocks of catches that throwing instructions should - // unwind to at any moment. That is, the topmost item in this vector relates - // to the current try-catch scope, and the vector there is a list of the items - // that can reach catch blocks (each item is assumed to be able to reach any - // of the catches, although that could be improved perhaps). - std::vector> throwingInstsStack; - // stack of 'Try' expressions corresponding to throwingInstsStack. - std::vector unwindExprStack; - // A stack for each try, where each entry is a list of blocks, one for each - // catch, used during processing. We start by assigning the start blocks to - // here, and then read those at the appropriate time; when we finish a catch - // we write to here the end block, so that when we finish with them all we can - // connect the ends to the outside. In principle two vectors could be used, - // but their usage does not overlap in time, and this is more efficient. - std::vector> processCatchStack; - - // Stack to store the catch indices within catch bodies. To be used in - // doStartCatch and doEndCatch. - std::vector catchIndexStack; + // stack of the first blocks of catch bodies + std::vector catchStack; - BasicBlock* startBasicBlock() { + void startBasicBlock() { currBasicBlock = ((SubType*)this)->makeBasicBlock(); basicBlocks.push_back(std::unique_ptr(currBasicBlock)); - return currBasicBlock; } void startUnreachableBlock() { currBasicBlock = nullptr; } @@ -163,14 +119,16 @@ static void doStartIfTrue(SubType* self, Expression** currp) { auto* last = self->currBasicBlock; - self->link(last, self->startBasicBlock()); // ifTrue + self->startBasicBlock(); + self->link(last, self->currBasicBlock); // ifTrue self->ifStack.push_back(last); // the block before the ifTrue } static void doStartIfFalse(SubType* self, Expression** currp) { self->ifStack.push_back(self->currBasicBlock); // the ifTrue fallthrough + self->startBasicBlock(); self->link(self->ifStack[self->ifStack.size() - 2], - self->startBasicBlock()); // before if -> ifFalse + self->currBasicBlock); // before if -> ifFalse } static void doEndIf(SubType* self, Expression** currp) { @@ -201,7 +159,8 @@ static void doEndLoop(SubType* self, Expression** currp) { auto* last = self->currBasicBlock; - self->link(last, self->startBasicBlock()); // fallthrough + self->startBasicBlock(); + self->link(last, self->currBasicBlock); // fallthrough auto* curr = (*currp)->cast(); // branches to the top of the loop if (curr->name.is()) { @@ -215,158 +174,90 @@ self->loopStack.pop_back(); } - static void doEndBranch(SubType* self, Expression** currp) { - auto* curr = *currp; - auto branchTargets = BranchUtils::getUniqueTargets(curr); - // Add branches to the targets. - for (auto target : branchTargets) { - self->branches[self->findBreakTarget(target)].push_back( - self->currBasicBlock); - } - if (curr->type != Type::unreachable) { + static void doEndBreak(SubType* self, Expression** currp) { + auto* curr = (*currp)->cast(); + self->branches[self->findBreakTarget(curr->name)].push_back( + self->currBasicBlock); // branch to the target + if (curr->condition) { auto* last = self->currBasicBlock; - self->link(last, self->startBasicBlock()); // we might fall through + self->startBasicBlock(); + self->link(last, self->currBasicBlock); // we might fall through } else { self->startUnreachableBlock(); } } - static void doEndThrowingInst(SubType* self, Expression** currp) { - // If the innermost try does not have a catch_all clause, an exception - // thrown can be caught by any of its outer catch block. And if that outer - // try-catch also does not have a catch_all, this continues until we - // encounter a try-catch_all. Create a link to all those possible catch - // unwind destinations. - // TODO This can be more precise for `throw`s if we compare tag types and - // create links to outer catch BBs only when the exception is not caught. - // TODO This can also be more precise if we analyze the structure of nested - // try-catches. For example, in the example below, 'call $foo' doesn't need - // a link to the BB of outer 'catch $e1', because if the exception thrown by - // the call is of tag $e1, it would've already been caught by the inner - // 'catch $e1'. Optimize these cases later. - // try - // try - // call $foo - // catch $e1 - // ... - // catch $e2 - // ... - // end - // catch $e1 - // ... - // catch $e3 - // ... - // end - assert(self->unwindExprStack.size() == self->throwingInstsStack.size()); - for (int i = self->throwingInstsStack.size() - 1; i >= 0;) { - auto* tryy = self->unwindExprStack[i]->template cast(); - if (tryy->isDelegate()) { - // If this delegates to the caller, there is no possibility that this - // instruction can throw to outer catches. - if (tryy->delegateTarget == DELEGATE_CALLER_TARGET) { - break; - } - // If this delegates to an outer try, we skip catches between this try - // and the target try. - bool found = false; - for (int j = i - 1; j >= 0; j--) { - if (self->unwindExprStack[j]->template cast()->name == - tryy->delegateTarget) { - i = j; - found = true; - break; - } - } - assert(found); - continue; - } - - // Exception thrown. Note outselves so that we will create a link to each - // catch within the try when we get there. - self->throwingInstsStack[i].push_back(self->currBasicBlock); - - // If this try has catch_all, there is no possibility that this - // instruction can throw to outer catches. Stop here. - if (tryy->hasCatchAll()) { - break; + static void doEndSwitch(SubType* self, Expression** currp) { + auto* curr = (*currp)->cast(); + // we might see the same label more than once; do not spam branches + std::set seen; + for (Name target : curr->targets) { + if (!seen.count(target)) { + self->branches[self->findBreakTarget(target)].push_back( + self->currBasicBlock); // branch to the target + seen.insert(target); } - i--; } + if (!seen.count(curr->default_)) { + self->branches[self->findBreakTarget(curr->default_)].push_back( + self->currBasicBlock); // branch to the target + } + self->startUnreachableBlock(); } static void doEndCall(SubType* self, Expression** currp) { - doEndThrowingInst(self, currp); - if (!self->throwingInstsStack.empty()) { - // exception not thrown. link to the continuation BB + // Every call can possibly throw, but we don't end the current basic block + // unless the call is within a try-catch, because the CFG will have too many + // blocks that way, and if an exception is thrown, the function will be + // exited anyway. + if (!self->catchStack.empty()) { auto* last = self->currBasicBlock; - self->link(last, self->startBasicBlock()); + self->startBasicBlock(); + self->link(last, self->currBasicBlock); // exception not thrown + self->link(last, self->catchStack.back()); // exception thrown } } static void doStartTry(SubType* self, Expression** currp) { - auto* curr = (*currp)->cast(); - self->throwingInstsStack.emplace_back(); - self->unwindExprStack.push_back(curr); - } - - static void doStartCatches(SubType* self, Expression** currp) { - self->tryStack.push_back(self->currBasicBlock); // last block of try body - - // Now that we are starting the catches, create the basic blocks that they - // begin with. auto* last = self->currBasicBlock; - auto* tryy = (*currp)->cast(); - self->processCatchStack.emplace_back(); - auto& entries = self->processCatchStack.back(); - for (Index i = 0; i < tryy->catchBodies.size(); i++) { - entries.push_back(self->startBasicBlock()); - } + self->startBasicBlock(); // catch body's first block + self->catchStack.push_back(self->currBasicBlock); self->currBasicBlock = last; // reset to the current block - - // Create links from things that reach those new basic blocks. - auto& preds = self->throwingInstsStack.back(); - for (auto* pred : preds) { - for (Index i = 0; i < entries.size(); i++) { - self->link(pred, entries[i]); - } - } - - self->throwingInstsStack.pop_back(); - self->unwindExprStack.pop_back(); - self->catchIndexStack.push_back(0); } static void doStartCatch(SubType* self, Expression** currp) { - // Get the block that starts this catch - self->currBasicBlock = - self->processCatchStack.back()[self->catchIndexStack.back()]; - } - - static void doEndCatch(SubType* self, Expression** currp) { - // We are done with this catch; set the block that ends it - self->processCatchStack.back()[self->catchIndexStack.back()] = - self->currBasicBlock; - self->catchIndexStack.back()++; + self->tryStack.push_back(self->currBasicBlock); // last block of try body + self->currBasicBlock = self->catchStack.back(); + self->catchStack.pop_back(); } static void doEndTry(SubType* self, Expression** currp) { + auto* last = self->currBasicBlock; self->startBasicBlock(); // continuation block after try-catch - // each catch body's last block -> continuation block - for (auto* last : self->processCatchStack.back()) { - self->link(last, self->currBasicBlock); - } + // catch body's last block -> continuation block + self->link(last, self->currBasicBlock); // try body's last block -> continuation block self->link(self->tryStack.back(), self->currBasicBlock); self->tryStack.pop_back(); - self->processCatchStack.pop_back(); - self->catchIndexStack.pop_back(); } static void doEndThrow(SubType* self, Expression** currp) { - doEndThrowingInst(self, currp); + // We unwind to the innermost catch, if any + if (!self->catchStack.empty()) { + self->link(self->currBasicBlock, self->catchStack.back()); + } self->startUnreachableBlock(); } + static void doEndBrOnExn(SubType* self, Expression** currp) { + auto* curr = (*currp)->cast(); + self->branches[self->findBreakTarget(curr->name)].push_back( + self->currBasicBlock); // branch to the target + auto* last = self->currBasicBlock; + self->startBasicBlock(); + self->link(last, self->currBasicBlock); // we might fall through + } + static void scan(SubType* self, Expression** currp) { Expression* curr = *currp; @@ -391,6 +282,22 @@ self->pushTask(SubType::doEndLoop, currp); break; } + case Expression::Id::BreakId: { + self->pushTask(SubType::doEndBreak, currp); + break; + } + case Expression::Id::SwitchId: { + self->pushTask(SubType::doEndSwitch, currp); + break; + } + case Expression::Id::ReturnId: { + self->pushTask(SubType::doStartUnreachableBlock, currp); + break; + } + case Expression::Id::UnreachableId: { + self->pushTask(SubType::doStartUnreachableBlock, currp); + break; + } case Expression::Id::CallId: case Expression::Id::CallIndirectId: { self->pushTask(SubType::doEndCall, currp); @@ -398,13 +305,8 @@ } case Expression::Id::TryId: { self->pushTask(SubType::doEndTry, currp); - auto& catchBodies = curr->cast()->catchBodies; - for (Index i = 0; i < catchBodies.size(); i++) { - self->pushTask(doEndCatch, currp); - self->pushTask(SubType::scan, &catchBodies[i]); - self->pushTask(doStartCatch, currp); - } - self->pushTask(SubType::doStartCatches, currp); + self->pushTask(SubType::scan, &curr->cast()->catchBody); + self->pushTask(SubType::doStartCatch, currp); self->pushTask(SubType::scan, &curr->cast()->body); self->pushTask(SubType::doStartTry, currp); return; // don't do anything else @@ -414,13 +316,11 @@ self->pushTask(SubType::doEndThrow, currp); break; } - default: { - if (Properties::isBranch(curr)) { - self->pushTask(SubType::doEndBranch, currp); - } else if (curr->type == Type::unreachable) { - self->pushTask(SubType::doStartUnreachableBlock, currp); - } + case Expression::Id::BrOnExnId: { + self->pushTask(SubType::doEndBrOnExn, currp); + break; } + default: {} } ControlFlowWalker::scan(self, currp); @@ -441,15 +341,12 @@ startBasicBlock(); entry = currBasicBlock; ControlFlowWalker::doWalkFunction(func); - exit = currBasicBlock; assert(branches.size() == 0); assert(ifStack.size() == 0); assert(loopStack.size() == 0); assert(tryStack.size() == 0); - assert(throwingInstsStack.size() == 0); - assert(unwindExprStack.size() == 0); - assert(processCatchStack.size() == 0); + assert(catchStack.size() == 0); } std::unordered_set findLiveBlocks() { @@ -511,8 +408,7 @@ generateDebugIds(); for (auto& block : basicBlocks) { assert(debugIds.count(block.get()) > 0); - std::cout << " block " << debugIds[block.get()] << " (" << block.get() - << "):\n"; + std::cout << " block " << debugIds[block.get()] << ":\n"; block->contents.dump(static_cast(this)->getFunction()); for (auto& in : block->in) { assert(debugIds.count(in) > 0); @@ -536,8 +432,8 @@ void checkDuplicates(std::vector& list) { std::unordered_set seen; for (auto* curr : list) { - auto res = seen.emplace(curr); - assert(res.second); + assert(seen.count(curr) == 0); + seen.insert(curr); } } diff -Nru binaryen-108/src/cfg/domtree.h binaryen-99/src/cfg/domtree.h --- binaryen-108/src/cfg/domtree.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/cfg/domtree.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Computes a dominator tree for a CFG graph, that is, for each block x we find -// the blocks y_i that must be reached before x on any path from the entry. Each -// block x has a single immediate dominator, the one closest to it, which forms -// a tree structure. -// -// This assumes the input is reducible. -// - -#ifndef domtree_h -#define domtree_h - -#include "cfg-traversal.h" -#include "wasm.h" - -namespace wasm { - -// -// DomTree receives an input CFG which has a list of basic blocks in reverse -// postorder. It generates the dominator tree by representing it as a vector of -// indexes, for each block giving the index of its parent (the immediate -// dominator) in the tree, that is, -// -// iDoms[0] = a nonsense value, as the entry node has no immediate dominator -// iDoms[1] = the index of the immediate dominator of CFG.blocks[1] -// iDoms[2] = the index of the immediate dominator of CFG.blocks[2] -// etc. -// -// The BasicBlock type is assumed to have a ".in" property which declares a -// vector of pointers to the incoming blocks, that is, the predecessors. -template struct DomTree { - std::vector iDoms; - - // Use a nonsense value to indicate what has yet to be initialized or what is - // irrelevant. - enum { nonsense = Index(-1) }; - - DomTree(std::vector>& blocks); -}; - -template -DomTree::DomTree(std::vector>& blocks) { - // Compute the dominator tree using the "engineered algorithm" in [1]. Minor - // differences in notation from the source include: - // - // * doms => iDoms. The final structure we emit is the vector of parents in - // the dominator tree, and that is our public interface, so name it - // explicitly as the immediate dominators. - // * Indexes are reversed. The paper uses postorder indexes, i.e., the entry - // node has the highest index, while we have a natural indexing since we - // traverse in reverse postorder anyhow (see cfg-traversal.h), that, is, - // the entry has the lowest index. - // * finger1, finger2 => left, right. - // * We assume the input is reducible, since wasm and Binaryen IR have that - // property. This simplifies some things, see below. - // - // Otherwise this is basically a direct implementation. - // - // [1] Cooper, Keith D.; Harvey, Timothy J; Kennedy, Ken (2001). "A Simple, - // Fast Dominance Algorithm" (PDF). - // http://www.hipersoft.rice.edu/grads/publications/dom14.pdf - - // If there are no blocks, we have nothing to do. - Index numBlocks = blocks.size(); - if (numBlocks == 0) { - return; - } - - // Map basic blocks to their indices. - std::unordered_map blockIndices; - for (Index i = 0; i < numBlocks; i++) { - blockIndices[blocks[i].get()] = i; - } - - // Initialize the iDoms array. The entry starts with its own index, which is - // used as a guard value in effect (we will never process it, and we will fix - // up this value at the very end). All other nodes start with a nonsense value - // that indicates they have yet to be processed. - iDoms.resize(numBlocks, nonsense); - iDoms[0] = 0; - - // Process the (non-entry) blocks in reverse postorder, computing the - // immediate dominators as we go. This returns whether we made any changes, - // which is used in an assertion later down. - auto processBlocks = [&]() { - bool changed = false; - for (Index index = 1; index < numBlocks; index++) { - // Loop over the predecessors. Our new parent is basically the - // intersection of all of theirs: our immediate dominator must precede all - // of them. - auto& preds = blocks[index]->in; - Index newParent = nonsense; - for (auto* pred : preds) { - auto predIndex = blockIndices[pred]; - - // In a reducible graph, we only need to care about the predecessors - // that appear before us in the reverse postorder numbering. The only - // predecessor that can appear *after* us is a loop backedge, but that - // will never dominate the loop - the loop is dominated by its single - // entry (since it is reducible, it has just one entry). - if (predIndex > index) { - continue; - } - - // All of our predecessors will have been processed before us, except - // if they are unreachable from the entry, in which case, we can ignore - // them. - if (iDoms[predIndex] == nonsense) { - continue; - } - - if (newParent == nonsense) { - // This is the first processed predecessor. - newParent = predIndex; - continue; - } - - // This is an additional predecessor. Intersect it, by going back to a - // node that definitely dominates both possibilities. Effectively, we - // keep decreasing the index backwards in the reverse postorder - // indexing until we stop (at the latest, in the entry). - auto left = newParent; - auto right = predIndex; - while (left != right) { - while (left > right) { - left = iDoms[left]; - } - while (right > left) { - right = iDoms[right]; - } - } - newParent = left; - } - - // Check if we found a new value here, and apply it. (We will normally - // always find a new value in the single pass that we run, but we also - // assert lower down that running another pass causes no further changes.) - if (newParent != iDoms[index]) { - iDoms[index] = newParent; - changed = true; - - // In reverse postorder the dominator cannot appear later. - assert(newParent <= index); - } - } - - return changed; - }; - - processBlocks(); - - // We must have finished all the work in a single traversal, since our input - // is reducible. - assert(!processBlocks()); - - // Finish up. The entry node has no dominator; mark that with a nonsense value - // which no one should use. - iDoms[0] = nonsense; -} - -} // namespace wasm - -#endif // domtree_h diff -Nru binaryen-108/src/cfg/liveness-traversal.h binaryen-99/src/cfg/liveness-traversal.h --- binaryen-108/src/cfg/liveness-traversal.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/cfg/liveness-traversal.h 2021-01-07 20:01:06.000000000 +0000 @@ -24,7 +24,6 @@ #include "cfg-traversal.h" #include "ir/utils.h" #include "support/sorted_vector.h" -#include "support/sparse_square_matrix.h" #include "wasm-builder.h" #include "wasm-traversal.h" #include "wasm.h" @@ -106,10 +105,10 @@ Index numLocals; std::unordered_set liveBlocks; - // access as a upper triangular matrix: i.e. when accessing a pair (i,j), - // should access the cell i < j. - sparse_square_matrix copies; - + // canonicalized - accesses should check (low, high) + // TODO: use a map for high N, as this tends to be sparse? or don't look at + // copies at all for big N? + std::vector copies; // total # of copies for each local, with all others std::vector totalCopies; @@ -119,27 +118,7 @@ auto* curr = (*currp)->cast(); // if in unreachable code, ignore if (!self->currBasicBlock) { - Builder builder(*self->getModule()); - auto* rep = builder.replaceWithIdenticalType(curr); - if (rep->is()) { - // We failed to replace the node with something simpler. This can happen - // if the local is non-nullable, for example. We still need to remove - // this node entirely, however, as it is unreachable and so we will not - // see it in the analysis we perform (for example, we may be changing - // local indexes). Replace it with something completely different, even - // if it is larger, a block with a forced type that has unreachable - // contents, - // - // (block (result X) - // (unreachable)) - // - // That pattern lets us set any type we wish. - // - // TODO: Make a helper function for this, if it is useful in other - // places. - rep = builder.makeBlock({builder.makeUnreachable()}, curr->type); - } - *currp = rep; + *currp = Builder(*self->getModule()).replaceWithIdenticalType(curr); return; } self->currBasicBlock->contents.actions.emplace_back( @@ -192,13 +171,30 @@ return nullptr; } + // If there are too many locals, we cannot run currently as + // numLocals * numLocals might overflow. We may want to add an option for + // a sparse matrix at some point TODO + bool canRun(Function* func) { + Index numLocals = func->getNumLocals(); + if (uint64_t(numLocals) * uint64_t(numLocals) <= + std::numeric_limits::max()) { + return true; + } + std::cerr << "warning: too many locals (" << numLocals + << ") to run liveness analysis in " << this->getFunction()->name + << '\n'; + return false; + } + // main entry point void doWalkFunction(Function* func) { numLocals = func->getNumLocals(); - copies.recreate(numLocals); - totalCopies.clear(); + assert(canRun(func)); + copies.resize(numLocals * numLocals); + std::fill(copies.begin(), copies.end(), 0); totalCopies.resize(numLocals); + std::fill(totalCopies.begin(), totalCopies.end(), 0); // create the CFG by walking the IR CFGWalker::doWalkFunction(func); // ignore links to dead blocks, so they don't confuse us and we can see @@ -281,19 +277,14 @@ } void addCopy(Index i, Index j) { - if (j > i) { - std::swap(i, j); - } - copies.set(i, j, std::min(copies.get(i, j), uint8_t(254)) + 1); + auto k = std::min(i, j) * numLocals + std::max(i, j); + copies[k] = std::min(copies[k], uint8_t(254)) + 1; totalCopies[i]++; totalCopies[j]++; } uint8_t getCopies(Index i, Index j) { - if (j > i) { - std::swap(i, j); - } - return copies.get(i, j); + return copies[std::min(i, j) * numLocals + std::max(i, j)]; } }; diff -Nru binaryen-108/src/cfg/Relooper.cpp binaryen-99/src/cfg/Relooper.cpp --- binaryen-108/src/cfg/Relooper.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/cfg/Relooper.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -62,7 +62,9 @@ if (!Multiple) { break; } - for (auto& [Id, Body] : Multiple->InnerMap) { + for (auto& iter : Multiple->InnerMap) { + int Id = iter.first; + Shape* Body = iter.second; Curr->name = Builder.getBlockBreakName(Id); Curr->finalize(); // it may now be reachable, via a break auto* Outer = Builder.makeBlock(Curr); @@ -220,13 +222,13 @@ Block* DefaultTarget = nullptr; // Find the default target, the one without a condition - for (auto& [Target, Details] : ProcessedBranchesOut) { - if ((!SwitchCondition && !Details->Condition) || - (SwitchCondition && !Details->SwitchValues)) { + for (auto& iter : ProcessedBranchesOut) { + if ((!SwitchCondition && !iter.second->Condition) || + (SwitchCondition && !iter.second->SwitchValues)) { assert(!DefaultTarget && "block has branches without a default (nullptr for the " "condition)"); // Must be exactly one default // nullptr - DefaultTarget = Target; + DefaultTarget = iter.first; } } // Since each Block* must* branch somewhere, this must be set @@ -336,7 +338,9 @@ auto* Outer = Builder.makeBlock(); auto* Inner = Outer; std::vector Table; - for (auto& [Target, Details] : ProcessedBranchesOut) { + for (auto& iter : ProcessedBranchesOut) { + Block* Target = iter.first; + Branch* Details = iter.second; wasm::Name CurrName; if (Details->SwitchValues) { CurrName = wasm::Name(Base + "$case$" + std::to_string(Target->Id)); @@ -431,9 +435,9 @@ wasm::If* FirstIf = nullptr; wasm::If* CurrIf = nullptr; std::vector finalizeStack; - for (auto& [Id, Body] : InnerMap) { - auto* Now = - Builder.makeIf(Builder.makeCheckLabel(Id), Body->Render(Builder, InLoop)); + for (auto& iter : InnerMap) { + auto* Now = Builder.makeIf(Builder.makeCheckLabel(iter.first), + iter.second->Render(Builder, InLoop)); finalizeStack.push_back(Now); if (!CurrIf) { FirstIf = CurrIf = Now; @@ -606,7 +610,8 @@ void CanonicalizeCode() { for (auto& Block : Parent->Blocks) { Block->Code = Canonicalize(Block->Code); - for (auto& [_, Branch] : Block->BranchesOut) { + for (auto& iter : Block->BranchesOut) { + auto* Branch = iter.second; if (Branch->Code) { Branch->Code = Canonicalize(Branch->Code); } @@ -642,7 +647,7 @@ Next = Replacement = NextNext; // If we've already seen this, stop - it's an infinite loop of // empty blocks we can skip through. - if (!Seen.emplace(Replacement).second) { + if (Seen.count(Replacement)) { // Stop here. Note that if we started from X and ended up with X // once more, then Replacement == First and so lower down we // will not report that we did any work, avoiding an infinite @@ -650,6 +655,7 @@ break; } else { // Otherwise, keep going. + Seen.insert(Replacement); continue; } } @@ -692,10 +698,12 @@ if (ParentBlock->BranchesOut.size() >= 2) { std::unordered_map> HashedBranchesOut; std::vector BlocksToErase; - for (auto& [CurrBlock, CurrBranch] : ParentBlock->BranchesOut) { + for (auto& iter : ParentBlock->BranchesOut) { + Block* CurrBlock = iter.first; #if RELOOPER_OPTIMIZER_DEBUG std::cout << " consider child " << CurrBlock->Id << '\n'; #endif + Branch* CurrBranch = iter.second; if (CurrBranch->Code) { // We can't merge code; ignore continue; @@ -704,7 +712,9 @@ auto& HashedSiblings = HashedBranchesOut[HashValue]; // Check if we are equivalent to any of them - if so, merge us. bool Merged = false; - for (auto& [SiblingBranch, SiblingBlock] : HashedSiblings) { + for (auto& Pair : HashedSiblings) { + Branch* SiblingBranch = Pair.first; + Block* SiblingBlock = Pair.second; if (HaveEquivalentContents(CurrBlock, SiblingBlock)) { #if RELOOPER_OPTIMIZER_DEBUG std::cout << " equiv! to " << SiblingBlock->Id << '\n'; @@ -799,8 +809,8 @@ } else { // If the block has no switch, the branches must not as well. #ifndef NDEBUG - for (auto& [_, CurrBranch] : ParentBlock->BranchesOut) { - assert(!CurrBranch->SwitchValues); + for (auto& iter : ParentBlock->BranchesOut) { + assert(!iter.second->SwitchValues); } #endif } @@ -913,7 +923,9 @@ if (A->BranchesOut.size() != B->BranchesOut.size()) { return false; } - for (auto& [ABlock, ABranch] : A->BranchesOut) { + for (auto& aiter : A->BranchesOut) { + Block* ABlock = aiter.first; + Branch* ABranch = aiter.second; if (B->BranchesOut.count(ABlock) == 0) { return false; } @@ -1018,11 +1030,11 @@ wasm::ExpressionAnalyzer::hash(Curr->SwitchCondition)); } wasm::rehash(digest, uint8_t(2)); - for (auto& [CurrBlock, CurrBranch] : Curr->BranchesOut) { + for (auto& Pair : Curr->BranchesOut) { // Hash the Block* as a pointer TODO: full hash? - wasm::rehash(digest, reinterpret_cast(CurrBlock)); + wasm::rehash(digest, reinterpret_cast(Pair.first)); // Hash the Branch info properly - wasm::hash_combine(digest, Hash(CurrBranch)); + wasm::hash_combine(digest, Hash(Pair.second)); } return digest; } @@ -1065,8 +1077,8 @@ if (!contains(Live.Live, Curr)) { continue; } - for (auto& [CurrBlock, _] : Curr->BranchesOut) { - CurrBlock->BranchesIn.insert(Curr); + for (auto& iter : Curr->BranchesOut) { + iter.first->BranchesIn.insert(Curr); } } @@ -1080,9 +1092,9 @@ void GetBlocksOut(Block* Source, BlockSet& Entries, BlockSet* LimitTo = nullptr) { - for (auto& [CurrBlock, _] : Source->BranchesOut) { - if (!LimitTo || contains(*LimitTo, CurrBlock)) { - Entries.insert(CurrBlock); + for (auto& iter : Source->BranchesOut) { + if (!LimitTo || contains(*LimitTo, iter.first)) { + Entries.insert(iter.first); } } } @@ -1162,7 +1174,8 @@ assert(InnerBlocks.size() > 0); for (auto* Curr : InnerBlocks) { - for (auto& [Possible, _] : Curr->BranchesOut) { + for (auto& iter : Curr->BranchesOut) { + Block* Possible = iter.first; if (!contains(InnerBlocks, Possible)) { NextEntries.insert(Possible); } @@ -1276,7 +1289,8 @@ // may have been seen before and invalidated already if (Ownership[Invalidatee]) { Ownership[Invalidatee] = nullptr; - for (auto& [Target, _] : Invalidatee->BranchesOut) { + for (auto& iter : Invalidatee->BranchesOut) { + Block* Target = iter.first; auto Known = Ownership.find(Target); if (Known != Ownership.end()) { Block* TargetOwner = Known->second; @@ -1316,7 +1330,8 @@ continue; } // Add all children - for (auto& [New, _] : Curr->BranchesOut) { + for (auto& iter : Curr->BranchesOut) { + Block* New = iter.first; auto Known = Helper.Ownership.find(New); if (Known == Helper.Ownership.end()) { // New node. Add it, and put it in the queue @@ -1389,7 +1404,9 @@ IndependentGroups.size()); MultipleShape* Multiple = Parent->AddMultipleShape(); BlockSet CurrEntries; - for (auto& [CurrEntry, CurrBlocks] : IndependentGroups) { + for (auto& iter : IndependentGroups) { + Block* CurrEntry = iter.first; + BlockSet& CurrBlocks = iter.second; PrintDebug(" multiple group with entry %d:\n", CurrEntry->Id); DebugDump(CurrBlocks, " "); // Create inner block @@ -1546,7 +1563,8 @@ bool DeadEnd = true; BlockSet& SmallGroup = IndependentGroups[SmallEntry]; for (auto* Curr : SmallGroup) { - for (auto& [Target, _] : Curr->BranchesOut) { + for (auto& iter : Curr->BranchesOut) { + Block* Target = iter.first; if (!contains(SmallGroup, Target)) { DeadEnd = false; break; @@ -1667,8 +1685,8 @@ printf("<< Simple with block %d\n", Simple->Inner->Id); } else if (MultipleShape* Multiple = Shape::IsMultiple(S)) { printf("<< Multiple\n"); - for (auto& [Entry, _] : Multiple->InnerMap) { - printf(" with entry %d\n", Entry); + for (auto& iter : Multiple->InnerMap) { + printf(" with entry %d\n", iter.first); } } else if (Shape::IsLoop(S)) { printf("<< Loop\n"); diff -Nru binaryen-108/src/cfg/Relooper.h binaryen-99/src/cfg/Relooper.h --- binaryen-108/src/cfg/Relooper.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/cfg/Relooper.h 2021-01-07 20:01:06.000000000 +0000 @@ -37,7 +37,6 @@ #include #include -#include "support/insert_ordered.h" #include "wasm-builder.h" #include "wasm.h" @@ -124,8 +123,121 @@ Render(RelooperBuilder& Builder, Block* Target, bool SetLabel); }; -typedef wasm::InsertOrderedSet BlockSet; -typedef wasm::InsertOrderedMap BlockBranchMap; +// like std::set, except that begin() -> end() iterates in the +// order that elements were added to the set (not in the order +// of operator<(T, T)) +template struct InsertOrderedSet { + std::map::iterator> Map; + std::list List; + + typedef typename std::list::iterator iterator; + iterator begin() { return List.begin(); } + iterator end() { return List.end(); } + + void erase(const T& val) { + auto it = Map.find(val); + if (it != Map.end()) { + List.erase(it->second); + Map.erase(it); + } + } + + void erase(iterator position) { + Map.erase(*position); + List.erase(position); + } + + // cheating a bit, not returning the iterator + void insert(const T& val) { + auto it = Map.find(val); + if (it == Map.end()) { + List.push_back(val); + Map.insert(std::make_pair(val, --List.end())); + } + } + + size_t size() const { return Map.size(); } + bool empty() const { return Map.empty(); } + + void clear() { + Map.clear(); + List.clear(); + } + + size_t count(const T& val) const { return Map.count(val); } + + InsertOrderedSet() = default; + InsertOrderedSet(const InsertOrderedSet& other) { *this = other; } + InsertOrderedSet& operator=(const InsertOrderedSet& other) { + clear(); + for (auto i : other.List) { + insert(i); // inserting manually creates proper iterators + } + return *this; + } +}; + +// like std::map, except that begin() -> end() iterates in the +// order that elements were added to the map (not in the order +// of operator<(Key, Key)) +template struct InsertOrderedMap { + std::map>::iterator> Map; + std::list> List; + + T& operator[](const Key& k) { + auto it = Map.find(k); + if (it == Map.end()) { + List.push_back(std::make_pair(k, T())); + auto e = --List.end(); + Map.insert(std::make_pair(k, e)); + return e->second; + } + return it->second->second; + } + + typedef typename std::list>::iterator iterator; + iterator begin() { return List.begin(); } + iterator end() { return List.end(); } + + void erase(const Key& k) { + auto it = Map.find(k); + if (it != Map.end()) { + List.erase(it->second); + Map.erase(it); + } + } + + void erase(iterator position) { erase(position->first); } + + void clear() { + Map.clear(); + List.clear(); + } + + void swap(InsertOrderedMap& Other) { + Map.swap(Other.Map); + List.swap(Other.List); + } + + size_t size() const { return Map.size(); } + bool empty() const { return Map.empty(); } + size_t count(const Key& k) const { return Map.count(k); } + + InsertOrderedMap() = default; + InsertOrderedMap(InsertOrderedMap& other) { + abort(); // TODO, watch out for iterators + } + InsertOrderedMap& operator=(const InsertOrderedMap& other) { + abort(); // TODO, watch out for iterators + } + bool operator==(const InsertOrderedMap& other) { + return Map == other.Map && List == other.List; + } + bool operator!=(const InsertOrderedMap& other) { return !(*this == other); } +}; + +typedef InsertOrderedSet BlockSet; +typedef InsertOrderedMap BlockBranchMap; // Represents a basic block of code - some instructions that end with a // control flow modifier (a branch, return or throw). @@ -313,7 +425,7 @@ void SetMinSize(bool MinSize_) { MinSize = MinSize_; } }; -typedef wasm::InsertOrderedMap BlockBlockSetMap; +typedef InsertOrderedMap BlockBlockSetMap; #ifdef RELOOPER_DEBUG struct Debugging { diff -Nru binaryen-108/src/compiler-support.h binaryen-99/src/compiler-support.h --- binaryen-108/src/compiler-support.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/compiler-support.h 2021-01-07 20:01:06.000000000 +0000 @@ -31,6 +31,14 @@ #define WASM_BUILTIN_UNREACHABLE __assume(false) #endif +#ifdef __GNUC__ +#define WASM_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define WASM_NORETURN __declspec(noreturn) +#else +#define WASM_NORETURN +#endif + // The code might contain TODOs or stubs that read some values but do nothing // with them. The compiler might fail with [-Werror,-Wunused-variable]. // The WASM_UNUSED(varible) is a wrapper that helps to suppress the error. diff -Nru binaryen-108/src/dataflow/graph.h binaryen-99/src/dataflow/graph.h --- binaryen-108/src/dataflow/graph.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/dataflow/graph.h 2021-01-07 20:01:06.000000000 +0000 @@ -31,7 +31,9 @@ #include "ir/literal-utils.h" #include "wasm.h" -namespace wasm::DataFlow { +namespace wasm { + +namespace DataFlow { // Main logic to generate IR for a function. This is implemented as a // visitor on the wasm, where visitors return a Node* that either @@ -226,7 +228,8 @@ return doVisitUnreachable(unreachable); } else if (auto* drop = curr->dynCast()) { return doVisitDrop(drop); - } else if (curr->is() || curr->is() || curr->is()) { + } else if (curr->is() || curr->is() || curr->is() || + curr->is()) { Fatal() << "DataFlow does not support EH instructions yet"; } else { return doVisitGeneric(curr); @@ -795,6 +798,8 @@ const Name FAKE_CALL = "fake$dfo$call"; }; -} // namespace wasm::DataFlow +} // namespace DataFlow + +} // namespace wasm #endif // wasm_dataflow_graph_h diff -Nru binaryen-108/src/dataflow/node.h binaryen-99/src/dataflow/node.h --- binaryen-108/src/dataflow/node.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/dataflow/node.h 2021-01-07 20:01:06.000000000 +0000 @@ -28,7 +28,9 @@ #include "ir/utils.h" #include "wasm.h" -namespace wasm::DataFlow { +namespace wasm { + +namespace DataFlow { // // The core IR representation in DataFlow: a Node. @@ -181,12 +183,10 @@ } break; } - case Cond: { + case Cond: if (index != other.index) { return false; } - break; - } default: {} } if (values.size() != other.values.size()) { @@ -216,6 +216,8 @@ } }; -} // namespace wasm::DataFlow +} // namespace DataFlow + +} // namespace wasm #endif // wasm_dataflow_node diff -Nru binaryen-108/src/dataflow/users.h binaryen-99/src/dataflow/users.h --- binaryen-108/src/dataflow/users.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/dataflow/users.h 2021-01-07 20:01:06.000000000 +0000 @@ -27,7 +27,9 @@ #include "dataflow/graph.h" -namespace wasm::DataFlow { +namespace wasm { + +namespace DataFlow { // Calculates the users of each node. // users[x] = { y, z, .. } @@ -93,6 +95,8 @@ void removeAllUsesOf(Node* node) { users.erase(node); } }; -} // namespace wasm::DataFlow +} // namespace DataFlow + +} // namespace wasm #endif // wasm_dataflow_users diff -Nru binaryen-108/src/dataflow/utils.h binaryen-99/src/dataflow/utils.h --- binaryen-108/src/dataflow/utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/dataflow/utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -25,11 +25,12 @@ #ifndef wasm_dataflow_utils_h #define wasm_dataflow_utils_h -#include "dataflow/graph.h" #include "dataflow/node.h" #include "wasm.h" -namespace wasm::DataFlow { +namespace wasm { + +namespace DataFlow { inline std::ostream& dump(Node* node, std::ostream& o, size_t indent = 0) { auto doIndent = [&]() { @@ -145,6 +146,8 @@ return false; } -} // namespace wasm::DataFlow +} // namespace DataFlow + +} // namespace wasm #endif // wasm_dataflow_utils diff -Nru binaryen-108/src/emscripten-optimizer/istring.h binaryen-99/src/emscripten-optimizer/istring.h --- binaryen-108/src/emscripten-optimizer/istring.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/emscripten-optimizer/istring.h 2021-01-07 20:01:06.000000000 +0000 @@ -48,11 +48,11 @@ return (size_t)hash; } - class CStringHash { + class CStringHash : public std::hash { public: size_t operator()(const char* str) const { return IString::hash_c(str); } }; - class CStringEqual { + class CStringEqual : public std::equal_to { public: bool operator()(const char* x, const char* y) const { return strcmp(x, y) == 0; diff -Nru binaryen-108/src/emscripten-optimizer/optimizer.h binaryen-99/src/emscripten-optimizer/optimizer.h --- binaryen-108/src/emscripten-optimizer/optimizer.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/emscripten-optimizer/optimizer.h 2021-01-07 20:01:06.000000000 +0000 @@ -19,39 +19,127 @@ #include "simple_ast.h" -using namespace cashew; +extern bool preciseF32, receiveJSON, emitJSON, minifyWhitespace, last; -extern IString JS_FLOAT_ZERO; +extern cashew::Ref extraInfo; -extern IString SIMD_INT8X16_CHECK; -extern IString SIMD_INT16X8_CHECK; -extern IString SIMD_INT32X4_CHECK; -extern IString SIMD_FLOAT32X4_CHECK; -extern IString SIMD_FLOAT64X2_CHECK; - -enum JsType { - JS_INT = 0, - JS_DOUBLE, - JS_FLOAT, - JS_FLOAT32X4, - JS_FLOAT64X2, - JS_INT8X16, - JS_INT16X8, - JS_INT32X4, - JS_INT64, - JS_NONE // number of types +// + +enum AsmType { + ASM_INT = 0, + ASM_DOUBLE, + ASM_FLOAT, + ASM_FLOAT32X4, + ASM_FLOAT64X2, + ASM_INT8X16, + ASM_INT16X8, + ASM_INT32X4, + ASM_INT64, // non-asm.js + ASM_NONE // number of types +}; + +struct AsmData; + +AsmType detectType(cashew::Ref node, + AsmData* asmData = nullptr, + bool inVarDef = false, + cashew::IString minifiedFround = cashew::IString(), + bool allowI64 = false); + +struct AsmData { + struct Local { + Local() = default; + Local(AsmType type, bool param) : type(type), param(param) {} + AsmType type; + bool param; // false if a var + }; + typedef std::unordered_map Locals; + + Locals locals; + std::vector params; // in order + std::vector vars; // in order + AsmType ret; + + cashew::Ref func; + + AsmType getType(const cashew::IString& name) { + auto ret = locals.find(name); + if (ret != locals.end()) { + return ret->second.type; + } + return ASM_NONE; + } + void setType(const cashew::IString& name, AsmType type) { + locals[name].type = type; + } + + bool isLocal(const cashew::IString& name) { return locals.count(name) > 0; } + bool isParam(const cashew::IString& name) { + return isLocal(name) && locals[name].param; + } + bool isVar(const cashew::IString& name) { + return isLocal(name) && !locals[name].param; + } + + // if you want to fill in the data yourself + AsmData() = default; + // if you want to read data from f, and modify it as you go (parallel to + // denormalize) + AsmData(cashew::Ref f); + + void denormalize(); + + void addParam(cashew::IString name, AsmType type) { + locals[name] = Local(type, true); + params.push_back(name); + } + void addVar(cashew::IString name, AsmType type) { + locals[name] = Local(type, false); + vars.push_back(name); + } + + void deleteVar(cashew::IString name) { + locals.erase(name); + for (size_t i = 0; i < vars.size(); i++) { + if (vars[i] == name) { + vars.erase(vars.begin() + i); + break; + } + } + } +}; + +extern cashew::IString ASM_FLOAT_ZERO; + +extern cashew::IString SIMD_INT8X16_CHECK; +extern cashew::IString SIMD_INT16X8_CHECK; +extern cashew::IString SIMD_INT32X4_CHECK; +extern cashew::IString SIMD_FLOAT32X4_CHECK; +extern cashew::IString SIMD_FLOAT64X2_CHECK; + +int parseInt(const char* str); + +struct HeapInfo { + bool valid, unsign, floaty; + int bits; + AsmType type; }; -enum JsSign { +HeapInfo parseHeap(const char* name); + +enum AsmSign { // small constants can be signed or unsigned, variables are also flexible - JS_FLEXIBLE = 0, - JS_SIGNED, - JS_UNSIGNED, - JS_NONSIGNED, + ASM_FLEXIBLE = 0, + ASM_SIGNED = 1, + ASM_UNSIGNED = 2, + ASM_NONSIGNED = 3, }; -Ref makeJsCoercedZero(JsType type); -Ref makeJsCoercion(Ref node, JsType type); -Ref makeSigning(Ref node, JsSign sign); +extern AsmSign detectSign(cashew::Ref node, cashew::IString minifiedFround); + +cashew::Ref makeAsmCoercedZero(AsmType type); +cashew::Ref makeAsmCoercion(cashew::Ref node, AsmType type); + +cashew::Ref makeSigning(cashew::Ref node, AsmSign sign); #endif // wasm_optimizer_h diff -Nru binaryen-108/src/emscripten-optimizer/optimizer-shared.cpp binaryen-99/src/emscripten-optimizer/optimizer-shared.cpp --- binaryen-108/src/emscripten-optimizer/optimizer-shared.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/emscripten-optimizer/optimizer-shared.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -21,31 +21,251 @@ using namespace cashew; -IString JS_FLOAT_ZERO; +IString ASM_FLOAT_ZERO; IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check"); IString SIMD_INT16X8_CHECK("SIMD_Int16x8_check"); IString SIMD_INT32X4_CHECK("SIMD_Int32x4_check"); IString SIMD_FLOAT32X4_CHECK("SIMD_Float32x4_check"); IString SIMD_FLOAT64X2_CHECK("SIMD_Float64x2_check"); +IString TEMP_RET0("tempRet0"); -Ref makeJsCoercedZero(JsType type) { +int parseInt(const char* str) { + int ret = *str - '0'; + while (*(++str)) { + ret *= 10; + ret += *str - '0'; + } + return ret; +} + +HeapInfo parseHeap(const char* name) { + HeapInfo ret; + if (name[0] != 'H' || name[1] != 'E' || name[2] != 'A' || name[3] != 'P') { + ret.valid = false; + return ret; + } + ret.valid = true; + ret.unsign = name[4] == 'U'; + ret.floaty = name[4] == 'F'; + ret.bits = parseInt(name + (ret.unsign || ret.floaty ? 5 : 4)); + ret.type = !ret.floaty ? ASM_INT : (ret.bits == 64 ? ASM_DOUBLE : ASM_FLOAT); + return ret; +} + +AsmType detectType(Ref node, + AsmData* asmData, + bool inVarDef, + IString minifiedFround, + bool allowI64) { + if (node->isString()) { + if (asmData) { + AsmType ret = asmData->getType(node->getCString()); + if (ret != ASM_NONE) { + return ret; + } + } + if (!inVarDef) { + if (node == INF || node == NaN) { + return ASM_DOUBLE; + } + if (node == TEMP_RET0) { + return ASM_INT; + } + return ASM_NONE; + } + // We are in a variable definition, where Math_fround(0) optimized into a + // global constant becomes f0 = Math_fround(0) + if (ASM_FLOAT_ZERO.isNull()) { + ASM_FLOAT_ZERO = node->getIString(); + } else { + assert(node == ASM_FLOAT_ZERO); + } + return ASM_FLOAT; + } + if (node->isNumber()) { + if (!wasm::isInteger(node->getNumber())) { + return ASM_DOUBLE; + } + return ASM_INT; + } + switch (node[0]->getCString()[0]) { + case 'u': { + if (node[0] == UNARY_PREFIX) { + switch (node[1]->getCString()[0]) { + case '+': + return ASM_DOUBLE; + case '-': + return detectType( + node[2], asmData, inVarDef, minifiedFround, allowI64); + case '!': + case '~': + return ASM_INT; + } + break; + } + break; + } + case 'c': { + if (node[0] == CALL) { + if (node[1]->isString()) { + IString name = node[1]->getIString(); + if (name == MATH_FROUND || name == minifiedFround) { + return ASM_FLOAT; + } else if (allowI64 && (name == INT64 || name == INT64_CONST)) { + return ASM_INT64; + } else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK) { + return ASM_FLOAT32X4; + } else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK) { + return ASM_FLOAT64X2; + } else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK) { + return ASM_INT8X16; + } else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK) { + return ASM_INT16X8; + } else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK) { + return ASM_INT32X4; + } + } + return ASM_NONE; + } else if (node[0] == CONDITIONAL) { + return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64); + } + break; + } + case 'b': { + if (node[0] == BINARY) { + switch (node[1]->getCString()[0]) { + case '+': + case '-': + case '*': + case '/': + case '%': + return detectType( + node[2], asmData, inVarDef, minifiedFround, allowI64); + case '|': + case '&': + case '^': + case '<': + case '>': // handles <<, >>, >>=, <=, >= + case '=': + case '!': { // handles ==, != + return ASM_INT; + } + } + } + break; + } + case 's': { + if (node[0] == SEQ) { + return detectType(node[2], asmData, inVarDef, minifiedFround, allowI64); + } else if (node[0] == SUB) { + assert(node[1]->isString()); + HeapInfo info = parseHeap(node[1][1]->getCString()); + if (info.valid) { + return ASM_NONE; + } + return info.floaty ? ASM_DOUBLE : ASM_INT; // XXX ASM_FLOAT? + } + break; + } + } + // dump("horrible", node); + // assert(0); + return ASM_NONE; +} + +static void abort_on(Ref node) { + node->stringify(std::cerr); + std::cerr << '\n'; + abort(); +} + +AsmSign detectSign(Ref node, IString minifiedFround) { + if (node->isString()) { + return ASM_FLEXIBLE; + } + if (node->isNumber()) { + double value = node->getNumber(); + if (value < 0) { + return ASM_SIGNED; + } + if (value > uint32_t(-1) || !wasm::isInteger(value)) { + return ASM_NONSIGNED; + } + if (wasm::isSInteger32(value)) { + return ASM_FLEXIBLE; + } + return ASM_UNSIGNED; + } + IString type = node[0]->getIString(); + if (type == BINARY) { + IString op = node[1]->getIString(); + switch (op.str[0]) { + case '>': { + if (op == TRSHIFT) { + return ASM_UNSIGNED; + } + } // fallthrough + case '|': + case '&': + case '^': + case '<': + case '=': + case '!': + return ASM_SIGNED; + case '+': + case '-': + return ASM_FLEXIBLE; + case '*': + case '/': + case '%': + return ASM_NONSIGNED; // without a coercion, these are double + default: + abort_on(node); + } + } else if (type == UNARY_PREFIX) { + IString op = node[1]->getIString(); + switch (op.str[0]) { + case '-': + return ASM_FLEXIBLE; + case '+': + return ASM_NONSIGNED; // XXX double + case '~': + return ASM_SIGNED; + default: + abort_on(node); + } + } else if (type == CONDITIONAL) { + return detectSign(node[2], minifiedFround); + } else if (type == CALL) { + if (node[1]->isString() && + (node[1] == MATH_FROUND || node[1] == minifiedFround)) { + return ASM_NONSIGNED; + } + } else if (type == SEQ) { + return detectSign(node[2], minifiedFround); + } + abort_on(node); + abort(); // avoid warning +} + +Ref makeAsmCoercedZero(AsmType type) { switch (type) { - case JS_INT: + case ASM_INT: return ValueBuilder::makeNum(0); break; - case JS_DOUBLE: + case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeNum(0)); break; - case JS_FLOAT: { - if (!JS_FLOAT_ZERO.isNull()) { - return ValueBuilder::makeName(JS_FLOAT_ZERO); + case ASM_FLOAT: { + if (!ASM_FLOAT_ZERO.isNull()) { + return ValueBuilder::makeName(ASM_FLOAT_ZERO); } else { return ValueBuilder::makeCall(MATH_FROUND, ValueBuilder::makeNum(0)); } break; } - case JS_FLOAT32X4: { + case ASM_FLOAT32X4: { return ValueBuilder::makeCall(SIMD_FLOAT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -53,12 +273,12 @@ ValueBuilder::makeNum(0)); break; } - case JS_FLOAT64X2: { + case ASM_FLOAT64X2: { return ValueBuilder::makeCall( SIMD_FLOAT64X2, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0)); break; } - case JS_INT8X16: { + case ASM_INT8X16: { return ValueBuilder::makeCall(SIMD_INT8X16, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -78,7 +298,7 @@ ValueBuilder::makeNum(0)); break; } - case JS_INT16X8: { + case ASM_INT16X8: { return ValueBuilder::makeCall(SIMD_INT16X8, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -90,7 +310,7 @@ ValueBuilder::makeNum(0)); break; } - case JS_INT32X4: { + case ASM_INT32X4: { return ValueBuilder::makeCall(SIMD_INT32X4, ValueBuilder::makeNum(0), ValueBuilder::makeNum(0), @@ -104,25 +324,25 @@ abort(); } -Ref makeJsCoercion(Ref node, JsType type) { +Ref makeAsmCoercion(Ref node, AsmType type) { switch (type) { - case JS_INT: + case ASM_INT: return ValueBuilder::makeBinary(node, OR, ValueBuilder::makeNum(0)); - case JS_DOUBLE: + case ASM_DOUBLE: return ValueBuilder::makeUnary(PLUS, node); - case JS_FLOAT: + case ASM_FLOAT: return ValueBuilder::makeCall(MATH_FROUND, node); - case JS_FLOAT32X4: + case ASM_FLOAT32X4: return ValueBuilder::makeCall(SIMD_FLOAT32X4_CHECK, node); - case JS_FLOAT64X2: + case ASM_FLOAT64X2: return ValueBuilder::makeCall(SIMD_FLOAT64X2_CHECK, node); - case JS_INT8X16: + case ASM_INT8X16: return ValueBuilder::makeCall(SIMD_INT8X16_CHECK, node); - case JS_INT16X8: + case ASM_INT16X8: return ValueBuilder::makeCall(SIMD_INT16X8_CHECK, node); - case JS_INT32X4: + case ASM_INT32X4: return ValueBuilder::makeCall(SIMD_INT32X4_CHECK, node); - case JS_NONE: + case ASM_NONE: default: // non-validating code, emit nothing XXX this is dangerous, we should only // allow this when we know we are not validating @@ -130,8 +350,8 @@ } } -Ref makeSigning(Ref node, JsSign sign) { - assert(sign == JS_SIGNED || sign == JS_UNSIGNED); +Ref makeSigning(Ref node, AsmSign sign) { + assert(sign == ASM_SIGNED || sign == ASM_UNSIGNED); return ValueBuilder::makeBinary( - node, sign == JS_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0)); + node, sign == ASM_SIGNED ? OR : TRSHIFT, ValueBuilder::makeNum(0)); } diff -Nru binaryen-108/src/emscripten-optimizer/parser.cpp binaryen-99/src/emscripten-optimizer/parser.cpp --- binaryen-108/src/emscripten-optimizer/parser.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/emscripten-optimizer/parser.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -107,8 +107,6 @@ IString COMPARE_EXCHANGE("compareExchange"); IString LOAD("load"); IString STORE("store"); -IString GETTER("get"); -IString SETTER("set"); IStringSet keywords("var const function if else do while for break continue return " diff -Nru binaryen-108/src/emscripten-optimizer/parser.h binaryen-99/src/emscripten-optimizer/parser.h --- binaryen-108/src/emscripten-optimizer/parser.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/emscripten-optimizer/parser.h 2021-01-07 20:01:06.000000000 +0000 @@ -124,8 +124,6 @@ extern IString COMPARE_EXCHANGE; extern IString LOAD; extern IString STORE; -extern IString GETTER; -extern IString SETTER; extern IStringSet keywords; @@ -209,8 +207,8 @@ }; struct Frag { - // MSVC does not allow unrestricted unions: - // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + // MSVC does not allow unrestricted unions: + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf #ifndef _MSC_VER union { #endif diff -Nru binaryen-108/src/emscripten-optimizer/simple_ast.h binaryen-99/src/emscripten-optimizer/simple_ast.h --- binaryen-108/src/emscripten-optimizer/simple_ast.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/emscripten-optimizer/simple_ast.h 2021-01-07 20:01:06.000000000 +0000 @@ -947,19 +947,17 @@ bool integer = wasm::isInteger(d); #define BUFFERSIZE 1000 // f is normal, e is scientific for float, x for integer - // These need to be thread-local because they are returned. - thread_local char full_storage_f[BUFFERSIZE]; - thread_local char full_storage_e[BUFFERSIZE]; + static char full_storage_f[BUFFERSIZE], full_storage_e[BUFFERSIZE]; // full has one more char, for a possible '-' - char* storage_f = full_storage_f + 1; - char* storage_e = full_storage_e + 1; + static char *storage_f = full_storage_f + 1, + *storage_e = full_storage_e + 1; auto err_f = std::numeric_limits::quiet_NaN(); auto err_e = std::numeric_limits::quiet_NaN(); for (int e = 0; e <= 1; e++) { char* buffer = e ? storage_e : storage_f; double temp; if (!integer) { - char format[6]; + static char format[6]; for (int i = 0; i <= 18; i++) { format[0] = '%'; format[1] = '.'; @@ -1463,24 +1461,12 @@ newline(); } bool needQuote = false; - const char* getterSetter = nullptr; - const char* setterParam = nullptr; const char* str; if (args[i][0]->isArray()) { - if (args[i][0][0] == STRING) { - // A quoted string. - needQuote = true; - str = args[i][0][1]->getCString(); - } else if (args[i][0][0] == GETTER) { - getterSetter = GETTER.c_str(); - str = args[i][0][1]->getCString(); - } else if (args[i][0][0] == SETTER) { - getterSetter = SETTER.c_str(); - str = args[i][0][1]->getCString(); - setterParam = args[i][0][2]->getCString(); - } else { - abort(); - } + assert(args[i][0][0] == STRING); + // A quoted string. + needQuote = true; + str = args[i][0][1]->getCString(); } else { // Just a raw string, no quotes. str = args[i][0]->getCString(); @@ -1493,10 +1479,6 @@ } check++; } - if (getterSetter != nullptr) { - emit(getterSetter); - space(); - } if (needQuote) { emit('"'); } @@ -1504,15 +1486,7 @@ if (needQuote) { emit('"'); } - if (getterSetter != nullptr) { - emit('('); - if (setterParam != nullptr) { - emit(setterParam); - } - emit(')'); - } else { - emit(":"); - } + emit(":"); space(); print(args[i][1]); } @@ -1852,26 +1826,6 @@ &makeRawArray(2)->push_back(makeString(key)).push_back(value)); } - static void appendToObjectAsGetter(Ref array, IString key, Ref value) { - assert(array[0] == OBJECT); - array[1]->push_back(&makeRawArray(2) - ->push_back(&makeRawArray(2) - ->push_back(makeRawString(GETTER)) - .push_back(makeRawString(key))) - .push_back(value)); - } - - static void - appendToObjectAsSetter(Ref array, IString key, IString param, Ref value) { - assert(array[0] == OBJECT); - array[1]->push_back(&makeRawArray(2) - ->push_back(&makeRawArray(3) - ->push_back(makeRawString(SETTER)) - .push_back(makeRawString(key)) - .push_back(makeRawString(param))) - .push_back(value)); - } - static Ref makeSub(Ref obj, Ref index) { return &makeRawArray(2) ->push_back(makeRawString(SUB)) diff -Nru binaryen-108/src/gen-s-parser.inc binaryen-99/src/gen-s-parser.inc --- binaryen-108/src/gen-s-parser.inc 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/gen-s-parser.inc 2021-01-07 20:01:06.000000000 +0000 @@ -4,16 +4,13 @@ #ifdef INSTRUCTION_PARSER #undef INSTRUCTION_PARSER -char op[33] = {'\0'}; -strncpy(op, s[0]->c_str(), 32); +char op[30] = {'\0'}; +strncpy(op, s[0]->c_str(), 29); switch (op[0]) { case 'a': { switch (op[1]) { case 'r': { switch (op[6]) { - case 'c': - if (strcmp(op, "array.copy") == 0) { return makeArrayCopy(s); } - goto parse_error; case 'g': { switch (op[9]) { case '\0': @@ -33,44 +30,17 @@ default: goto parse_error; } } - case 'i': { - switch (op[10]) { - case '\0': - if (strcmp(op, "array.init") == 0) { return makeArrayInit(s); } - goto parse_error; - case '_': - if (strcmp(op, "array.init_static") == 0) { return makeArrayInitStatic(s); } - goto parse_error; - default: goto parse_error; - } - } case 'l': if (strcmp(op, "array.len") == 0) { return makeArrayLen(s); } goto parse_error; case 'n': { - switch (op[9]) { - case '\0': - if (strcmp(op, "array.new") == 0) { return makeArrayNewStatic(s, false); } + switch (op[10]) { + case 'd': + if (strcmp(op, "array.new_default_with_rtt") == 0) { return makeArrayNew(s, true); } + goto parse_error; + case 'w': + if (strcmp(op, "array.new_with_rtt") == 0) { return makeArrayNew(s, false); } goto parse_error; - case '_': { - switch (op[10]) { - case 'd': { - switch (op[17]) { - case '\0': - if (strcmp(op, "array.new_default") == 0) { return makeArrayNewStatic(s, true); } - goto parse_error; - case '_': - if (strcmp(op, "array.new_default_with_rtt") == 0) { return makeArrayNew(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 'w': - if (strcmp(op, "array.new_with_rtt") == 0) { return makeArrayNew(s, false); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } @@ -103,67 +73,12 @@ goto parse_error; case 'o': { switch (op[6]) { - case 'c': { - switch (op[10]) { - case '\0': - if (strcmp(op, "br_on_cast") == 0) { return makeBrOn(s, BrOnCast); } - goto parse_error; - case '_': { - switch (op[11]) { - case 'f': - if (strcmp(op, "br_on_cast_fail") == 0) { return makeBrOn(s, BrOnCastFail); } - goto parse_error; - case 's': { - switch (op[17]) { - case '\0': - if (strcmp(op, "br_on_cast_static") == 0) { return makeBrOnStatic(s, BrOnCast); } - goto parse_error; - case '_': - if (strcmp(op, "br_on_cast_static_fail") == 0) { return makeBrOnStatic(s, BrOnCastFail); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'd': - if (strcmp(op, "br_on_data") == 0) { return makeBrOn(s, BrOnData); } - goto parse_error; - case 'f': - if (strcmp(op, "br_on_func") == 0) { return makeBrOn(s, BrOnFunc); } + case 'c': + if (strcmp(op, "br_on_cast") == 0) { return makeBrOnCast(s); } goto parse_error; - case 'i': - if (strcmp(op, "br_on_i31") == 0) { return makeBrOn(s, BrOnI31); } + case 'e': + if (strcmp(op, "br_on_exn") == 0) { return makeBrOnExn(s); } goto parse_error; - case 'n': { - switch (op[7]) { - case 'o': { - switch (op[10]) { - case 'd': - if (strcmp(op, "br_on_non_data") == 0) { return makeBrOn(s, BrOnNonData); } - goto parse_error; - case 'f': - if (strcmp(op, "br_on_non_func") == 0) { return makeBrOn(s, BrOnNonFunc); } - goto parse_error; - case 'i': - if (strcmp(op, "br_on_non_i31") == 0) { return makeBrOn(s, BrOnNonI31); } - goto parse_error; - case 'n': - if (strcmp(op, "br_on_non_null") == 0) { return makeBrOn(s, BrOnNonNull); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': - if (strcmp(op, "br_on_null") == 0) { return makeBrOn(s, BrOnNull); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } @@ -405,17 +320,9 @@ default: goto parse_error; } } - case 'd': { - switch (op[7]) { - case 'e': - if (strcmp(op, "f32x4.demote_f64x2_zero") == 0) { return makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4); } - goto parse_error; - case 'i': - if (strcmp(op, "f32x4.div") == 0) { return makeBinary(s, BinaryOp::DivVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } + case 'd': + if (strcmp(op, "f32x4.div") == 0) { return makeBinary(s, BinaryOp::DivVecF32x4); } + goto parse_error; case 'e': { switch (op[7]) { case 'q': @@ -491,41 +398,20 @@ default: goto parse_error; } } - case 'r': { - switch (op[8]) { - case 'l': { - switch (op[14]) { - case 'f': { - switch (op[16]) { - case 'a': - if (strcmp(op, "f32x4.relaxed_fma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF32x4); } - goto parse_error; - case 's': - if (strcmp(op, "f32x4.relaxed_fms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (op[15]) { - case 'a': - if (strcmp(op, "f32x4.relaxed_max") == 0) { return makeBinary(s, BinaryOp::RelaxedMaxVecF32x4); } - goto parse_error; - case 'i': - if (strcmp(op, "f32x4.relaxed_min") == 0) { return makeBinary(s, BinaryOp::RelaxedMinVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (strcmp(op, "f32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4); } + case 'q': { + switch (op[9]) { + case 'a': + if (strcmp(op, "f32x4.qfma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMAF32x4); } + goto parse_error; + case 's': + if (strcmp(op, "f32x4.qfms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMSF32x4); } goto parse_error; default: goto parse_error; } } + case 'r': + if (strcmp(op, "f32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4); } + goto parse_error; case 's': { switch (op[7]) { case 'p': @@ -722,12 +608,12 @@ if (strcmp(op, "f64x2.ceil") == 0) { return makeUnary(s, UnaryOp::CeilVecF64x2); } goto parse_error; case 'o': { - switch (op[24]) { + switch (op[20]) { case 's': - if (strcmp(op, "f64x2.convert_low_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2); } + if (strcmp(op, "f64x2.convert_i64x2_s") == 0) { return makeUnary(s, UnaryOp::ConvertSVecI64x2ToVecF64x2); } goto parse_error; case 'u': - if (strcmp(op, "f64x2.convert_low_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2); } + if (strcmp(op, "f64x2.convert_i64x2_u") == 0) { return makeUnary(s, UnaryOp::ConvertUVecI64x2ToVecF64x2); } goto parse_error; default: goto parse_error; } @@ -803,59 +689,30 @@ } } case 'p': { - switch (op[7]) { - case 'm': { - switch (op[8]) { - case 'a': - if (strcmp(op, "f64x2.pmax") == 0) { return makeBinary(s, BinaryOp::PMaxVecF64x2); } - goto parse_error; - case 'i': - if (strcmp(op, "f64x2.pmin") == 0) { return makeBinary(s, BinaryOp::PMinVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': - if (strcmp(op, "f64x2.promote_low_f32x4") == 0) { return makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2); } + switch (op[8]) { + case 'a': + if (strcmp(op, "f64x2.pmax") == 0) { return makeBinary(s, BinaryOp::PMaxVecF64x2); } + goto parse_error; + case 'i': + if (strcmp(op, "f64x2.pmin") == 0) { return makeBinary(s, BinaryOp::PMinVecF64x2); } goto parse_error; default: goto parse_error; } } - case 'r': { - switch (op[8]) { - case 'l': { - switch (op[14]) { - case 'f': { - switch (op[16]) { - case 'a': - if (strcmp(op, "f64x2.relaxed_fma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF64x2); } - goto parse_error; - case 's': - if (strcmp(op, "f64x2.relaxed_fms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (op[15]) { - case 'a': - if (strcmp(op, "f64x2.relaxed_max") == 0) { return makeBinary(s, BinaryOp::RelaxedMaxVecF64x2); } - goto parse_error; - case 'i': - if (strcmp(op, "f64x2.relaxed_min") == 0) { return makeBinary(s, BinaryOp::RelaxedMinVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (strcmp(op, "f64x2.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2); } + case 'q': { + switch (op[9]) { + case 'a': + if (strcmp(op, "f64x2.qfma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMAF64x2); } + goto parse_error; + case 's': + if (strcmp(op, "f64x2.qfms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::QFMSF64x2); } goto parse_error; default: goto parse_error; } } + case 'r': + if (strcmp(op, "f64x2.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2); } + goto parse_error; case 's': { switch (op[7]) { case 'p': @@ -908,12 +765,12 @@ if (strcmp(op, "i16x8.add") == 0) { return makeBinary(s, BinaryOp::AddVecI16x8); } goto parse_error; case '_': { - switch (op[14]) { + switch (op[19]) { case 's': - if (strcmp(op, "i16x8.add_sat_s") == 0) { return makeBinary(s, BinaryOp::AddSatSVecI16x8); } + if (strcmp(op, "i16x8.add_saturate_s") == 0) { return makeBinary(s, BinaryOp::AddSatSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.add_sat_u") == 0) { return makeBinary(s, BinaryOp::AddSatUVecI16x8); } + if (strcmp(op, "i16x8.add_saturate_u") == 0) { return makeBinary(s, BinaryOp::AddSatUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -924,6 +781,9 @@ case 'l': if (strcmp(op, "i16x8.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI16x8); } goto parse_error; + case 'n': + if (strcmp(op, "i16x8.any_true") == 0) { return makeUnary(s, UnaryOp::AnyTrueVecI16x8); } + goto parse_error; case 'v': if (strcmp(op, "i16x8.avgr_u") == 0) { return makeBinary(s, BinaryOp::AvgrUVecI16x8); } goto parse_error; @@ -933,17 +793,6 @@ case 'b': if (strcmp(op, "i16x8.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI16x8); } goto parse_error; - case 'd': { - switch (op[22]) { - case 's': - if (strcmp(op, "i16x8.dot_i8x16_i7x16_s") == 0) { return makeBinary(s, BinaryOp::DotI8x16I7x16SToVecI16x8); } - goto parse_error; - case 'u': - if (strcmp(op, "i16x8.dot_i8x16_i7x16_u") == 0) { return makeBinary(s, BinaryOp::DotI8x16I7x16UToVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } case 'e': { switch (op[7]) { case 'q': @@ -962,33 +811,6 @@ default: goto parse_error; } } - case 'e': { - switch (op[13]) { - case 'h': { - switch (op[24]) { - case 's': - if (strcmp(op, "i16x8.extend_high_i8x16_s") == 0) { return makeUnary(s, UnaryOp::ExtendHighSVecI8x16ToVecI16x8); } - goto parse_error; - case 'u': - if (strcmp(op, "i16x8.extend_high_i8x16_u") == 0) { return makeUnary(s, UnaryOp::ExtendHighUVecI8x16ToVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (op[23]) { - case 's': - if (strcmp(op, "i16x8.extend_low_i8x16_s") == 0) { return makeUnary(s, UnaryOp::ExtendLowSVecI8x16ToVecI16x8); } - goto parse_error; - case 'u': - if (strcmp(op, "i16x8.extend_low_i8x16_u") == 0) { return makeUnary(s, UnaryOp::ExtendLowUVecI8x16ToVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } case 'm': { switch (op[13]) { case 'h': { @@ -1062,9 +884,6 @@ } case 'l': { switch (op[7]) { - case 'a': - if (strcmp(op, "i16x8.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI16x8); } - goto parse_error; case 'e': { switch (op[9]) { case 's': @@ -1076,6 +895,17 @@ default: goto parse_error; } } + case 'o': { + switch (op[14]) { + case 's': + if (strcmp(op, "i16x8.load8x8_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec8x8ToVecI16x8); } + goto parse_error; + case 'u': + if (strcmp(op, "i16x8.load8x8_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec8x8ToVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } case 't': { switch (op[9]) { case 's': @@ -1150,17 +980,9 @@ case 'q': if (strcmp(op, "i16x8.q15mulr_sat_s") == 0) { return makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8); } goto parse_error; - case 'r': { - switch (op[8]) { - case 'l': - if (strcmp(op, "i16x8.relaxed_q15mulr_s") == 0) { return makeBinary(s, BinaryOp::RelaxedQ15MulrSVecI16x8); } - goto parse_error; - case 'p': - if (strcmp(op, "i16x8.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); } - goto parse_error; - default: goto parse_error; - } - } + case 'r': + if (strcmp(op, "i16x8.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); } + goto parse_error; case 's': { switch (op[7]) { case 'h': { @@ -1191,12 +1013,12 @@ if (strcmp(op, "i16x8.sub") == 0) { return makeBinary(s, BinaryOp::SubVecI16x8); } goto parse_error; case '_': { - switch (op[14]) { + switch (op[19]) { case 's': - if (strcmp(op, "i16x8.sub_sat_s") == 0) { return makeBinary(s, BinaryOp::SubSatSVecI16x8); } + if (strcmp(op, "i16x8.sub_saturate_s") == 0) { return makeBinary(s, BinaryOp::SubSatSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.sub_sat_u") == 0) { return makeBinary(s, BinaryOp::SubSatUVecI16x8); } + if (strcmp(op, "i16x8.sub_saturate_u") == 0) { return makeBinary(s, BinaryOp::SubSatUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1207,6 +1029,33 @@ default: goto parse_error; } } + case 'w': { + switch (op[12]) { + case 'h': { + switch (op[23]) { + case 's': + if (strcmp(op, "i16x8.widen_high_i8x16_s") == 0) { return makeUnary(s, UnaryOp::WidenHighSVecI8x16ToVecI16x8); } + goto parse_error; + case 'u': + if (strcmp(op, "i16x8.widen_high_i8x16_u") == 0) { return makeUnary(s, UnaryOp::WidenHighUVecI8x16ToVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } + case 'l': { + switch (op[22]) { + case 's': + if (strcmp(op, "i16x8.widen_low_i8x16_s") == 0) { return makeUnary(s, UnaryOp::WidenLowSVecI8x16ToVecI16x8); } + goto parse_error; + case 'u': + if (strcmp(op, "i16x8.widen_low_i8x16_u") == 0) { return makeUnary(s, UnaryOp::WidenLowUVecI8x16ToVecI16x8); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } default: goto parse_error; } } @@ -1697,31 +1546,18 @@ case 'l': if (strcmp(op, "i32x4.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI32x4); } goto parse_error; + case 'n': + if (strcmp(op, "i32x4.any_true") == 0) { return makeUnary(s, UnaryOp::AnyTrueVecI32x4); } + goto parse_error; default: goto parse_error; } } case 'b': if (strcmp(op, "i32x4.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI32x4); } goto parse_error; - case 'd': { - switch (op[11]) { - case '1': - if (strcmp(op, "i32x4.dot_i16x8_s") == 0) { return makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4); } - goto parse_error; - case '8': { - switch (op[26]) { - case 's': - if (strcmp(op, "i32x4.dot_i8x16_i7x16_add_s") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4); } - goto parse_error; - case 'u': - if (strcmp(op, "i32x4.dot_i8x16_i7x16_add_u") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddUToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } + case 'd': + if (strcmp(op, "i32x4.dot_i16x8_s") == 0) { return makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4); } + goto parse_error; case 'e': { switch (op[7]) { case 'q': @@ -1740,15 +1576,15 @@ default: goto parse_error; } } - case 'e': { + case 'm': { switch (op[13]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i32x4.extend_high_i16x8_s") == 0) { return makeUnary(s, UnaryOp::ExtendHighSVecI16x8ToVecI32x4); } + if (strcmp(op, "i32x4.extmul_high_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extend_high_i16x8_u") == 0) { return makeUnary(s, UnaryOp::ExtendHighUVecI16x8ToVecI32x4); } + if (strcmp(op, "i32x4.extmul_high_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1756,37 +1592,10 @@ case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i32x4.extend_low_i16x8_s") == 0) { return makeUnary(s, UnaryOp::ExtendLowSVecI16x8ToVecI32x4); } + if (strcmp(op, "i32x4.extmul_low_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extend_low_i16x8_u") == 0) { return makeUnary(s, UnaryOp::ExtendLowUVecI16x8ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (op[13]) { - case 'h': { - switch (op[24]) { - case 's': - if (strcmp(op, "i32x4.extmul_high_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); } - goto parse_error; - case 'u': - if (strcmp(op, "i32x4.extmul_high_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (op[23]) { - case 's': - if (strcmp(op, "i32x4.extmul_low_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); } - goto parse_error; - case 'u': - if (strcmp(op, "i32x4.extmul_low_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); } + if (strcmp(op, "i32x4.extmul_low_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1832,9 +1641,6 @@ } case 'l': { switch (op[7]) { - case 'a': - if (strcmp(op, "i32x4.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI32x4); } - goto parse_error; case 'e': { switch (op[9]) { case 's': @@ -1846,6 +1652,17 @@ default: goto parse_error; } } + case 'o': { + switch (op[15]) { + case 's': + if (strcmp(op, "i32x4.load16x4_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec16x4ToVecI32x4); } + goto parse_error; + case 'u': + if (strcmp(op, "i32x4.load16x4_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec16x4ToVecI32x4); } + goto parse_error; + default: goto parse_error; + } + } case 't': { switch (op[9]) { case 's': @@ -1901,41 +1718,9 @@ default: goto parse_error; } } - case 'r': { - switch (op[8]) { - case 'l': { - switch (op[21]) { - case '3': { - switch (op[26]) { - case 's': - if (strcmp(op, "i32x4.relaxed_trunc_f32x4_s") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4); } - goto parse_error; - case 'u': - if (strcmp(op, "i32x4.relaxed_trunc_f32x4_u") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (op[26]) { - case 's': - if (strcmp(op, "i32x4.relaxed_trunc_f64x2_s_zero") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4); } - goto parse_error; - case 'u': - if (strcmp(op, "i32x4.relaxed_trunc_f64x2_u_zero") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (strcmp(op, "i32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI32x4, 4); } - goto parse_error; - default: goto parse_error; - } - } + case 'r': + if (strcmp(op, "i32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI32x4, 4); } + goto parse_error; case 's': { switch (op[7]) { case 'h': { @@ -1967,25 +1752,36 @@ } } case 't': { - switch (op[17]) { - case '3': { - switch (op[22]) { + switch (op[22]) { + case 's': + if (strcmp(op, "i32x4.trunc_sat_f32x4_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } + goto parse_error; + case 'u': + if (strcmp(op, "i32x4.trunc_sat_f32x4_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } + goto parse_error; + default: goto parse_error; + } + } + case 'w': { + switch (op[12]) { + case 'h': { + switch (op[23]) { case 's': - if (strcmp(op, "i32x4.trunc_sat_f32x4_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } + if (strcmp(op, "i32x4.widen_high_i16x8_s") == 0) { return makeUnary(s, UnaryOp::WidenHighSVecI16x8ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.trunc_sat_f32x4_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } + if (strcmp(op, "i32x4.widen_high_i16x8_u") == 0) { return makeUnary(s, UnaryOp::WidenHighUVecI16x8ToVecI32x4); } goto parse_error; default: goto parse_error; } } - case '6': { + case 'l': { switch (op[22]) { case 's': - if (strcmp(op, "i32x4.trunc_sat_f64x2_s_zero") == 0) { return makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4); } + if (strcmp(op, "i32x4.widen_low_i16x8_s") == 0) { return makeUnary(s, UnaryOp::WidenLowSVecI16x8ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.trunc_sat_f64x2_u_zero") == 0) { return makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4); } + if (strcmp(op, "i32x4.widen_low_i16x8_u") == 0) { return makeUnary(s, UnaryOp::WidenLowUVecI16x8ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -2524,20 +2320,9 @@ } case 'x': { switch (op[6]) { - case 'a': { - switch (op[7]) { - case 'b': - if (strcmp(op, "i64x2.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecI64x2); } - goto parse_error; - case 'd': - if (strcmp(op, "i64x2.add") == 0) { return makeBinary(s, BinaryOp::AddVecI64x2); } - goto parse_error; - case 'l': - if (strcmp(op, "i64x2.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } + case 'a': + if (strcmp(op, "i64x2.add") == 0) { return makeBinary(s, BinaryOp::AddVecI64x2); } + goto parse_error; case 'b': if (strcmp(op, "i64x2.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI64x2); } goto parse_error; @@ -2548,33 +2333,6 @@ goto parse_error; case 'x': { switch (op[9]) { - case 'e': { - switch (op[13]) { - case 'h': { - switch (op[24]) { - case 's': - if (strcmp(op, "i64x2.extend_high_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ExtendHighSVecI32x4ToVecI64x2); } - goto parse_error; - case 'u': - if (strcmp(op, "i64x2.extend_high_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ExtendHighUVecI32x4ToVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (op[23]) { - case 's': - if (strcmp(op, "i64x2.extend_low_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ExtendLowSVecI32x4ToVecI64x2); } - goto parse_error; - case 'u': - if (strcmp(op, "i64x2.extend_low_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ExtendLowUVecI32x4ToVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } case 'm': { switch (op[13]) { case 'h': { @@ -2611,27 +2369,13 @@ default: goto parse_error; } } - case 'g': { - switch (op[7]) { - case 'e': - if (strcmp(op, "i64x2.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSVecI64x2); } - goto parse_error; - case 't': - if (strcmp(op, "i64x2.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } case 'l': { - switch (op[7]) { - case 'a': - if (strcmp(op, "i64x2.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI64x2); } - goto parse_error; - case 'e': - if (strcmp(op, "i64x2.le_s") == 0) { return makeBinary(s, BinaryOp::LeSVecI64x2); } + switch (op[15]) { + case 's': + if (strcmp(op, "i64x2.load32x2_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadExtSVec32x2ToVecI64x2); } goto parse_error; - case 't': - if (strcmp(op, "i64x2.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSVecI64x2); } + case 'u': + if (strcmp(op, "i64x2.load32x2_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadExtUVec32x2ToVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2639,17 +2383,9 @@ case 'm': if (strcmp(op, "i64x2.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI64x2); } goto parse_error; - case 'n': { - switch (op[8]) { - case '\0': - if (strcmp(op, "i64x2.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI64x2); } - goto parse_error; - case 'g': - if (strcmp(op, "i64x2.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } + case 'n': + if (strcmp(op, "i64x2.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI64x2); } + goto parse_error; case 'r': if (strcmp(op, "i64x2.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI64x2, 2); } goto parse_error; @@ -2683,6 +2419,44 @@ default: goto parse_error; } } + case 't': { + switch (op[22]) { + case 's': + if (strcmp(op, "i64x2.trunc_sat_f64x2_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSVecF64x2ToVecI64x2); } + goto parse_error; + case 'u': + if (strcmp(op, "i64x2.trunc_sat_f64x2_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUVecF64x2ToVecI64x2); } + goto parse_error; + default: goto parse_error; + } + } + case 'w': { + switch (op[12]) { + case 'h': { + switch (op[23]) { + case 's': + if (strcmp(op, "i64x2.widen_high_i32x4_s") == 0) { return makeUnary(s, UnaryOp::WidenHighSVecI32x4ToVecI64x2); } + goto parse_error; + case 'u': + if (strcmp(op, "i64x2.widen_high_i32x4_u") == 0) { return makeUnary(s, UnaryOp::WidenHighUVecI32x4ToVecI64x2); } + goto parse_error; + default: goto parse_error; + } + } + case 'l': { + switch (op[22]) { + case 's': + if (strcmp(op, "i64x2.widen_low_i32x4_s") == 0) { return makeUnary(s, UnaryOp::WidenLowSVecI32x4ToVecI64x2); } + goto parse_error; + case 'u': + if (strcmp(op, "i64x2.widen_low_i32x4_u") == 0) { return makeUnary(s, UnaryOp::WidenLowUVecI32x4ToVecI64x2); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } default: goto parse_error; } } @@ -2702,12 +2476,12 @@ if (strcmp(op, "i8x16.add") == 0) { return makeBinary(s, BinaryOp::AddVecI8x16); } goto parse_error; case '_': { - switch (op[14]) { + switch (op[19]) { case 's': - if (strcmp(op, "i8x16.add_sat_s") == 0) { return makeBinary(s, BinaryOp::AddSatSVecI8x16); } + if (strcmp(op, "i8x16.add_saturate_s") == 0) { return makeBinary(s, BinaryOp::AddSatSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.add_sat_u") == 0) { return makeBinary(s, BinaryOp::AddSatUVecI8x16); } + if (strcmp(op, "i8x16.add_saturate_u") == 0) { return makeBinary(s, BinaryOp::AddSatUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2718,6 +2492,9 @@ case 'l': if (strcmp(op, "i8x16.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI8x16); } goto parse_error; + case 'n': + if (strcmp(op, "i8x16.any_true") == 0) { return makeUnary(s, UnaryOp::AnyTrueVecI8x16); } + goto parse_error; case 'v': if (strcmp(op, "i8x16.avgr_u") == 0) { return makeBinary(s, BinaryOp::AvgrUVecI8x16); } goto parse_error; @@ -2775,9 +2552,6 @@ } case 'l': { switch (op[7]) { - case 'a': - if (strcmp(op, "i8x16.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI8x16); } - goto parse_error; case 'e': { switch (op[9]) { case 's': @@ -2827,6 +2601,9 @@ default: goto parse_error; } } + case 'u': + if (strcmp(op, "i8x16.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI8x16); } + goto parse_error; default: goto parse_error; } } @@ -2860,17 +2637,9 @@ case 'p': if (strcmp(op, "i8x16.popcnt") == 0) { return makeUnary(s, UnaryOp::PopcntVecI8x16); } goto parse_error; - case 'r': { - switch (op[8]) { - case 'l': - if (strcmp(op, "i8x16.relaxed_swizzle") == 0) { return makeBinary(s, BinaryOp::RelaxedSwizzleVecI8x16); } - goto parse_error; - case 'p': - if (strcmp(op, "i8x16.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI8x16, 16); } - goto parse_error; - default: goto parse_error; - } - } + case 'r': + if (strcmp(op, "i8x16.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI8x16, 16); } + goto parse_error; case 's': { switch (op[7]) { case 'h': { @@ -2889,9 +2658,6 @@ default: goto parse_error; } } - case 'u': - if (strcmp(op, "i8x16.shuffle") == 0) { return makeSIMDShuffle(s); } - goto parse_error; default: goto parse_error; } } @@ -2904,12 +2670,12 @@ if (strcmp(op, "i8x16.sub") == 0) { return makeBinary(s, BinaryOp::SubVecI8x16); } goto parse_error; case '_': { - switch (op[14]) { + switch (op[19]) { case 's': - if (strcmp(op, "i8x16.sub_sat_s") == 0) { return makeBinary(s, BinaryOp::SubSatSVecI8x16); } + if (strcmp(op, "i8x16.sub_saturate_s") == 0) { return makeBinary(s, BinaryOp::SubSatSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.sub_sat_u") == 0) { return makeBinary(s, BinaryOp::SubSatUVecI8x16); } + if (strcmp(op, "i8x16.sub_saturate_u") == 0) { return makeBinary(s, BinaryOp::SubSatUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2917,9 +2683,6 @@ default: goto parse_error; } } - case 'w': - if (strcmp(op, "i8x16.swizzle") == 0) { return makeBinary(s, BinaryOp::SwizzleVecI8x16); } - goto parse_error; default: goto parse_error; } } @@ -2996,88 +2759,49 @@ case 'n': if (strcmp(op, "nop") == 0) { return makeNop(); } goto parse_error; - case 'p': - if (strcmp(op, "pop") == 0) { return makePop(s); } - goto parse_error; + case 'p': { + switch (op[1]) { + case 'o': + if (strcmp(op, "pop") == 0) { return makePop(s); } + goto parse_error; + case 'r': { + switch (op[9]) { + case 'n': + if (strcmp(op, "prefetch.nt") == 0) { return makePrefetch(s, PrefetchOp::PrefetchNontemporal); } + goto parse_error; + case 't': + if (strcmp(op, "prefetch.t") == 0) { return makePrefetch(s, PrefetchOp::PrefetchTemporal); } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; + } + } case 'r': { switch (op[1]) { case 'e': { switch (op[2]) { case 'f': { switch (op[4]) { - case 'a': { - switch (op[7]) { - case 'd': - if (strcmp(op, "ref.as_data") == 0) { return makeRefAs(s, RefAsData); } - goto parse_error; - case 'f': - if (strcmp(op, "ref.as_func") == 0) { return makeRefAs(s, RefAsFunc); } - goto parse_error; - case 'i': - if (strcmp(op, "ref.as_i31") == 0) { return makeRefAs(s, RefAsI31); } - goto parse_error; - case 'n': - if (strcmp(op, "ref.as_non_null") == 0) { return makeRefAs(s, RefAsNonNull); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (op[8]) { - case '\0': - if (strcmp(op, "ref.cast") == 0) { return makeRefCast(s); } - goto parse_error; - case '_': { - switch (op[9]) { - case 'n': - if (strcmp(op, "ref.cast_nop_static") == 0) { return makeRefCastNopStatic(s); } - goto parse_error; - case 's': - if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } + case 'c': + if (strcmp(op, "ref.cast") == 0) { return makeRefCast(s); } + goto parse_error; case 'e': if (strcmp(op, "ref.eq") == 0) { return makeRefEq(s); } goto parse_error; case 'f': if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); } goto parse_error; - case 'i': { - switch (op[7]) { - case 'd': - if (strcmp(op, "ref.is_data") == 0) { return makeRefIs(s, RefIsData); } - goto parse_error; - case 'f': - if (strcmp(op, "ref.is_func") == 0) { return makeRefIs(s, RefIsFunc); } - goto parse_error; - case 'i': - if (strcmp(op, "ref.is_i31") == 0) { return makeRefIs(s, RefIsI31); } - goto parse_error; - case 'n': - if (strcmp(op, "ref.is_null") == 0) { return makeRefIs(s, RefIsNull); } - goto parse_error; - default: goto parse_error; - } - } + case 'i': + if (strcmp(op, "ref.is_null") == 0) { return makeRefIsNull(s); } + goto parse_error; case 'n': if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); } goto parse_error; - case 't': { - switch (op[8]) { - case '\0': - if (strcmp(op, "ref.test") == 0) { return makeRefTest(s); } - goto parse_error; - case '_': - if (strcmp(op, "ref.test_static") == 0) { return makeRefTestStatic(s); } - goto parse_error; - default: goto parse_error; - } - } + case 't': + if (strcmp(op, "ref.test") == 0) { return makeRefTest(s); } + goto parse_error; default: goto parse_error; } } @@ -3124,9 +2848,6 @@ case 'c': if (strcmp(op, "rtt.canon") == 0) { return makeRttCanon(s); } goto parse_error; - case 'f': - if (strcmp(op, "rtt.fresh_sub") == 0) { return makeRttFreshSub(s); } - goto parse_error; case 's': if (strcmp(op, "rtt.sub") == 0) { return makeRttSub(s); } goto parse_error; @@ -3163,29 +2884,13 @@ } } case 'n': { - switch (op[10]) { - case '\0': - if (strcmp(op, "struct.new") == 0) { return makeStructNewStatic(s, false); } + switch (op[11]) { + case 'd': + if (strcmp(op, "struct.new_default_with_rtt") == 0) { return makeStructNew(s, true); } + goto parse_error; + case 'w': + if (strcmp(op, "struct.new_with_rtt") == 0) { return makeStructNew(s, false); } goto parse_error; - case '_': { - switch (op[11]) { - case 'd': { - switch (op[18]) { - case '\0': - if (strcmp(op, "struct.new_default") == 0) { return makeStructNewStatic(s, true); } - goto parse_error; - case '_': - if (strcmp(op, "struct.new_default_with_rtt") == 0) { return makeStructNew(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 'w': - if (strcmp(op, "struct.new_with_rtt") == 0) { return makeStructNew(s, false); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } @@ -3200,33 +2905,6 @@ } case 't': { switch (op[1]) { - case 'a': { - switch (op[6]) { - case 'g': { - switch (op[7]) { - case 'e': - if (strcmp(op, "table.get") == 0) { return makeTableGet(s); } - goto parse_error; - case 'r': - if (strcmp(op, "table.grow") == 0) { return makeTableGrow(s); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (op[7]) { - case 'e': - if (strcmp(op, "table.set") == 0) { return makeTableSet(s); } - goto parse_error; - case 'i': - if (strcmp(op, "table.size") == 0) { return makeTableSize(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } case 'h': { switch (op[2]) { case 'e': @@ -3259,167 +2937,154 @@ if (strcmp(op, "unreachable") == 0) { return makeUnreachable(); } goto parse_error; case 'v': { - switch (op[5]) { - case 'a': { - switch (op[7]) { - case 'd': { - switch (op[8]) { - case '\0': - if (strcmp(op, "v128.and") == 0) { return makeBinary(s, BinaryOp::AndVec128); } - goto parse_error; - case 'n': - if (strcmp(op, "v128.andnot") == 0) { return makeBinary(s, BinaryOp::AndNotVec128); } - goto parse_error; - default: goto parse_error; - } - } - case 'y': - if (strcmp(op, "v128.any_true") == 0) { return makeUnary(s, UnaryOp::AnyTrueVec128); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': - if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); } - goto parse_error; - case 'c': - if (strcmp(op, "v128.const") == 0) { return makeConst(s, Type::v128); } - goto parse_error; - case 'l': { - switch (op[9]) { - case '\0': - if (strcmp(op, "v128.load") == 0) { return makeLoad(s, Type::v128, /*isAtomic=*/false); } - goto parse_error; - case '1': { - switch (op[11]) { - case '_': { - switch (op[12]) { - case 'l': - if (strcmp(op, "v128.load16_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load16LaneVec128); } + switch (op[1]) { + case '1': { + switch (op[2]) { + case '2': { + switch (op[5]) { + case 'a': { + switch (op[8]) { + case '\0': + if (strcmp(op, "v128.and") == 0) { return makeBinary(s, BinaryOp::AndVec128); } goto parse_error; - case 's': - if (strcmp(op, "v128.load16_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load16SplatVec128); } + case 'n': + if (strcmp(op, "v128.andnot") == 0) { return makeBinary(s, BinaryOp::AndNotVec128); } goto parse_error; default: goto parse_error; } } - case 'x': { - switch (op[14]) { - case 's': - if (strcmp(op, "v128.load16x4_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4SVec128); } + case 'b': + if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); } + goto parse_error; + case 'c': + if (strcmp(op, "v128.const") == 0) { return makeConst(s, Type::v128); } + goto parse_error; + case 'l': { + switch (op[9]) { + case '\0': + if (strcmp(op, "v128.load") == 0) { return makeLoad(s, Type::v128, /*isAtomic=*/false); } goto parse_error; - case 'u': - if (strcmp(op, "v128.load16x4_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4UVec128); } + case '1': + if (strcmp(op, "v128.load16_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec16x8); } + goto parse_error; + case '3': { + switch (op[12]) { + case 'l': + if (strcmp(op, "v128.load32_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec32x4); } + goto parse_error; + case 'z': + if (strcmp(op, "v128.load32_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32Zero); } + goto parse_error; + default: goto parse_error; + } + } + case '6': { + switch (op[12]) { + case 'l': + if (strcmp(op, "v128.load64_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec64x2); } + goto parse_error; + case 'z': + if (strcmp(op, "v128.load64_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64Zero); } + goto parse_error; + default: goto parse_error; + } + } + case '8': + if (strcmp(op, "v128.load8_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec8x16); } goto parse_error; default: goto parse_error; } } - default: goto parse_error; - } - } - case '3': { - switch (op[11]) { - case '_': { - switch (op[12]) { - case 'l': - if (strcmp(op, "v128.load32_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load32LaneVec128); } + case 'n': + if (strcmp(op, "v128.not") == 0) { return makeUnary(s, UnaryOp::NotVec128); } + goto parse_error; + case 'o': + if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); } + goto parse_error; + case 's': { + switch (op[10]) { + case '\0': + if (strcmp(op, "v128.store") == 0) { return makeStore(s, Type::v128, /*isAtomic=*/false); } goto parse_error; - case 's': - if (strcmp(op, "v128.load32_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32SplatVec128); } + case '1': + if (strcmp(op, "v128.store16_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec16x8); } goto parse_error; - case 'z': - if (strcmp(op, "v128.load32_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32ZeroVec128); } + case '3': + if (strcmp(op, "v128.store32_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec32x4); } goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (op[14]) { - case 's': - if (strcmp(op, "v128.load32x2_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2SVec128); } + case '6': + if (strcmp(op, "v128.store64_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec64x2); } goto parse_error; - case 'u': - if (strcmp(op, "v128.load32x2_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2UVec128); } + case '8': + if (strcmp(op, "v128.store8_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec8x16); } goto parse_error; default: goto parse_error; } } + case 'x': + if (strcmp(op, "v128.xor") == 0) { return makeBinary(s, BinaryOp::XorVec128); } + goto parse_error; default: goto parse_error; } } case '6': { - switch (op[12]) { + switch (op[6]) { case 'l': - if (strcmp(op, "v128.load64_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load64LaneVec128); } + if (strcmp(op, "v16x8.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec16x8); } goto parse_error; case 's': - if (strcmp(op, "v128.load64_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64SplatVec128); } + if (strcmp(op, "v16x8.signselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec16x8); } goto parse_error; - case 'z': - if (strcmp(op, "v128.load64_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64ZeroVec128); } - goto parse_error; - default: goto parse_error; - } - } - case '8': { - switch (op[10]) { - case '_': { - switch (op[11]) { - case 'l': - if (strcmp(op, "v128.load8_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load8LaneVec128); } - goto parse_error; - case 's': - if (strcmp(op, "v128.load8_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load8SplatVec128); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (op[13]) { - case 's': - if (strcmp(op, "v128.load8x8_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8SVec128); } - goto parse_error; - case 'u': - if (strcmp(op, "v128.load8x8_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8UVec128); } - goto parse_error; - default: goto parse_error; - } - } default: goto parse_error; } } default: goto parse_error; } } - case 'n': - if (strcmp(op, "v128.not") == 0) { return makeUnary(s, UnaryOp::NotVec128); } - goto parse_error; - case 'o': - if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); } - goto parse_error; - case 's': { - switch (op[10]) { - case '\0': - if (strcmp(op, "v128.store") == 0) { return makeStore(s, Type::v128, /*isAtomic=*/false); } + case '3': { + switch (op[6]) { + case 'l': + if (strcmp(op, "v32x4.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec32x4); } goto parse_error; - case '1': - if (strcmp(op, "v128.store16_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store16LaneVec128); } + case 's': + if (strcmp(op, "v32x4.signselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec32x4); } goto parse_error; - case '3': - if (strcmp(op, "v128.store32_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store32LaneVec128); } + default: goto parse_error; + } + } + case '6': { + switch (op[6]) { + case 'l': + if (strcmp(op, "v64x2.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec64x2); } goto parse_error; - case '6': - if (strcmp(op, "v128.store64_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store64LaneVec128); } + case 's': + if (strcmp(op, "v64x2.signselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec64x2); } goto parse_error; - case '8': - if (strcmp(op, "v128.store8_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store8LaneVec128); } + default: goto parse_error; + } + } + case '8': { + switch (op[6]) { + case 'l': + if (strcmp(op, "v8x16.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec8x16); } goto parse_error; + case 's': { + switch (op[7]) { + case 'h': + if (strcmp(op, "v8x16.shuffle") == 0) { return makeSIMDShuffle(s); } + goto parse_error; + case 'i': + if (strcmp(op, "v8x16.signselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::SignSelectVec8x16); } + goto parse_error; + case 'w': + if (strcmp(op, "v8x16.swizzle") == 0) { return makeBinary(s, BinaryOp::SwizzleVec8x16); } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } - case 'x': - if (strcmp(op, "v128.xor") == 0) { return makeBinary(s, BinaryOp::XorVec128); } - goto parse_error; default: goto parse_error; } } diff -Nru binaryen-108/src/ir/abstract.h binaryen-99/src/ir/abstract.h --- binaryen-108/src/ir/abstract.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/abstract.h 2021-01-07 20:01:06.000000000 +0000 @@ -21,13 +21,14 @@ #include -namespace wasm::Abstract { +namespace wasm { + +namespace Abstract { enum Op { // Unary Abs, Neg, - Popcnt, // Binary Add, Sub, @@ -66,11 +67,6 @@ op == RotRInt64; } -inline bool hasAnyReinterpret(UnaryOp op) { - return op == ReinterpretInt32 || op == ReinterpretInt64 || - op == ReinterpretFloat32 || op == ReinterpretFloat64; -} - // Provide a wasm type and an abstract op and get the concrete one. For example, // you can provide i32 and Add and receive the specific opcode for a 32-bit // addition, AddInt32. If the op does not exist, it returns Invalid. @@ -80,8 +76,6 @@ switch (op) { case EqZ: return EqZInt32; - case Popcnt: - return PopcntInt32; default: return InvalidUnary; } @@ -91,8 +85,6 @@ switch (op) { case EqZ: return EqZInt64; - case Popcnt: - return PopcntInt64; default: return InvalidUnary; } @@ -122,10 +114,11 @@ } case Type::v128: case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: { return InvalidUnary; @@ -294,10 +287,11 @@ } case Type::v128: case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: { return InvalidBinary; @@ -306,6 +300,8 @@ WASM_UNREACHABLE("invalid type"); } -} // namespace wasm::Abstract +} // namespace Abstract + +} // namespace wasm #endif // wasm_ir_abstract_h diff -Nru binaryen-108/src/ir/bits.h binaryen-99/src/ir/bits.h --- binaryen-108/src/ir/bits.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/bits.h 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,9 @@ #include "wasm-builder.h" #include -namespace wasm::Bits { +namespace wasm { + +namespace Bits { // get a mask to keep only the low # of bits inline int32_t lowBitMask(int32_t bits) { @@ -383,26 +385,9 @@ case WrapInt64: case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); - case ExtendS8Int32: { - auto maxBits = getMaxBits(unary->value, localInfoProvider); - return maxBits >= 8 ? Index(32) : maxBits; - } - case ExtendS16Int32: { - auto maxBits = getMaxBits(unary->value, localInfoProvider); - return maxBits >= 16 ? Index(32) : maxBits; - } - case ExtendS8Int64: { - auto maxBits = getMaxBits(unary->value, localInfoProvider); - return maxBits >= 8 ? Index(64) : maxBits; - } - case ExtendS16Int64: { - auto maxBits = getMaxBits(unary->value, localInfoProvider); - return maxBits >= 16 ? Index(64) : maxBits; - } - case ExtendS32Int64: case ExtendSInt32: { auto maxBits = getMaxBits(unary->value, localInfoProvider); - return maxBits >= 32 ? Index(64) : maxBits; + return maxBits == 32 ? Index(64) : maxBits; } default: { } @@ -411,8 +396,6 @@ // a tee passes through the value return getMaxBits(set->value, localInfoProvider); } else if (auto* get = curr->dynCast()) { - // TODO: Should this be optional? - assert(localInfoProvider); return localInfoProvider->getMaxBitsForLocal(get); } else if (auto* load = curr->dynCast()) { // if signed, then the sign-extension might fill all the bits @@ -433,6 +416,8 @@ } } -} // namespace wasm::Bits +} // namespace Bits + +} // namespace wasm #endif // wasm_ir_bits_h diff -Nru binaryen-108/src/ir/block-utils.h binaryen-99/src/ir/block-utils.h --- binaryen-108/src/ir/block-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/block-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -24,8 +24,9 @@ #include "wasm-builder.h" #include "wasm.h" -namespace wasm::BlockUtils { +namespace wasm { +namespace BlockUtils { // if a block has just one element, it can often be replaced // with that content template @@ -36,9 +37,10 @@ !BranchUtils::BranchSeeker::has(list[0], block->name)) { // just one element. try to replace the block auto* singleton = list[0]; - auto sideEffects = - EffectAnalyzer(parent->getPassOptions(), *parent->getModule(), singleton) - .hasSideEffects(); + auto sideEffects = EffectAnalyzer(parent->getPassOptions(), + parent->getModule()->features, + singleton) + .hasSideEffects(); if (!sideEffects && !singleton->type.isConcrete()) { // no side effects, and singleton is not returning a value, so we can // throw away the block and its contents, basically @@ -67,6 +69,8 @@ T* parent) { return simplifyToContents(block, parent, true); } -} // namespace wasm::BlockUtils +} // namespace BlockUtils + +} // namespace wasm #endif // wasm_ir_block_h diff -Nru binaryen-108/src/ir/branch-utils.h binaryen-99/src/ir/branch-utils.h --- binaryen-108/src/ir/branch-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/branch-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -21,7 +21,9 @@ #include "wasm-traversal.h" #include "wasm.h" -namespace wasm::BranchUtils { +namespace wasm { + +namespace BranchUtils { // Some branches are obviously not actually reachable (e.g. (br $out // (unreachable))) @@ -38,9 +40,9 @@ return true; } -// Perform a generic operation on uses of scope names (branch + delegate -// targets) in an expression. The provided function receives a Name& which it -// can modify if it needs to. +// Perform a generic operation on uses of scope names (branch targets) in an +// expression. The provided function receives a Name& which it can modify if it +// needs to. template void operateOnScopeNameUses(Expression* expr, T func) { #define DELEGATE_ID expr->_id @@ -48,23 +50,22 @@ auto* cast = expr->cast(); \ WASM_UNUSED(cast); -#define DELEGATE_GET_FIELD(id, field) cast->field +#define DELEGATE_GET_FIELD(id, name) cast->name -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) func(cast->field); +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) func(cast->name); -#define DELEGATE_FIELD_CHILD(id, field) -#define DELEGATE_FIELD_INT(id, field) -#define DELEGATE_FIELD_LITERAL(id, field) -#define DELEGATE_FIELD_NAME(id, field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) -#define DELEGATE_FIELD_TYPE(id, field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) -#define DELEGATE_FIELD_ADDRESS(id, field) -#define DELEGATE_FIELD_CHILD_VECTOR(id, field) -#define DELEGATE_FIELD_INT_ARRAY(id, field) +#define DELEGATE_FIELD_CHILD(id, name) +#define DELEGATE_FIELD_INT(id, name) +#define DELEGATE_FIELD_LITERAL(id, name) +#define DELEGATE_FIELD_NAME(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) +#define DELEGATE_FIELD_SIGNATURE(id, name) +#define DELEGATE_FIELD_TYPE(id, name) +#define DELEGATE_FIELD_ADDRESS(id, name) +#define DELEGATE_FIELD_CHILD_VECTOR(id, name) +#define DELEGATE_FIELD_INT_ARRAY(id, name) -#include "wasm-delegations-fields.def" +#include "wasm-delegations-fields.h" } // Similar to operateOnScopeNameUses, but also passes in the type that is sent @@ -78,29 +79,12 @@ func(name, br->value ? br->value->type : Type::none); } else if (auto* sw = expr->dynCast()) { func(name, sw->value ? sw->value->type : Type::none); - } else if (auto* br = expr->dynCast()) { - func(name, br->getSentType()); - } else { - assert(expr->is() || expr->is()); // delegate or rethrow - } - }); -} - -// Similar to operateOnScopeNameUses, but also passes in the expression that is -// sent if the branch is taken. nullptr is given if there is no value. -template -void operateOnScopeNameUsesAndSentValues(Expression* expr, T func) { - operateOnScopeNameUses(expr, [&](Name& name) { - // There isn't a delegate mechanism for getting a sent value, so do a direct - // if-else chain. This will need to be updated with new br variants. - if (auto* br = expr->dynCast()) { - func(name, br->value); - } else if (auto* sw = expr->dynCast()) { - func(name, sw->value); - } else if (auto* br = expr->dynCast()) { - func(name, br->ref); + } else if (auto* br = expr->dynCast()) { + func(name, br->sent); + } else if (auto* br = expr->dynCast()) { + func(name, br->getCastType()); } else { - assert(expr->is() || expr->is()); // delegate or rethrow + WASM_UNREACHABLE("bad br type"); } }); } @@ -114,22 +98,21 @@ auto* cast = expr->cast(); \ WASM_UNUSED(cast); -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) func(cast->field) +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) func(cast->name) -#define DELEGATE_FIELD_CHILD(id, field) -#define DELEGATE_FIELD_INT(id, field) -#define DELEGATE_FIELD_LITERAL(id, field) -#define DELEGATE_FIELD_NAME(id, field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) -#define DELEGATE_FIELD_TYPE(id, field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) -#define DELEGATE_FIELD_ADDRESS(id, field) -#define DELEGATE_FIELD_CHILD_VECTOR(id, field) -#define DELEGATE_FIELD_INT_ARRAY(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) +#define DELEGATE_FIELD_CHILD(id, name) +#define DELEGATE_FIELD_INT(id, name) +#define DELEGATE_FIELD_LITERAL(id, name) +#define DELEGATE_FIELD_NAME(id, name) +#define DELEGATE_FIELD_SIGNATURE(id, name) +#define DELEGATE_FIELD_TYPE(id, name) +#define DELEGATE_FIELD_ADDRESS(id, name) +#define DELEGATE_FIELD_CHILD_VECTOR(id, name) +#define DELEGATE_FIELD_INT_ARRAY(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) -#include "wasm-delegations-fields.def" +#include "wasm-delegations-fields.h" } using NameSet = std::set; @@ -152,46 +135,6 @@ return worked; } -// Replace all delegate/rethrow targets within the given AST. -inline void replaceExceptionTargets(Expression* ast, Name from, Name to) { - struct Replacer - : public PostWalker> { - Name from, to; - Replacer(Name from, Name to) : from(from), to(to) {} - void visitExpression(Expression* curr) { - if (curr->is() || curr->is()) { - operateOnScopeNameUses(curr, [&](Name& name) { - if (name == from) { - name = to; - } - }); - } - } - }; - Replacer replacer(from, to); - replacer.walk(ast); -} - -// Replace all branch targets within the given AST. -inline void replaceBranchTargets(Expression* ast, Name from, Name to) { - struct Replacer - : public PostWalker> { - Name from, to; - Replacer(Name from, Name to) : from(from), to(to) {} - void visitExpression(Expression* curr) { - if (Properties::isBranch(curr)) { - operateOnScopeNameUses(curr, [&](Name& name) { - if (name == from) { - name = to; - } - }); - } - } - }; - Replacer replacer(from, to); - replacer.walk(ast); -} - // Returns the set of targets to which we branch that are // outside of an expression. inline NameSet getExitingBranches(Expression* ast) { @@ -234,48 +177,6 @@ return scanner.targets; } -// Check if an expression defines a particular name as a branch target anywhere -// inside it. -inline bool hasBranchTarget(Expression* ast, Name target) { - if (!target.is()) { - return false; - } - - struct Scanner - : public PostWalker> { - Name target; - bool has = false; - - void visitExpression(Expression* curr) { - operateOnScopeNameDefs(curr, [&](Name& name) { - if (name == target) { - has = true; - } - }); - } - }; - Scanner scanner; - scanner.target = target; - scanner.walk(ast); - return scanner.has; -} - -// Get the name of the branch target that is defined in the expression, or an -// empty name if there is none. -inline Name getDefinedName(Expression* curr) { - Name ret; - operateOnScopeNameDefs(curr, [&](Name& name) { ret = name; }); - return ret; -} - -// Return the value sent by a branch instruction, or nullptr if there is none. -inline Expression* getSentValue(Expression* curr) { - Expression* ret = nullptr; - operateOnScopeNameUsesAndSentValues( - curr, [&](Name name, Expression* value) { ret = value; }); - return ret; -} - // Finds if there are branches targeting a name. Note that since names are // unique in our IR, we just need to look for the name, and do not need // to analyze scoping. @@ -284,14 +185,20 @@ Name target; Index found = 0; - - std::unordered_set types; + // None indicates no value is sent. + Type valueType = Type::none; BranchSeeker(Name target) : target(target) {} void noteFound(Type newType) { found++; - types.insert(newType); + if (newType != Type::none) { + if (found == 1) { + valueType = newType; + } else { + valueType = Type::getLeastUpperBound(valueType, newType); + } + } } void visitExpression(Expression* curr) { @@ -392,44 +299,8 @@ } }; -// Stores information about branch targets, specifically, finding them by their -// name, and finding the branches to them. -struct BranchTargets { - BranchTargets(Expression* expr) { inner.walk(expr); } - - // Gets the expression that defines this branch target, i.e., where we branch - // to if we branch to that name. - Expression* getTarget(Name name) { return inner.targets[name]; } - - // Gets the expressions branching to a target. - std::unordered_set getBranches(Name name) { - auto iter = inner.branches.find(name); - if (iter != inner.branches.end()) { - return iter->second; - } - return {}; - } - -private: - struct Inner : public PostWalker> { - void visitExpression(Expression* curr) { - operateOnScopeNameDefs(curr, [&](Name name) { - if (name.is()) { - targets[name] = curr; - } - }); - operateOnScopeNameUses(curr, [&](Name& name) { - if (name.is()) { - branches[name].insert(curr); - } - }); - } - - std::map targets; - std::map> branches; - } inner; -}; +} // namespace BranchUtils -} // namespace wasm::BranchUtils +} // namespace wasm #endif // wasm_ir_branch_h diff -Nru binaryen-108/src/ir/CMakeLists.txt binaryen-99/src/ir/CMakeLists.txt --- binaryen-108/src/ir/CMakeLists.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/CMakeLists.txt 2021-01-07 20:01:06.000000000 +0000 @@ -2,18 +2,9 @@ set(ir_SOURCES ExpressionAnalyzer.cpp ExpressionManipulator.cpp - eh-utils.cpp - intrinsics.cpp - lubs.cpp - memory-utils.cpp - module-utils.cpp - names.cpp - properties.cpp LocalGraph.cpp ReFinalize.cpp stack-utils.cpp - table-utils.cpp - type-updating.cpp module-splitting.cpp ${ir_HEADERS} ) diff -Nru binaryen-108/src/ir/cost.h binaryen-99/src/ir/cost.h --- binaryen-108/src/ir/cost.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/cost.h 2021-01-07 20:01:06.000000000 +0000 @@ -24,84 +24,82 @@ // Measure the execution cost of an AST. Very handwave-ey -using CostType = uint32_t; - -struct CostAnalyzer : public OverriddenVisitor { +struct CostAnalyzer : public OverriddenVisitor { CostAnalyzer(Expression* ast) { cost = visit(ast); } - CostType cost; + Index cost; - CostType maybeVisit(Expression* curr) { return curr ? visit(curr) : 0; } + Index maybeVisit(Expression* curr) { return curr ? visit(curr) : 0; } - CostType visitBlock(Block* curr) { - CostType ret = 0; + Index visitBlock(Block* curr) { + Index ret = 0; for (auto* child : curr->list) { ret += visit(child); } return ret; } - CostType visitIf(If* curr) { + Index visitIf(If* curr) { return 1 + visit(curr->condition) + std::max(visit(curr->ifTrue), maybeVisit(curr->ifFalse)); } - CostType visitLoop(Loop* curr) { return 5 * visit(curr->body); } - CostType visitBreak(Break* curr) { + Index visitLoop(Loop* curr) { return 5 * visit(curr->body); } + Index visitBreak(Break* curr) { return 1 + maybeVisit(curr->value) + maybeVisit(curr->condition); } - CostType visitSwitch(Switch* curr) { + Index visitSwitch(Switch* curr) { return 2 + visit(curr->condition) + maybeVisit(curr->value); } - CostType visitCall(Call* curr) { + Index visitCall(Call* curr) { // XXX this does not take into account if the call is to an import, which // may be costlier in general - CostType ret = 4; + Index ret = 4; for (auto* child : curr->operands) { ret += visit(child); } return ret; } - CostType visitCallIndirect(CallIndirect* curr) { - CostType ret = 6 + visit(curr->target); + Index visitCallIndirect(CallIndirect* curr) { + Index ret = 6 + visit(curr->target); for (auto* child : curr->operands) { ret += visit(child); } return ret; } - CostType visitCallRef(CallRef* curr) { - CostType ret = 5 + visit(curr->target); + Index visitCallRef(CallRef* curr) { + Index ret = 5 + visit(curr->target); for (auto* child : curr->operands) { ret += visit(child); } return ret; } - CostType visitLocalGet(LocalGet* curr) { return 0; } - CostType visitLocalSet(LocalSet* curr) { return 1 + visit(curr->value); } - CostType visitGlobalGet(GlobalGet* curr) { return 1; } - CostType visitGlobalSet(GlobalSet* curr) { return 2 + visit(curr->value); } - CostType visitLoad(Load* curr) { + Index visitLocalGet(LocalGet* curr) { return 0; } + Index visitLocalSet(LocalSet* curr) { return 1 + visit(curr->value); } + Index visitGlobalGet(GlobalGet* curr) { return 1; } + Index visitGlobalSet(GlobalSet* curr) { return 2 + visit(curr->value); } + Index visitLoad(Load* curr) { return 1 + visit(curr->ptr) + 10 * curr->isAtomic; } - CostType visitStore(Store* curr) { + Index visitStore(Store* curr) { return 2 + visit(curr->ptr) + visit(curr->value) + 10 * curr->isAtomic; } - CostType visitAtomicRMW(AtomicRMW* curr) { + Index visitAtomicRMW(AtomicRMW* curr) { return 100 + visit(curr->ptr) + visit(curr->value); } - CostType visitAtomicCmpxchg(AtomicCmpxchg* curr) { + Index visitAtomicCmpxchg(AtomicCmpxchg* curr) { return 100 + visit(curr->ptr) + visit(curr->expected) + visit(curr->replacement); } - CostType visitAtomicWait(AtomicWait* curr) { + Index visitAtomicWait(AtomicWait* curr) { return 100 + visit(curr->ptr) + visit(curr->expected) + visit(curr->timeout); } - CostType visitAtomicNotify(AtomicNotify* curr) { + Index visitAtomicNotify(AtomicNotify* curr) { return 100 + visit(curr->ptr) + visit(curr->notifyCount); } - CostType visitAtomicFence(AtomicFence* curr) { return 100; } - CostType visitConst(Const* curr) { return 1; } - CostType visitUnary(Unary* curr) { - CostType ret = 0; + Index visitAtomicFence(AtomicFence* curr) { return 100; } + Index visitConst(Const* curr) { return 1; } + Index visitUnary(Unary* curr) { + Index ret = 0; switch (curr->op) { case ClzInt32: case CtzInt32: @@ -174,23 +172,23 @@ case SplatVecF32x4: case SplatVecF64x2: case NotVec128: - case AnyTrueVec128: case AbsVecI8x16: case NegVecI8x16: + case AnyTrueVecI8x16: case AllTrueVecI8x16: case BitmaskVecI8x16: case PopcntVecI8x16: case AbsVecI16x8: case NegVecI16x8: + case AnyTrueVecI16x8: case AllTrueVecI16x8: case BitmaskVecI16x8: case AbsVecI32x4: case NegVecI32x4: + case AnyTrueVecI32x4: case AllTrueVecI32x4: case BitmaskVecI32x4: - case AbsVecI64x2: case NegVecI64x2: - case AllTrueVecI64x2: case BitmaskVecI64x2: case AbsVecF32x4: case NegVecF32x4: @@ -212,30 +210,24 @@ case ExtAddPairwiseUVecI16x8ToI32x4: case TruncSatSVecF32x4ToVecI32x4: case TruncSatUVecF32x4ToVecI32x4: + case TruncSatSVecF64x2ToVecI64x2: + case TruncSatUVecF64x2ToVecI64x2: case ConvertSVecI32x4ToVecF32x4: case ConvertUVecI32x4ToVecF32x4: - case ExtendLowSVecI8x16ToVecI16x8: - case ExtendHighSVecI8x16ToVecI16x8: - case ExtendLowUVecI8x16ToVecI16x8: - case ExtendHighUVecI8x16ToVecI16x8: - case ExtendLowSVecI16x8ToVecI32x4: - case ExtendHighSVecI16x8ToVecI32x4: - case ExtendLowUVecI16x8ToVecI32x4: - case ExtendHighUVecI16x8ToVecI32x4: - case ExtendLowSVecI32x4ToVecI64x2: - case ExtendHighSVecI32x4ToVecI64x2: - case ExtendLowUVecI32x4ToVecI64x2: - case ExtendHighUVecI32x4ToVecI64x2: - case ConvertLowSVecI32x4ToVecF64x2: - case ConvertLowUVecI32x4ToVecF64x2: - case TruncSatZeroSVecF64x2ToVecI32x4: - case TruncSatZeroUVecF64x2ToVecI32x4: - case DemoteZeroVecF64x2ToVecF32x4: - case PromoteLowVecF32x4ToVecF64x2: - case RelaxedTruncSVecF32x4ToVecI32x4: - case RelaxedTruncUVecF32x4ToVecI32x4: - case RelaxedTruncZeroSVecF64x2ToVecI32x4: - case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case ConvertSVecI64x2ToVecF64x2: + case ConvertUVecI64x2ToVecF64x2: + case WidenLowSVecI8x16ToVecI16x8: + case WidenHighSVecI8x16ToVecI16x8: + case WidenLowUVecI8x16ToVecI16x8: + case WidenHighUVecI8x16ToVecI16x8: + case WidenLowSVecI16x8ToVecI32x4: + case WidenHighSVecI16x8ToVecI32x4: + case WidenLowUVecI16x8ToVecI32x4: + case WidenHighUVecI16x8ToVecI32x4: + case WidenLowSVecI32x4ToVecI64x2: + case WidenHighSVecI32x4ToVecI64x2: + case WidenLowUVecI32x4ToVecI64x2: + case WidenHighUVecI32x4ToVecI64x2: ret = 1; break; case InvalidUnary: @@ -243,8 +235,8 @@ } return ret + visit(curr->value); } - CostType visitBinary(Binary* curr) { - CostType ret = 0; + Index visitBinary(Binary* curr) { + Index ret = 0; switch (curr->op) { case AddInt32: case SubInt32: @@ -257,7 +249,7 @@ case DivUInt32: case RemSInt32: case RemUInt32: - ret = curr->right->is() ? 2 : 3; + ret = 3; break; case AndInt32: case OrInt32: @@ -278,7 +270,7 @@ case DivUInt64: case RemSInt64: case RemUInt64: - ret = curr->right->is() ? 3 : 4; + ret = 3; break; case AndInt64: case OrInt64: @@ -379,11 +371,6 @@ case GeSVecI32x4: case GeUVecI32x4: case EqVecI64x2: - case NeVecI64x2: - case LtSVecI64x2: - case LeSVecI64x2: - case GtSVecI64x2: - case GeSVecI64x2: case EqVecF32x4: case NeVecF32x4: case LtVecF32x4: @@ -406,6 +393,11 @@ case SubVecI8x16: case SubSatSVecI8x16: case SubSatUVecI8x16: + ret = 1; + break; + case MulVecI8x16: + ret = 2; + break; case MinSVecI8x16: case MinUVecI8x16: case MaxSVecI8x16: @@ -469,8 +461,6 @@ case MaxVecF32x4: case PMinVecF32x4: case PMaxVecF32x4: - case RelaxedMinVecF32x4: - case RelaxedMaxVecF32x4: case AddVecF64x2: case SubVecF64x2: ret = 1; @@ -485,17 +475,11 @@ case MaxVecF64x2: case PMinVecF64x2: case PMaxVecF64x2: - case RelaxedMinVecF64x2: - case RelaxedMaxVecF64x2: case NarrowSVecI16x8ToVecI8x16: case NarrowUVecI16x8ToVecI8x16: case NarrowSVecI32x4ToVecI16x8: case NarrowUVecI32x4ToVecI16x8: - case SwizzleVecI8x16: - case RelaxedSwizzleVecI8x16: - case RelaxedQ15MulrSVecI16x8: - case DotI8x16I7x16SToVecI16x8: - case DotI8x16I7x16UToVecI16x8: + case SwizzleVec8x16: ret = 1; break; case InvalidBinary: @@ -503,168 +487,142 @@ } return ret + visit(curr->left) + visit(curr->right); } - CostType visitSelect(Select* curr) { + Index visitSelect(Select* curr) { return 1 + visit(curr->condition) + visit(curr->ifTrue) + visit(curr->ifFalse); } - CostType visitDrop(Drop* curr) { return visit(curr->value); } - CostType visitReturn(Return* curr) { return maybeVisit(curr->value); } - CostType visitMemorySize(MemorySize* curr) { return 1; } - CostType visitMemoryGrow(MemoryGrow* curr) { - return 100 + visit(curr->delta); - } - CostType visitMemoryInit(MemoryInit* curr) { + Index visitDrop(Drop* curr) { return visit(curr->value); } + Index visitReturn(Return* curr) { return maybeVisit(curr->value); } + Index visitMemorySize(MemorySize* curr) { return 1; } + Index visitMemoryGrow(MemoryGrow* curr) { return 100 + visit(curr->delta); } + Index visitMemoryInit(MemoryInit* curr) { return 6 + visit(curr->dest) + visit(curr->offset) + visit(curr->size); } - CostType visitMemoryCopy(MemoryCopy* curr) { - // TODO when the size is a constant, estimate the time based on that + Index visitMemoryCopy(MemoryCopy* curr) { return 6 + visit(curr->dest) + visit(curr->source) + visit(curr->size); } - CostType visitMemoryFill(MemoryFill* curr) { + Index visitMemoryFill(MemoryFill* curr) { return 6 + visit(curr->dest) + visit(curr->value) + visit(curr->size); } - CostType visitSIMDLoad(SIMDLoad* curr) { return 1 + visit(curr->ptr); } - CostType visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { - return 1 + CostType(curr->isStore()) + visit(curr->ptr) + visit(curr->vec); + Index visitSIMDLoad(SIMDLoad* curr) { return 1 + visit(curr->ptr); } + Index visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { + return 1 + Index(curr->isStore()) + visit(curr->ptr) + visit(curr->vec); } - CostType visitSIMDReplace(SIMDReplace* curr) { + Index visitSIMDReplace(SIMDReplace* curr) { return 2 + visit(curr->vec) + visit(curr->value); } - CostType visitSIMDExtract(SIMDExtract* curr) { return 1 + visit(curr->vec); } - CostType visitSIMDTernary(SIMDTernary* curr) { - CostType ret = 0; + Index visitSIMDExtract(SIMDExtract* curr) { return 1 + visit(curr->vec); } + Index visitSIMDTernary(SIMDTernary* curr) { + Index ret = 0; switch (curr->op) { case Bitselect: - case LaneselectI8x16: - case LaneselectI16x8: - case LaneselectI32x4: - case LaneselectI64x2: - case RelaxedFmaVecF32x4: - case RelaxedFmsVecF32x4: - case RelaxedFmaVecF64x2: - case RelaxedFmsVecF64x2: - case DotI8x16I7x16AddSToVecI32x4: - case DotI8x16I7x16AddUToVecI32x4: + case SignSelectVec8x16: + case SignSelectVec16x8: + case SignSelectVec32x4: + case SignSelectVec64x2: ret = 1; break; + case QFMAF32x4: + case QFMSF32x4: + case QFMAF64x2: + case QFMSF64x2: + ret = 2; + break; } return ret + visit(curr->a) + visit(curr->b) + visit(curr->c); } - CostType visitSIMDShift(SIMDShift* curr) { + Index visitSIMDShift(SIMDShift* curr) { return 1 + visit(curr->vec) + visit(curr->shift); } - CostType visitSIMDShuffle(SIMDShuffle* curr) { + Index visitSIMDShuffle(SIMDShuffle* curr) { return 1 + visit(curr->left) + visit(curr->right); } - CostType visitRefNull(RefNull* curr) { return 1; } - CostType visitRefIs(RefIs* curr) { return 1 + visit(curr->value); } - CostType visitRefFunc(RefFunc* curr) { return 1; } - CostType visitRefEq(RefEq* curr) { + Index visitPrefetch(Prefetch* curr) { return 0 + visit(curr->ptr); } + Index visitRefNull(RefNull* curr) { return 1; } + Index visitRefIsNull(RefIsNull* curr) { return 1 + visit(curr->value); } + Index visitRefFunc(RefFunc* curr) { return 1; } + Index visitRefEq(RefEq* curr) { return 1 + visit(curr->left) + visit(curr->right); } - CostType visitTableGet(TableGet* curr) { return 1 + visit(curr->index); } - CostType visitTableSet(TableSet* curr) { - return 2 + visit(curr->index) + visit(curr->value); - } - CostType visitTableSize(TableSize* curr) { return 1; } - CostType visitTableGrow(TableGrow* curr) { - return 100 + visit(curr->value) + visit(curr->delta); - } - CostType visitTry(Try* curr) { + Index visitTry(Try* curr) { // We assume no exception will be thrown in most cases - return visit(curr->body); + return visit(curr->body) + maybeVisit(curr->catchBody); } - CostType visitThrow(Throw* curr) { - CostType ret = 100; + Index visitThrow(Throw* curr) { + Index ret = 100; for (auto* child : curr->operands) { ret += visit(child); } return ret; } - CostType visitRethrow(Rethrow* curr) { return 100; } - CostType visitTupleMake(TupleMake* curr) { - CostType ret = 0; + Index visitRethrow(Rethrow* curr) { return 100 + visit(curr->exnref); } + Index visitBrOnExn(BrOnExn* curr) { + return 1 + visit(curr->exnref) + curr->sent.size(); + } + Index visitTupleMake(TupleMake* curr) { + Index ret = 0; for (auto* child : curr->operands) { ret += visit(child); } return ret; } - CostType visitTupleExtract(TupleExtract* curr) { return visit(curr->tuple); } - CostType visitPop(Pop* curr) { return 0; } - CostType visitNop(Nop* curr) { return 0; } - CostType visitUnreachable(Unreachable* curr) { return 0; } - CostType visitDataDrop(DataDrop* curr) { return 5; } - CostType visitI31New(I31New* curr) { return 3 + visit(curr->value); } - CostType visitI31Get(I31Get* curr) { return 2 + visit(curr->i31); } - CostType visitRefTest(RefTest* curr) { - return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + - maybeVisit(curr->rtt); + Index visitTupleExtract(TupleExtract* curr) { return visit(curr->tuple); } + Index visitPop(Pop* curr) { return 0; } + Index visitNop(Nop* curr) { return 0; } + Index visitUnreachable(Unreachable* curr) { return 0; } + Index visitDataDrop(DataDrop* curr) { return 5; } + Index visitI31New(I31New* curr) { return 3 + visit(curr->value); } + Index visitI31Get(I31Get* curr) { return 2 + visit(curr->i31); } + Index visitRefTest(RefTest* curr) { + return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->rtt); } - CostType visitRefCast(RefCast* curr) { - return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + - maybeVisit(curr->rtt); + Index visitRefCast(RefCast* curr) { + return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->rtt); } - CostType visitBrOn(BrOn* curr) { - // BrOnCast has more work to do with the rtt, so add a little there. - CostType base = curr->op == BrOnCast ? 3 : 2; - return base + nullCheckCost(curr->ref) + maybeVisit(curr->ref) + - maybeVisit(curr->rtt); + Index visitBrOnCast(BrOnCast* curr) { + return 3 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->rtt); } - CostType visitRttCanon(RttCanon* curr) { + Index visitRttCanon(RttCanon* curr) { // TODO: investigate actual RTT costs in VMs return 1; } - CostType visitRttSub(RttSub* curr) { + Index visitRttSub(RttSub* curr) { // TODO: investigate actual RTT costs in VMs return 2 + visit(curr->parent); } - CostType visitStructNew(StructNew* curr) { + Index visitStructNew(StructNew* curr) { // While allocation itself is almost free with generational GC, there is // at least some baseline cost, plus writing the fields. (If we use default // values for the fields, then it is possible they are all 0 and if so, we // can get that almost for free as well, so don't add anything there.) - CostType ret = 4 + maybeVisit(curr->rtt) + curr->operands.size(); + Index ret = 4 + visit(curr->rtt) + curr->operands.size(); for (auto* child : curr->operands) { ret += visit(child); } return ret; } - CostType visitStructGet(StructGet* curr) { + Index visitStructGet(StructGet* curr) { return 1 + nullCheckCost(curr->ref) + visit(curr->ref); } - CostType visitStructSet(StructSet* curr) { + Index visitStructSet(StructSet* curr) { return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->value); } - CostType visitArrayNew(ArrayNew* curr) { - return 4 + maybeVisit(curr->rtt) + visit(curr->size) + - maybeVisit(curr->init); - } - CostType visitArrayInit(ArrayInit* curr) { - CostType ret = 4 + maybeVisit(curr->rtt); - for (auto* child : curr->values) { - ret += visit(child); - } - return ret; + Index visitArrayNew(ArrayNew* curr) { + return 4 + visit(curr->rtt) + visit(curr->size) + visit(curr->init); } - CostType visitArrayGet(ArrayGet* curr) { + Index visitArrayGet(ArrayGet* curr) { return 1 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->index); } - CostType visitArraySet(ArraySet* curr) { + Index visitArraySet(ArraySet* curr) { return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->index) + visit(curr->value); } - CostType visitArrayLen(ArrayLen* curr) { + Index visitArrayLen(ArrayLen* curr) { return 1 + nullCheckCost(curr->ref) + visit(curr->ref); } - CostType visitArrayCopy(ArrayCopy* curr) { - // Similar to MemoryCopy. - return 6 + visit(curr->destRef) + visit(curr->destIndex) + - visit(curr->srcRef) + visit(curr->srcIndex) + visit(curr->length); - } - CostType visitRefAs(RefAs* curr) { return 1 + visit(curr->value); } private: - CostType nullCheckCost(Expression* ref) { + Index nullCheckCost(Expression* ref) { // A nullable type requires a bounds check in most VMs. return ref->type.isNullable(); } diff -Nru binaryen-108/src/ir/debug.h binaryen-99/src/ir/debug.h --- binaryen-108/src/ir/debug.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/debug.h 2021-01-07 20:01:06.000000000 +0000 @@ -19,7 +19,9 @@ #include -namespace wasm::debug { +namespace wasm { + +namespace debug { // Given an expression and a copy of it in another function, copy the debug // info into the second function. @@ -50,6 +52,8 @@ } }; -} // namespace wasm::debug +} // namespace debug + +} // namespace wasm #endif // wasm_ir_debug_h diff -Nru binaryen-108/src/ir/effects.h binaryen-99/src/ir/effects.h --- binaryen-108/src/ir/effects.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/effects.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,30 +17,28 @@ #ifndef wasm_ir_effects_h #define wasm_ir_effects_h -#include "ir/intrinsics.h" #include "pass.h" #include "wasm-traversal.h" namespace wasm { -// Analyze various possible effects. +// Look for side effects, including control flow +// TODO: optimize class EffectAnalyzer { public: EffectAnalyzer(const PassOptions& passOptions, - Module& module, + FeatureSet features, Expression* ast = nullptr) : ignoreImplicitTraps(passOptions.ignoreImplicitTraps), - trapsNeverHappen(passOptions.trapsNeverHappen), module(module), - features(module.features) { + debugInfo(passOptions.debugInfo), features(features) { if (ast) { walk(ast); } } bool ignoreImplicitTraps; - bool trapsNeverHappen; - Module& module; + bool debugInfo; FeatureSet features; // Walk an expression and all its children. @@ -69,37 +67,15 @@ bool calls = false; std::set localsRead; std::set localsWritten; - std::set mutableGlobalsRead; + std::set globalsRead; std::set globalsWritten; bool readsMemory = false; bool writesMemory = false; - bool readsTable = false; - bool writesTable = false; - // TODO: More specific type-based alias analysis, and not just at the - // struct/array level. - bool readsMutableStruct = false; - bool writesStruct = false; - bool readsArray = false; - bool writesArray = false; // A trap, either from an unreachable instruction, or from an implicit trap // that we do not ignore (see below). - // // Note that we ignore trap differences, so it is ok to reorder traps with // each other, but it is not ok to remove them or reorder them with other // effects in a noticeable way. - // - // Note also that we ignore runtime-dependent traps, such as hitting a - // recursion limit or running out of memory. Such traps are not part of wasm's - // official semantics, and they can occur anywhere: *any* instruction could in - // theory be implemented by a VM call (as will be the case when running in an - // interpreter), and such a call could run out of stack or memory in - // principle. To put it another way, an i32 division by zero is the program - // doing something bad that causes a trap, but the VM running out of memory is - // the VM doing something bad - and therefore the VM behaving in a way that is - // not according to the wasm semantics - and we do not model such things. Note - // that as a result we do *not* mark things like GC allocation instructions as - // having side effects, which has the nice benefit of making it possible to - // eliminate an allocation whose result is not captured. bool trap = false; // A trap from an instruction like a load or div/rem, which may trap on corner // cases. If we do not ignore implicit traps then these are counted as a trap. @@ -107,17 +83,15 @@ // An atomic load/store/RMW/Cmpxchg or an operator that has a defined ordering // wrt atomics (e.g. memory.grow) bool isAtomic = false; - bool throws_ = false; - // The nested depth of try-catch_all. If an instruction that may throw is - // inside an inner try-catch_all, we don't mark it as 'throws_', because it - // will be caught by an inner catch_all. We only count 'try's with a - // 'catch_all' because instructions within a 'try' without a 'catch_all' can - // still throw outside of the try. + bool throws = false; + // The nested depth of try. If an instruction that may throw is inside an + // inner try, we don't mark it as 'throws', because it will be caught by an + // inner catch. size_t tryDepth = 0; // The nested depth of catch. This is necessary to track danglng pops. size_t catchDepth = 0; - // If this expression contains 'pop's that are not enclosed in 'catch' body. - // For example, (drop (pop i32)) should set this to true. + // If this expression contains 'exnref.pop's that are not enclosed in 'catch' + // body. For example, (drop (exnref.pop)) should set this to true. bool danglingPop = false; // Helper functions to check for various effect types @@ -125,16 +99,10 @@ bool accessesLocal() const { return localsRead.size() + localsWritten.size() > 0; } - bool accessesMutableGlobal() const { - return globalsWritten.size() + mutableGlobalsRead.size() > 0; + bool accessesGlobal() const { + return globalsRead.size() + globalsWritten.size() > 0; } bool accessesMemory() const { return calls || readsMemory || writesMemory; } - bool accessesTable() const { return calls || readsTable || writesTable; } - bool accessesMutableStruct() const { - return calls || readsMutableStruct || writesStruct; - } - bool accessesArray() const { return calls || readsArray || writesArray; } - bool throws() const { return throws_ || !delegateTargets.empty(); } // Check whether this may transfer control flow to somewhere outside of this // expression (aside from just flowing out normally). That includes a break // or a throw (if the throw is not known to be caught inside this expression; @@ -143,53 +111,24 @@ // caught in the function at all, which would mean control flow cannot be // transferred inside the function, but this expression does not know that). bool transfersControlFlow() const { - return branchesOut || throws() || hasExternalBreakTargets(); + return branchesOut || throws || hasExternalBreakTargets(); } // Changes something in globally-stored state. bool writesGlobalState() const { - return globalsWritten.size() || writesMemory || writesTable || - writesStruct || writesArray || isAtomic || calls; + return globalsWritten.size() || writesMemory || isAtomic || calls; } - bool readsMutableGlobalState() const { - return mutableGlobalsRead.size() || readsMemory || readsTable || - readsMutableStruct || readsArray || isAtomic || calls; + bool readsGlobalState() const { + return globalsRead.size() || readsMemory || isAtomic || calls; } - bool hasNonTrapSideEffects() const { + bool hasSideEffects() const { return localsWritten.size() > 0 || danglingPop || writesGlobalState() || - throws() || transfersControlFlow(); - } - - bool hasSideEffects() const { return trap || hasNonTrapSideEffects(); } - - // Check if there are side effects, and they are of a kind that cannot be - // removed by optimization passes. - // - // The difference between this and hasSideEffects is subtle, and only related - // to trapsNeverHappen - if trapsNeverHappen then any trap we see is removable - // by optimizations. In general, you should call hasSideEffects, and only call - // this method if you are certain that it is a place that would not perform an - // unsafe transformation with a trap. Specifically, if a pass calls this - // and gets the result that there are no unremovable side effects, then it - // must either - // - // 1. Remove any side effects present, if any, so they no longer exist. - // 2. Keep the code exactly where it is. - // - // If instead of 1&2 a pass kept the side effect and also reordered the code - // with other things, then that could be bad, as the side effect might have - // been behind a condition that avoids it occurring. - // - // TODO: Go through the optimizer and use this in all places that do not move - // code around. - bool hasUnremovableSideEffects() const { - return hasNonTrapSideEffects() || (trap && !trapsNeverHappen); + trap || throws || transfersControlFlow(); } - bool hasAnything() const { - return hasSideEffects() || accessesLocal() || readsMemory || readsTable || - accessesMutableGlobal(); + return hasSideEffects() || accessesLocal() || readsMemory || + accessesGlobal(); } // check if we break to anything external from ourselves @@ -202,12 +141,6 @@ (other.transfersControlFlow() && hasSideEffects()) || ((writesMemory || calls) && other.accessesMemory()) || ((other.writesMemory || other.calls) && accessesMemory()) || - ((writesTable || calls) && other.accessesTable()) || - ((other.writesTable || other.calls) && accessesTable()) || - ((writesStruct || calls) && other.accessesMutableStruct()) || - ((other.writesStruct || other.calls) && accessesMutableStruct()) || - ((writesArray || calls) && other.accessesArray()) || - ((other.writesArray || other.calls) && accessesArray()) || (danglingPop || other.danglingPop)) { return true; } @@ -227,17 +160,17 @@ return true; } } - if ((other.calls && accessesMutableGlobal()) || - (calls && other.accessesMutableGlobal())) { + if ((other.calls && accessesGlobal()) || + (calls && other.accessesGlobal())) { return true; } for (auto global : globalsWritten) { - if (other.mutableGlobalsRead.count(global) || + if (other.globalsRead.count(global) || other.globalsWritten.count(global)) { return true; } } - for (auto global : mutableGlobalsRead) { + for (auto global : globalsRead) { if (other.globalsWritten.count(global)) { return true; } @@ -252,7 +185,7 @@ // function, so transfersControlFlow would be true) - while we allow the // reordering of traps with each other, we do not reorder exceptions with // anything. - assert(!((trap && other.throws()) || (throws() && other.trap))); + assert(!((trap && other.throws) || (throws && other.trap))); // We can't reorder an implicit trap in a way that could alter what global // state is modified. if ((trap && other.writesGlobalState()) || @@ -267,17 +200,10 @@ calls = calls || other.calls; readsMemory = readsMemory || other.readsMemory; writesMemory = writesMemory || other.writesMemory; - readsTable = readsTable || other.readsTable; - writesTable = writesTable || other.writesTable; - readsMutableStruct = readsMutableStruct || other.readsMutableStruct; - writesStruct = writesStruct || other.writesStruct; - readsArray = readsArray || other.readsArray; - writesArray = writesArray || other.writesArray; trap = trap || other.trap; implicitTrap = implicitTrap || other.implicitTrap; - trapsNeverHappen = trapsNeverHappen || other.trapsNeverHappen; isAtomic = isAtomic || other.isAtomic; - throws_ = throws_ || other.throws_; + throws = throws || other.throws; danglingPop = danglingPop || other.danglingPop; for (auto i : other.localsRead) { localsRead.insert(i); @@ -285,8 +211,8 @@ for (auto i : other.localsWritten) { localsWritten.insert(i); } - for (auto i : other.mutableGlobalsRead) { - mutableGlobalsRead.insert(i); + for (auto i : other.globalsRead) { + globalsRead.insert(i); } for (auto i : other.globalsWritten) { globalsWritten.insert(i); @@ -294,9 +220,6 @@ for (auto i : other.breakTargets) { breakTargets.insert(i); } - for (auto i : other.delegateTargets) { - delegateTargets.insert(i); - } } // the checks above happen after the node's children were processed, in the @@ -319,7 +242,6 @@ } std::set breakTargets; - std::set delegateTargets; private: struct InternalAnalyzer @@ -336,10 +258,7 @@ if (curr->is()) { self->pushTask(doVisitTry, currp); self->pushTask(doEndCatch, currp); - auto& catchBodies = curr->cast()->catchBodies; - for (int i = int(catchBodies.size()) - 1; i >= 0; i--) { - self->pushTask(scan, &catchBodies[i]); - } + self->pushTask(scan, &curr->cast()->catchBody); self->pushTask(doStartCatch, currp); self->pushTask(scan, &curr->cast()->body); self->pushTask(doStartTry, currp); @@ -350,34 +269,12 @@ } static void doStartTry(InternalAnalyzer* self, Expression** currp) { - Try* curr = (*currp)->cast(); - // We only count 'try's with a 'catch_all' because instructions within a - // 'try' without a 'catch_all' can still throw outside of the try. - if (curr->hasCatchAll()) { - self->parent.tryDepth++; - } + self->parent.tryDepth++; } static void doStartCatch(InternalAnalyzer* self, Expression** currp) { - Try* curr = (*currp)->cast(); - // This is conservative. When an inner try-delegate targets the current - // expression, even if the try-delegate's body can't throw, we consider - // the current expression can throw for simplicity, unless the current - // expression is not inside a try-catch_all. It is hard to figure out - // whether the original try-delegate's body throws or not at this point. - if (curr->name.is()) { - if (self->parent.delegateTargets.count(curr->name) && - self->parent.tryDepth == 0) { - self->parent.throws_ = true; - } - self->parent.delegateTargets.erase(curr->name); - } - // We only count 'try's with a 'catch_all' because instructions within a - // 'try' without a 'catch_all' can still throw outside of the try. - if (curr->hasCatchAll()) { - assert(self->parent.tryDepth > 0 && "try depth cannot be negative"); - self->parent.tryDepth--; - } + assert(self->parent.tryDepth > 0 && "try depth cannot be negative"); + self->parent.tryDepth--; self->parent.catchDepth++; } @@ -418,24 +315,25 @@ } void visitCall(Call* curr) { - // call.without.effects has no effects. - if (Intrinsics(parent.module).isCallWithoutEffects(curr)) { - return; - } - parent.calls = true; // When EH is enabled, any call can throw. if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) { - parent.throws_ = true; + parent.throws = true; } if (curr->isReturn) { parent.branchesOut = true; } + if (parent.debugInfo) { + // debugInfo call imports must be preserved very strongly, do not + // move code around them + // FIXME: we could check if the call is to an import + parent.branchesOut = true; + } } void visitCallIndirect(CallIndirect* curr) { parent.calls = true; if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) { - parent.throws_ = true; + parent.throws = true; } if (curr->isReturn) { parent.branchesOut = true; @@ -448,9 +346,7 @@ parent.localsWritten.insert(curr->index); } void visitGlobalGet(GlobalGet* curr) { - if (parent.module.getGlobal(curr->name)->mutable_ == Mutable) { - parent.mutableGlobalsRead.insert(curr->name); - } + parent.globalsRead.insert(curr->name); } void visitGlobalSet(GlobalSet* curr) { parent.globalsWritten.insert(curr->name); @@ -519,6 +415,11 @@ } parent.implicitTrap = true; } + void visitPrefetch(Prefetch* curr) { + // Do not reorder with respect to other memory ops + parent.writesMemory = true; + parent.readsMemory = true; + } void visitMemoryInit(MemoryInit* curr) { parent.writesMemory = true; parent.implicitTrap = true; @@ -596,7 +497,6 @@ parent.isAtomic = true; } void visitMemoryGrow(MemoryGrow* curr) { - // TODO: find out if calls is necessary here parent.calls = true; // memory.grow technically does a read-modify-write operation on the // memory size in the successful case, modifying the set of valid @@ -607,42 +507,27 @@ parent.isAtomic = true; } void visitRefNull(RefNull* curr) {} - void visitRefIs(RefIs* curr) {} + void visitRefIsNull(RefIsNull* curr) {} void visitRefFunc(RefFunc* curr) {} void visitRefEq(RefEq* curr) {} - void visitTableGet(TableGet* curr) { - parent.readsTable = true; - parent.implicitTrap = true; - } - void visitTableSet(TableSet* curr) { - parent.writesTable = true; - parent.implicitTrap = true; - } - void visitTableSize(TableSize* curr) { parent.readsTable = true; } - void visitTableGrow(TableGrow* curr) { - // table.grow technically does a read-modify-write operation on the - // table size in the successful case, modifying the set of valid - // indices, and just a read operation in the failure case - parent.readsTable = true; - parent.writesTable = true; - } - void visitTry(Try* curr) { - if (curr->delegateTarget.is()) { - parent.delegateTargets.insert(curr->delegateTarget); - } - } + void visitTry(Try* curr) {} void visitThrow(Throw* curr) { if (parent.tryDepth == 0) { - parent.throws_ = true; + parent.throws = true; } } void visitRethrow(Rethrow* curr) { if (parent.tryDepth == 0) { - parent.throws_ = true; + parent.throws = true; } // traps when the arg is null parent.implicitTrap = true; } + void visitBrOnExn(BrOnExn* curr) { + parent.breakTargets.insert(curr->name); + // traps when the arg is null + parent.implicitTrap = true; + } void visitNop(Nop* curr) {} void visitUnreachable(Unreachable* curr) { parent.trap = true; } void visitPop(Pop* curr) { @@ -657,7 +542,7 @@ void visitCallRef(CallRef* curr) { parent.calls = true; if (parent.features.hasExceptionHandling() && parent.tryDepth == 0) { - parent.throws_ = true; + parent.throws = true; } if (curr->isReturn) { parent.branchesOut = true; @@ -670,41 +555,30 @@ // Traps if the ref is not null and it has an invalid rtt. parent.implicitTrap = true; } - void visitBrOn(BrOn* curr) { parent.breakTargets.insert(curr->name); } + void visitBrOnCast(BrOnCast* curr) { + parent.breakTargets.insert(curr->name); + } void visitRttCanon(RttCanon* curr) {} void visitRttSub(RttSub* curr) {} void visitStructNew(StructNew* curr) {} void visitStructGet(StructGet* curr) { - if (curr->ref->type == Type::unreachable) { - return; - } - if (curr->ref->type.getHeapType() - .getStruct() - .fields[curr->index] - .mutable_ == Mutable) { - parent.readsMutableStruct = true; - } // traps when the arg is null if (curr->ref->type.isNullable()) { parent.implicitTrap = true; } } void visitStructSet(StructSet* curr) { - parent.writesStruct = true; // traps when the arg is null if (curr->ref->type.isNullable()) { parent.implicitTrap = true; } } void visitArrayNew(ArrayNew* curr) {} - void visitArrayInit(ArrayInit* curr) {} void visitArrayGet(ArrayGet* curr) { - parent.readsArray = true; // traps when the arg is null or the index out of bounds parent.implicitTrap = true; } void visitArraySet(ArraySet* curr) { - parent.writesArray = true; // traps when the arg is null or the index out of bounds parent.implicitTrap = true; } @@ -714,35 +588,17 @@ parent.implicitTrap = true; } } - void visitArrayCopy(ArrayCopy* curr) { - parent.readsArray = true; - parent.writesArray = true; - // traps when a ref is null, or when out of bounds. - parent.implicitTrap = true; - } - void visitRefAs(RefAs* curr) { - // traps when the arg is not valid - parent.implicitTrap = true; - // Note: We could be more precise here and report the lack of a possible - // trap if the input is non-nullable (and also of the right kind for - // RefAsFunc etc.). However, we have optimization passes that will - // remove a RefAs in such a case (in OptimizeInstructions, and also - // Vacuum in trapsNeverHappen mode), so duplicating that code here would - // only help until the next time those optimizations run. As a tradeoff, - // we keep the code here simpler, but it does mean another optimization - // cycle may be needed in some cases. - } }; public: // Helpers static bool canReorder(const PassOptions& passOptions, - Module& module, + FeatureSet features, Expression* a, Expression* b) { - EffectAnalyzer aEffects(passOptions, module, a); - EffectAnalyzer bEffects(passOptions, module, b); + EffectAnalyzer aEffects(passOptions, features, a); + EffectAnalyzer bEffects(passOptions, features, b); return !aEffects.invalidates(bEffects); } @@ -758,14 +614,11 @@ WritesGlobal = 1 << 5, ReadsMemory = 1 << 6, WritesMemory = 1 << 7, - ReadsTable = 1 << 8, - WritesTable = 1 << 9, - ImplicitTrap = 1 << 10, - IsAtomic = 1 << 11, - Throws = 1 << 12, - DanglingPop = 1 << 13, - TrapsNeverHappen = 1 << 14, - Any = (1 << 15) - 1 + ImplicitTrap = 1 << 8, + IsAtomic = 1 << 9, + Throws = 1 << 10, + DanglingPop = 1 << 11, + Any = (1 << 12) - 1 }; uint32_t getSideEffects() const { uint32_t effects = 0; @@ -781,7 +634,7 @@ if (localsWritten.size() > 0) { effects |= SideEffects::WritesLocal; } - if (mutableGlobalsRead.size()) { + if (globalsRead.size() > 0) { effects |= SideEffects::ReadsGlobal; } if (globalsWritten.size() > 0) { @@ -793,22 +646,13 @@ if (writesMemory) { effects |= SideEffects::WritesMemory; } - if (readsTable) { - effects |= SideEffects::ReadsTable; - } - if (writesTable) { - effects |= SideEffects::WritesTable; - } if (implicitTrap) { effects |= SideEffects::ImplicitTrap; } - if (trapsNeverHappen) { - effects |= SideEffects::TrapsNeverHappen; - } if (isAtomic) { effects |= SideEffects::IsAtomic; } - if (throws_) { + if (throws) { effects |= SideEffects::Throws; } if (danglingPop) { @@ -823,10 +667,7 @@ } private: - void pre() { - breakTargets.clear(); - delegateTargets.clear(); - } + void pre() { breakTargets.clear(); } void post() { assert(tryDepth == 0); @@ -838,20 +679,6 @@ } } }; - -// Calculate effects only on the node itself (shallowly), and not on -// children. -class ShallowEffectAnalyzer : public EffectAnalyzer { -public: - ShallowEffectAnalyzer(const PassOptions& passOptions, - Module& module, - Expression* ast = nullptr) - : EffectAnalyzer(passOptions, module) { - if (ast) { - visit(ast); - } - } -}; } // namespace wasm diff -Nru binaryen-108/src/ir/eh-utils.cpp binaryen-99/src/ir/eh-utils.cpp --- binaryen-108/src/ir/eh-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/eh-utils.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,167 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/eh-utils.h" -#include "ir/branch-utils.h" -#include "ir/find_all.h" -#include "ir/type-updating.h" - -namespace wasm { - -namespace EHUtils { - -// This returns three values, some of them as output parameters: -// - Return value: 'pop' expression (Expression*), when there is one in -// first-descendant line. If there's no such pop, it returns null. -// - isPopNested: Whether the discovered 'pop' is nested within a block -// - popPtr: 'pop' expression's pointer (Expression**), when there is one found -// -// When 'catchBody' itself is a 'pop', 'pop''s pointer is null, because there is -// no way to get the given expression's address. But that's fine because pop's -// pointer is only necessary (in handleBlockNestedPops) to fix it up when it is -// nested, and if 'catchBody' itself is a pop, we don't need to fix it up. -static Expression* -getFirstPop(Expression* catchBody, bool& isPopNested, Expression**& popPtr) { - Expression* firstChild = catchBody; - isPopNested = false; - popPtr = nullptr; - // When there are multiple expressions within a catch body, an implicit - // block is created within it for convenience purposes. - auto* implicitBlock = catchBody->dynCast(); - - // Go down the line for the first child until we reach a leaf. A pop should be - // in that first-decendant line. - Expression** firstChildPtr = nullptr; - while (true) { - if (firstChild->is()) { - popPtr = firstChildPtr; - return firstChild; - } - - if (Properties::isControlFlowStructure(firstChild)) { - if (auto* iff = firstChild->dynCast()) { - // If's condition is a value child who comes before an 'if' instruction - // in binary, it is fine if a 'pop' is in there. We don't allow a 'pop' - // to be in an 'if''s then or else body because they are not first - // descendants. - firstChild = iff->condition; - firstChildPtr = &iff->condition; - continue; - } else if (firstChild->is()) { - // We don't allow the pop to be included in a loop, because it cannot be - // run more than once - return nullptr; - } - if (firstChild->is()) { - // If there are no branches that targets the implicit block, it will be - // removed when written back. But if there are branches that target the - // implicit block, - // (catch $e - // (block $l0 - // (pop i32) ;; within a block! - // (br $l0) - // ... - // ) - // This cannot be removed, so this is considered a nested pop (which we - // should fix). - if (firstChild == implicitBlock) { - if (BranchUtils::BranchSeeker::has(implicitBlock, - implicitBlock->name)) { - isPopNested = true; - } - } else { - isPopNested = true; - } - } else if (firstChild->is()) { - isPopNested = true; - } else { - WASM_UNREACHABLE("Unexpected control flow expression"); - } - } - ChildIterator it(firstChild); - if (it.getNumChildren() == 0) { - return nullptr; - } - firstChildPtr = &*it.begin(); - firstChild = *firstChildPtr; - } -} - -bool containsValidDanglingPop(Expression* catchBody) { - bool isPopNested = false; - Expression** popPtr = nullptr; - auto* pop = getFirstPop(catchBody, isPopNested, popPtr); - return pop != nullptr && !isPopNested; -} - -void handleBlockNestedPop(Try* try_, Function* func, Module& wasm) { - Builder builder(wasm); - for (Index i = 0; i < try_->catchTags.size(); i++) { - Name tagName = try_->catchTags[i]; - auto* tag = wasm.getTag(tagName); - if (tag->sig.params == Type::none) { - continue; - } - - auto* catchBody = try_->catchBodies[i]; - bool isPopNested = false; - Expression** popPtr = nullptr; - Expression* pop = getFirstPop(catchBody, isPopNested, popPtr); - assert(pop && "Pop has not been found in this catch"); - - // Change code like - // (catch $e - // ... - // (block - // (pop i32) - // ) - // ) - // into - // (catch $e - // (local.set $new - // (pop i32) - // ) - // ... - // (block - // (local.get $new) - // ) - // ) - if (isPopNested) { - assert(popPtr); - Index newLocal = builder.addVar(func, pop->type); - try_->catchBodies[i] = - builder.makeSequence(builder.makeLocalSet(newLocal, pop), catchBody); - *popPtr = builder.makeLocalGet(newLocal, pop->type); - } - } -} - -void handleBlockNestedPops(Function* func, Module& wasm) { - if (!wasm.features.hasExceptionHandling()) { - return; - } - FindAll trys(func->body); - for (auto* try_ : trys.list) { - handleBlockNestedPop(try_, func, wasm); - } - // Pops we handled can be of non-defaultable types, so we may have created - // non-nullable type locals. Fix them. - TypeUpdating::handleNonDefaultableLocals(func, wasm); -} - -} // namespace EHUtils - -} // namespace wasm diff -Nru binaryen-108/src/ir/eh-utils.h binaryen-99/src/ir/eh-utils.h --- binaryen-108/src/ir/eh-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/eh-utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_eh_h -#define wasm_ir_eh_h - -#include "wasm.h" - -namespace wasm { - -namespace EHUtils { - -// Returns true if a 'pop' instruction exists in a valid location, which means -// right after a 'catch' instruction in binary writing order. -// - This assumes there should be at least a single pop. So given a catch body -// whose tag type is void or a catch_all's body, this returns false. -// - This returns true even if there are more pops after the first one within a -// catch body, which is invalid. That will be taken care of in validation. -bool containsValidDanglingPop(Expression* catchBody); - -// Given a 'Try' expression, fixes up 'pop's nested in blocks, which are -// currently not supported without block param types, by creating a new local, -// putting a (local.set $new (pop type)) right after 'catch', and putting a -// '(local.get $new)' where the 'pop' used to be. -void handleBlockNestedPop(Try* try_, Function* func, Module& wasm); - -// Calls handleBlockNestedPop for each 'Try's in a given function. -void handleBlockNestedPops(Function* func, Module& wasm); - -} // namespace EHUtils - -} // namespace wasm - -#endif // wasm_ir_eh_h diff -Nru binaryen-108/src/ir/element-utils.h binaryen-99/src/ir/element-utils.h --- binaryen-108/src/ir/element-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/element-utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_element_h -#define wasm_ir_element_h - -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm::ElementUtils { - -// iterate over functions referenced in an element segment -template -inline void iterElementSegmentFunctionNames(ElementSegment* segment, - T visitor) { - if (!segment->type.isFunction()) { - return; - } - - for (Index i = 0; i < segment->data.size(); i++) { - if (auto* get = segment->data[i]->dynCast()) { - visitor(get->func, i); - } - } -} - -// iterate over functions referenced in all element segments of a module -template -inline void iterAllElementFunctionNames(const Module* wasm, T visitor) { - for (auto& segment : wasm->elementSegments) { - iterElementSegmentFunctionNames( - segment.get(), [&](Name& name, Index i) { visitor(name); }); - } -} - -} // namespace wasm::ElementUtils - -#endif // wasm_ir_element_h diff -Nru binaryen-108/src/ir/export-utils.h binaryen-99/src/ir/export-utils.h --- binaryen-108/src/ir/export-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/export-utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_export_h -#define wasm_ir_export_h - -#include "wasm.h" - -namespace wasm::ExportUtils { - -inline std::vector getExportedFunctions(Module& wasm) { - std::vector ret; - for (auto& ex : wasm.exports) { - if (ex->kind == ExternalKind::Function) { - ret.push_back(wasm.getFunction(ex->value)); - } - } - return ret; -} - -} // namespace wasm::ExportUtils - -#endif // wasm_ir_export_h diff -Nru binaryen-108/src/ir/ExpressionAnalyzer.cpp binaryen-99/src/ir/ExpressionAnalyzer.cpp --- binaryen-108/src/ir/ExpressionAnalyzer.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/ExpressionAnalyzer.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -17,7 +17,6 @@ #include "ir/iteration.h" #include "ir/load-utils.h" #include "ir/utils.h" -#include "shared-constants.h" #include "support/hash.h" #include "support/small_vector.h" #include "wasm-traversal.h" @@ -60,7 +59,7 @@ } } // The value might be used, so it depends on if the function returns - return func->getResults() != Type::none; + return func->sig.results != Type::none; } // Checks if a value is dropped. @@ -169,68 +168,67 @@ WASM_UNUSED(castRight); // Handle each type of field, comparing it appropriately. -#define DELEGATE_FIELD_CHILD(id, field) \ - leftStack.push_back(castLeft->field); \ - rightStack.push_back(castRight->field); +#define DELEGATE_FIELD_CHILD(id, name) \ + leftStack.push_back(castLeft->name); \ + rightStack.push_back(castRight->name); -#define DELEGATE_FIELD_CHILD_VECTOR(id, field) \ - if (castLeft->field.size() != castRight->field.size()) { \ +#define DELEGATE_FIELD_CHILD_VECTOR(id, name) \ + if (castLeft->name.size() != castRight->name.size()) { \ return false; \ } \ - for (auto* child : castLeft->field) { \ + for (auto* child : castLeft->name) { \ leftStack.push_back(child); \ } \ - for (auto* child : castRight->field) { \ + for (auto* child : castRight->name) { \ rightStack.push_back(child); \ } -#define COMPARE_FIELD(field) \ - if (castLeft->field != castRight->field) { \ +#define COMPARE_FIELD(name) \ + if (castLeft->name != castRight->name) { \ return false; \ } -#define DELEGATE_FIELD_INT(id, field) COMPARE_FIELD(field) -#define DELEGATE_FIELD_LITERAL(id, field) COMPARE_FIELD(field) -#define DELEGATE_FIELD_NAME(id, field) COMPARE_FIELD(field) -#define DELEGATE_FIELD_TYPE(id, field) COMPARE_FIELD(field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) COMPARE_FIELD(field) -#define DELEGATE_FIELD_ADDRESS(id, field) COMPARE_FIELD(field) +#define DELEGATE_FIELD_INT(id, name) COMPARE_FIELD(name) +#define DELEGATE_FIELD_LITERAL(id, name) COMPARE_FIELD(name) +#define DELEGATE_FIELD_NAME(id, name) COMPARE_FIELD(name) +#define DELEGATE_FIELD_SIGNATURE(id, name) COMPARE_FIELD(name) +#define DELEGATE_FIELD_TYPE(id, name) COMPARE_FIELD(name) +#define DELEGATE_FIELD_ADDRESS(id, name) COMPARE_FIELD(name) -#define COMPARE_LIST(field) \ - if (castLeft->field.size() != castRight->field.size()) { \ +#define COMPARE_LIST(name) \ + if (castLeft->name.size() != castRight->name.size()) { \ return false; \ } \ - for (Index i = 0; i < castLeft->field.size(); i++) { \ - if (castLeft->field[i] != castRight->field[i]) { \ + for (Index i = 0; i < castLeft->name.size(); i++) { \ + if (castLeft->name[i] != castRight->name[i]) { \ return false; \ } \ } -#define DELEGATE_FIELD_INT_ARRAY(id, field) COMPARE_LIST(field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) COMPARE_LIST(field) +#define DELEGATE_FIELD_INT_ARRAY(id, name) COMPARE_LIST(name) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) \ - if (castLeft->field.is() != castRight->field.is()) { \ +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) \ + if (castLeft->name.is() != castRight->name.is()) { \ return false; \ } \ - rightNames[castLeft->field] = castRight->field; + rightNames[castLeft->name] = castRight->name; -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) \ - if (!compareNames(castLeft->field, castRight->field)) { \ +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) \ + if (!compareNames(castLeft->name, castRight->name)) { \ return false; \ } -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) \ - if (castLeft->field.size() != castRight->field.size()) { \ +#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) \ + if (castLeft->name.size() != castRight->name.size()) { \ return false; \ } \ - for (Index i = 0; i < castLeft->field.size(); i++) { \ - if (!compareNames(castLeft->field[i], castRight->field[i])) { \ + for (Index i = 0; i < castLeft->name.size(); i++) { \ + if (!compareNames(castLeft->name[i], castRight->name[i])) { \ return false; \ } \ } -#include "wasm-delegations-fields.def" +#include "wasm-delegations-fields.h" return true; } @@ -250,56 +248,44 @@ return Comparer().compare(left, right, comparer); } -namespace { - -struct Hasher { - bool visitChildren; - - size_t digest = wasm::hash(0); - - Index internalCounter = 0; - // for each internal name, its unique id - std::map internalNames; - ExpressionStack stack; - - Hasher(Expression* curr, - bool visitChildren, - ExpressionAnalyzer::ExprHasher custom) - : visitChildren(visitChildren) { - stack.push_back(curr); - // DELEGATE_CALLER_TARGET is a fake target used to denote delegating to - // the caller. Add it here to prevent the unknown name error. - noteScopeName(DELEGATE_CALLER_TARGET); - - while (stack.size() > 0) { - curr = stack.back(); - stack.pop_back(); - if (!curr) { - // This was an optional child that was not present. Hash a 0 to - // represent that. - rehash(digest, 0); - continue; - } - rehash(digest, curr->_id); - // we often don't need to hash the type, as it is tied to other values - // we are hashing anyhow, but there are exceptions: for example, a - // local.get's type is determined by the function, so if we are - // hashing only expression fragments, then two from different - // functions may turn out the same even if the type differs. Likewise, - // if we hash between modules, then we need to take int account - // call_imports type, etc. The simplest thing is just to hash the - // type for all of them. - rehash(digest, curr->type.getID()); - // If the custom hasher handled this expr, then we have nothing to do. - if (custom(curr, digest)) { - continue; +// hash an expression, ignoring superficial details like specific internal names +size_t ExpressionAnalyzer::hash(Expression* curr) { + struct Hasher { + size_t digest = wasm::hash(0); + + Index internalCounter = 0; + // for each internal name, its unique id + std::map internalNames; + ExpressionStack stack; + + Hasher(Expression* curr) { + stack.push_back(curr); + + while (stack.size() > 0) { + curr = stack.back(); + stack.pop_back(); + if (!curr) { + // This was an optional child that was not present. Hash a 0 to + // represent that. + rehash(digest, 0); + continue; + } + rehash(digest, curr->_id); + // we often don't need to hash the type, as it is tied to other values + // we are hashing anyhow, but there are exceptions: for example, a + // local.get's type is determined by the function, so if we are + // hashing only expression fragments, then two from different + // functions may turn out the same even if the type differs. Likewise, + // if we hash between modules, then we need to take int account + // call_imports type, etc. The simplest thing is just to hash the + // type for all of them. + rehash(digest, curr->type.getID()); + // Hash the contents of the expression. + hashExpression(curr); } - // Hash the contents of the expression normally. - hashExpression(curr); } - } - void hashExpression(Expression* curr) { + void hashExpression(Expression* curr) { #define DELEGATE_ID curr->_id @@ -309,76 +295,51 @@ WASM_UNUSED(cast); // Handle each type of field, comparing it appropriately. -#define DELEGATE_GET_FIELD(id, field) cast->field +#define DELEGATE_GET_FIELD(id, name) cast->name -#define DELEGATE_FIELD_CHILD(id, field) \ - if (visitChildren) { \ - stack.push_back(cast->field); \ - } +#define DELEGATE_FIELD_CHILD(id, name) stack.push_back(cast->name); -#define HASH_FIELD(field) rehash(digest, cast->field); +#define HASH_FIELD(name) rehash(digest, cast->name); -#define DELEGATE_FIELD_INT(id, field) HASH_FIELD(field) -#define DELEGATE_FIELD_LITERAL(id, field) HASH_FIELD(field) +#define DELEGATE_FIELD_INT(id, name) HASH_FIELD(name) +#define DELEGATE_FIELD_LITERAL(id, name) HASH_FIELD(name) +#define DELEGATE_FIELD_SIGNATURE(id, name) HASH_FIELD(name) -#define DELEGATE_FIELD_NAME(id, field) visitNonScopeName(cast->field) -#define DELEGATE_FIELD_TYPE(id, field) visitType(cast->field); -#define DELEGATE_FIELD_HEAPTYPE(id, field) visitHeapType(cast->field); -#define DELEGATE_FIELD_ADDRESS(id, field) visitAddress(cast->field); +#define DELEGATE_FIELD_NAME(id, name) visitNonScopeName(cast->name) +#define DELEGATE_FIELD_TYPE(id, name) visitType(cast->name); +#define DELEGATE_FIELD_ADDRESS(id, name) visitAddress(cast->name); // Note that we only note the scope name, but do not also visit it. That means // that (block $x) and (block) get the same hash. In other words, we only change // the hash based on uses of scope names, that is when there is a noticeable // difference in break targets. -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) noteScopeName(cast->field); +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) noteScopeName(cast->name); -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) visitScopeName(cast->field); +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) visitScopeName(cast->name); -#include "wasm-delegations-fields.def" - } - - void noteScopeName(Name curr) { - if (curr.is()) { - internalNames[curr] = internalCounter++; +#include "wasm-delegations-fields.h" } - } - void visitScopeName(Name curr) { - // We consider 3 cases here, and prefix a hash value of 0, 1, or 2 to - // maximally differentiate them. - - // Try's delegate target can be null. - if (!curr.is()) { - rehash(digest, 0); - return; + + void noteScopeName(Name curr) { + if (curr.is()) { + internalNames[curr] = internalCounter++; + } } - // Names are relative, we give the same hash for - // (block $x (br $x)) - // (block $y (br $y)) - // But if the name is not known to us, hash the absolute one. - if (!internalNames.count(curr)) { - rehash(digest, 1); - // Perform the same hashing as a generic name. - visitNonScopeName(curr); - return; + void visitScopeName(Name curr) { + // Names are relative, we give the same hash for + // (block $x (br $x)) + // (block $y (br $y)) + static_assert(sizeof(Index) == sizeof(int32_t), + "wasm64 will need changes here"); + assert(internalNames.find(curr) != internalNames.end()); + rehash(digest, internalNames[curr]); } - rehash(digest, 2); - rehash(digest, internalNames[curr]); - } - void visitNonScopeName(Name curr) { rehash(digest, uint64_t(curr.str)); } - void visitType(Type curr) { rehash(digest, curr.getID()); } - void visitHeapType(HeapType curr) { rehash(digest, curr.getID()); } - void visitAddress(Address curr) { rehash(digest, curr.addr); } -}; - -} // anonymous namespace - -size_t ExpressionAnalyzer::flexibleHash(Expression* curr, - ExpressionAnalyzer::ExprHasher custom) { - return Hasher(curr, true, custom).digest; -} + void visitNonScopeName(Name curr) { rehash(digest, uint64_t(curr.str)); } + void visitType(Type curr) { rehash(digest, curr.getID()); } + void visitAddress(Address curr) { rehash(digest, curr.addr); } + }; -size_t ExpressionAnalyzer::shallowHash(Expression* curr) { - return Hasher(curr, false, ExpressionAnalyzer::nothingHasher).digest; + return Hasher(curr).digest; } } // namespace wasm diff -Nru binaryen-108/src/ir/ExpressionManipulator.cpp binaryen-99/src/ir/ExpressionManipulator.cpp --- binaryen-108/src/ir/ExpressionManipulator.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/ExpressionManipulator.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -17,7 +17,9 @@ #include "ir/load-utils.h" #include "ir/utils.h" -namespace wasm::ExpressionManipulator { +namespace wasm { + +namespace ExpressionManipulator { Expression* flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) { @@ -61,45 +63,44 @@ WASM_UNUSED(castCopy); // Handle each type of field, copying it appropriately. -#define DELEGATE_FIELD_CHILD(id, field) \ - tasks.push_back({castOriginal->field, &castCopy->field}); +#define DELEGATE_FIELD_CHILD(id, name) \ + tasks.push_back({castOriginal->name, &castCopy->name}); -#define DELEGATE_FIELD_CHILD_VECTOR(id, field) \ - castCopy->field.resize(castOriginal->field.size()); \ - for (Index i = 0; i < castOriginal->field.size(); i++) { \ - tasks.push_back({castOriginal->field[i], &castCopy->field[i]}); \ +#define DELEGATE_FIELD_CHILD_VECTOR(id, name) \ + castCopy->name.resize(castOriginal->name.size()); \ + for (Index i = 0; i < castOriginal->name.size(); i++) { \ + tasks.push_back({castOriginal->name[i], &castCopy->name[i]}); \ } -#define COPY_FIELD(field) castCopy->field = castOriginal->field; +#define COPY_FIELD(name) castCopy->name = castOriginal->name; -#define DELEGATE_FIELD_INT(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_LITERAL(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_NAME(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_TYPE(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) COPY_FIELD(field) -#define DELEGATE_FIELD_ADDRESS(id, field) COPY_FIELD(field) - -#define COPY_FIELD_LIST(field) \ - for (Index i = 0; i < castOriginal->field.size(); i++) { \ - castCopy->field[i] = castOriginal->field[i]; \ +#define DELEGATE_FIELD_INT(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_LITERAL(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_NAME(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_SIGNATURE(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_TYPE(id, name) COPY_FIELD(name) +#define DELEGATE_FIELD_ADDRESS(id, name) COPY_FIELD(name) + +#define COPY_FIELD_LIST(name) \ + for (Index i = 0; i < castOriginal->name.size(); i++) { \ + castCopy->name[i] = castOriginal->name[i]; \ } -#define COPY_VECTOR(field) \ - castCopy->field.resize(castOriginal->field.size()); \ - COPY_FIELD_LIST(field) +#define COPY_VECTOR(name) \ + castCopy->name.resize(castOriginal->name.size()); \ + COPY_FIELD_LIST(name) -#define COPY_ARRAY(field) \ - assert(castCopy->field.size() == castOriginal->field.size()); \ - COPY_FIELD_LIST(field) +#define COPY_ARRAY(name) \ + assert(castCopy->name.size() == castOriginal->name.size()); \ + COPY_FIELD_LIST(name) -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) COPY_VECTOR(field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) COPY_VECTOR(field) +#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) COPY_VECTOR(name) -#define DELEGATE_FIELD_INT_ARRAY(id, field) COPY_ARRAY(field) +#define DELEGATE_FIELD_INT_ARRAY(id, name) COPY_ARRAY(name) -#include "wasm-delegations-fields.def" +#include "wasm-delegations-fields.h" // The type can be simply copied. copy->type = original->type; @@ -112,8 +113,20 @@ // Splice an item into the middle of a block's list void spliceIntoBlock(Block* block, Index index, Expression* add) { - block->list.insertAt(index, add); + auto& list = block->list; + if (index == list.size()) { + list.push_back(add); // simple append + } else { + // we need to make room + list.push_back(nullptr); + for (Index i = list.size() - 1; i > index; i--) { + list[i] = list[i - 1]; + } + list[index] = add; + } block->finalize(block->type); } -} // namespace wasm::ExpressionManipulator +} // namespace ExpressionManipulator + +} // namespace wasm diff -Nru binaryen-108/src/ir/features.h binaryen-99/src/ir/features.h --- binaryen-108/src/ir/features.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/features.h 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,9 @@ #include #include -namespace wasm::Features { +namespace wasm { + +namespace Features { inline FeatureSet get(UnaryOp op) { FeatureSet ret; @@ -46,10 +48,13 @@ case SplatVecF64x2: case NotVec128: case NegVecI8x16: + case AnyTrueVecI8x16: case AllTrueVecI8x16: case NegVecI16x8: + case AnyTrueVecI16x8: case AllTrueVecI16x8: case NegVecI32x4: + case AnyTrueVecI32x4: case AllTrueVecI32x4: case NegVecI64x2: case AbsVecF32x4: @@ -60,8 +65,12 @@ case SqrtVecF64x2: case TruncSatSVecF32x4ToVecI32x4: case TruncSatUVecF32x4ToVecI32x4: + case TruncSatSVecF64x2ToVecI64x2: + case TruncSatUVecF64x2ToVecI64x2: case ConvertSVecI32x4ToVecF32x4: - case ConvertUVecI32x4ToVecF32x4: { + case ConvertUVecI32x4ToVecF32x4: + case ConvertSVecI64x2ToVecF64x2: + case ConvertUVecI64x2ToVecF64x2: { ret.setSIMD(); break; } @@ -132,6 +141,7 @@ case SubVecI8x16: case SubSatSVecI8x16: case SubSatUVecI8x16: + case MulVecI8x16: case AddVecI16x8: case AddSatSVecI16x8: case AddSatUVecI16x8: @@ -164,6 +174,8 @@ return ret; } -} // namespace wasm::Features +} // namespace Features + +} // namespace wasm #endif // wasm_ir_features_h diff -Nru binaryen-108/src/ir/find_all.h binaryen-99/src/ir/find_all.h --- binaryen-108/src/ir/find_all.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/find_all.h 2021-01-07 20:01:06.000000000 +0000 @@ -40,8 +40,6 @@ finder.list = &list; finder.walk(ast); } - - bool has() { return !list.empty(); } }; // Find all pointers to instances of a certain node type diff -Nru binaryen-108/src/ir/flat.h binaryen-99/src/ir/flat.h --- binaryen-108/src/ir/flat.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/flat.h 2021-01-07 20:01:06.000000000 +0000 @@ -43,8 +43,8 @@ // making the AST have these properties: // // 1. Aside from a local.set, the operands of an instruction must be a -// local.get, a const, an unreachable, or a ref.as_non_null. Anything else -// is written to a local earlier. +// local.get, a const, or an unreachable. Anything else is written +// to a local earlier. // 2. Disallow control flow (block, loop, if, and try) return values, and do // not allow the function body to have a concrete type, i.e., do not use // control flow to pass around values. @@ -54,10 +54,6 @@ // values is prohibited already, but e.g. a block ending in unreachable, // which can normally be nested, is also disallowed). // -// Note: ref.as_non_null must be allowed in a nested position because we cannot -// spill it to a local - the result is non-null, which is not allowable in a -// local. -// #ifndef wasm_ir_flat_h #define wasm_ir_flat_h @@ -67,7 +63,9 @@ #include "pass.h" #include "wasm-traversal.h" -namespace wasm::Flat { +namespace wasm { + +namespace Flat { inline void verifyFlatness(Function* func) { struct VerifyFlatness @@ -84,11 +82,8 @@ "set values cannot be control flow"); } else { for (auto* child : ChildIterator(curr)) { - bool isRefAsNonNull = - child->is() && child->cast()->op == RefAsNonNull; verify(Properties::isConstantExpression(child) || - child->is() || child->is() || - isRefAsNonNull, + child->is() || child->is(), "instructions must only have constant expressions, local.get, " "or unreachable as children"); } @@ -125,6 +120,8 @@ VerifyFlatness().run(&runner, module); } -} // namespace wasm::Flat +} // namespace Flat + +} // namespace wasm #endif // wasm_ir_flat_h diff -Nru binaryen-108/src/ir/function-utils.h binaryen-99/src/ir/function-utils.h --- binaryen-108/src/ir/function-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/function-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,19 +20,21 @@ #include "ir/utils.h" #include "wasm.h" -namespace wasm::FunctionUtils { +namespace wasm { + +namespace FunctionUtils { // Checks if two functions are equal in all functional aspects, // everything but their name (which can't be the same, in the same // module!) - same params, vars, body, result, etc. inline bool equal(Function* left, Function* right) { - if (left->type != right->type) { + if (left->sig != right->sig) { return false; } if (left->getNumVars() != right->getNumVars()) { return false; } - for (Index i = left->getParams().size(); i < left->getNumLocals(); i++) { + for (Index i = left->sig.params.size(); i < left->getNumLocals(); i++) { if (left->getLocalType(i) != right->getLocalType(i)) { return false; } @@ -43,6 +45,8 @@ return left->imported() && right->imported(); } -} // namespace wasm::FunctionUtils +} // namespace FunctionUtils + +} // namespace wasm #endif // wasm_ir_function_h diff -Nru binaryen-108/src/ir/gc-type-utils.h binaryen-99/src/ir/gc-type-utils.h --- binaryen-108/src/ir/gc-type-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/gc-type-utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_gc_type_utils_h -#define wasm_ir_gc_type_utils_h - -#include "wasm.h" - -namespace wasm::GCTypeUtils { - -// Helper code to evaluate a reference at compile time and check if it is of a -// certain kind. Various wasm instructions check if something is a function or -// data etc., and that code is shared here. - -enum Kind { Func, Data, I31, Other }; - -enum EvaluationResult { - // The result is not known at compile time. - Unknown, - // The evaluation is known to succeed (i.e., we find what we are looking - // for), or fail, at compile time. - Success, - Failure -}; - -// Given an instruction that checks if the child reference is of a certain kind -// (like br_on_func checks if it is a function), see if type info lets us -// determine that at compile time. -// This ignores nullability - it just checks the kind. -inline EvaluationResult evaluateKindCheck(Expression* curr) { - Kind expected; - Expression* child; - - // Some operations flip the condition. - bool flip = false; - - if (auto* br = curr->dynCast()) { - switch (br->op) { - // We don't check nullability here. - case BrOnNull: - case BrOnNonNull: - case BrOnCastFail: - flip = true; - [[fallthrough]]; - case BrOnCast: - if (!br->rtt) { - // This is a static cast check, which we may be able to resolve at - // compile time. Note that the type must be non-nullable for us to - // succeed at that inference, as otherwise a null can make us fail. - if (Type::isSubType(br->ref->type, - Type(br->intendedType, NonNullable))) { - return flip ? Failure : Success; - } - } - return Unknown; - case BrOnNonFunc: - flip = true; - [[fallthrough]]; - case BrOnFunc: - expected = Func; - break; - case BrOnNonData: - flip = true; - [[fallthrough]]; - case BrOnData: - expected = Data; - break; - case BrOnNonI31: - flip = true; - [[fallthrough]]; - case BrOnI31: - expected = I31; - break; - default: - WASM_UNREACHABLE("unhandled BrOn"); - } - child = br->ref; - } else if (auto* is = curr->dynCast()) { - switch (is->op) { - // We don't check nullability here. - case RefIsNull: - return Unknown; - case RefIsFunc: - expected = Func; - break; - case RefIsData: - expected = Data; - break; - case RefIsI31: - expected = I31; - break; - default: - WASM_UNREACHABLE("unhandled BrOn"); - } - child = is->value; - } else if (auto* as = curr->dynCast()) { - switch (as->op) { - // We don't check nullability here. - case RefAsNonNull: - return Unknown; - case RefAsFunc: - expected = Func; - break; - case RefAsData: - expected = Data; - break; - case RefAsI31: - expected = I31; - break; - default: - WASM_UNREACHABLE("unhandled BrOn"); - } - child = as->value; - } else { - WASM_UNREACHABLE("invalid input to evaluateKindCheck"); - } - - auto childType = child->type; - - Kind actual; - - if (childType.isFunction()) { - actual = Func; - } else if (childType.isData()) { - actual = Data; - } else if (childType.getHeapType() == HeapType::i31) { - actual = I31; - } else { - return Unknown; - } - - auto success = actual == expected; - if (flip) { - success = !success; - } - return success ? Success : Failure; -} - -} // namespace wasm::GCTypeUtils - -#endif // wasm_ir_gc_type_utils_h diff -Nru binaryen-108/src/ir/global-utils.h binaryen-99/src/ir/global-utils.h --- binaryen-108/src/ir/global-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/global-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,13 +20,13 @@ #include #include -#include "ir/iteration.h" #include "ir/module-utils.h" #include "literal.h" #include "wasm.h" -namespace wasm::GlobalUtils { +namespace wasm { +namespace GlobalUtils { // find a global initialized to the value of an import, or null if no such // global inline Global* @@ -53,26 +53,21 @@ return ret; } -inline bool canInitializeGlobal(Expression* curr, FeatureSet features) { +inline bool canInitializeGlobal(const Expression* curr) { if (auto* tuple = curr->dynCast()) { for (auto* op : tuple->operands) { - if (!canInitializeGlobal(op, features)) { + if (!canInitializeGlobal(op)) { return false; } } return true; } - if (Properties::isValidInConstantExpression(curr, features)) { - for (auto* child : ChildIterator(curr)) { - if (!canInitializeGlobal(child, features)) { - return false; - } - } - return true; - } - return false; + return Properties::isSingleConstantExpression(curr) || + curr->is() || curr->is() || curr->is(); } -} // namespace wasm::GlobalUtils +} // namespace GlobalUtils + +} // namespace wasm #endif // wasm_ir_global_h diff -Nru binaryen-108/src/ir/hashed.h binaryen-99/src/ir/hashed.h --- binaryen-108/src/ir/hashed.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/hashed.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,10 +20,26 @@ #include "ir/utils.h" #include "support/hash.h" #include "wasm.h" -#include namespace wasm { +// An expression with a cached hash value +struct HashedExpression { + Expression* expr; + size_t digest; + + HashedExpression(Expression* expr) : expr(expr) { + if (expr) { + digest = ExpressionAnalyzer::hash(expr); + } else { + digest = hash(0); + } + } + + HashedExpression(const HashedExpression& other) + : expr(other.expr), digest(other.digest) {} +}; + // A pass that hashes all functions struct FunctionHasher : public WalkerPass> { @@ -31,14 +47,9 @@ struct Map : public std::map {}; - FunctionHasher(Map* output, ExpressionAnalyzer::ExprHasher customHasher) - : output(output), customHasher(customHasher) {} - FunctionHasher(Map* output) - : output(output), customHasher(ExpressionAnalyzer::nothingHasher) {} + FunctionHasher(Map* output) : output(output) {} - FunctionHasher* create() override { - return new FunctionHasher(output, customHasher); - } + FunctionHasher* create() override { return new FunctionHasher(output); } static Map createMap(Module* module) { Map hashes; @@ -50,29 +61,20 @@ return hashes; } - void doWalkFunction(Function* func) { - output->at(func) = flexibleHashFunction(func, customHasher); - } + void doWalkFunction(Function* func) { output->at(func) = hashFunction(func); } - static size_t - flexibleHashFunction(Function* func, - ExpressionAnalyzer::ExprHasher customHasher) { - auto digest = hash(func->type); + static size_t hashFunction(Function* func) { + auto digest = hash(func->sig.params.getID()); + rehash(digest, func->sig.results.getID()); for (auto type : func->vars) { rehash(digest, type.getID()); } - hash_combine(digest, - ExpressionAnalyzer::flexibleHash(func->body, customHasher)); + hash_combine(digest, ExpressionAnalyzer::hash(func->body)); return digest; } - static size_t hashFunction(Function* func) { - return flexibleHashFunction(func, ExpressionAnalyzer::nothingHasher); - } - private: Map* output; - ExpressionAnalyzer::ExprHasher customHasher; }; } // namespace wasm diff -Nru binaryen-108/src/ir/import-utils.h binaryen-99/src/ir/import-utils.h --- binaryen-108/src/ir/import-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/import-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -29,8 +29,7 @@ std::vector importedGlobals; std::vector importedFunctions; - std::vector importedTables; - std::vector importedTags; + std::vector importedEvents; ImportInfo(Module& wasm) : wasm(wasm) { for (auto& import : wasm.globals) { @@ -43,14 +42,9 @@ importedFunctions.push_back(import.get()); } } - for (auto& import : wasm.tables) { + for (auto& import : wasm.events) { if (import->imported()) { - importedTables.push_back(import.get()); - } - } - for (auto& import : wasm.tags) { - if (import->imported()) { - importedTags.push_back(import.get()); + importedEvents.push_back(import.get()); } } } @@ -73,8 +67,8 @@ return nullptr; } - Tag* getImportedTag(Name module, Name base) { - for (auto* import : importedTags) { + Event* getImportedEvent(Name module, Name base) { + for (auto* import : importedEvents) { if (import->module == module && import->base == base) { return import; } @@ -86,14 +80,12 @@ Index getNumImportedFunctions() { return importedFunctions.size(); } - Index getNumImportedTables() { return importedTables.size(); } - - Index getNumImportedTags() { return importedTags.size(); } + Index getNumImportedEvents() { return importedEvents.size(); } Index getNumImports() { return getNumImportedGlobals() + getNumImportedFunctions() + - getNumImportedTags() + (wasm.memory.imported() ? 1 : 0) + - getNumImportedTables(); + getNumImportedEvents() + (wasm.memory.imported() ? 1 : 0) + + (wasm.table.imported() ? 1 : 0); } Index getNumDefinedGlobals() { @@ -104,11 +96,9 @@ return wasm.functions.size() - getNumImportedFunctions(); } - Index getNumDefinedTables() { - return wasm.tables.size() - getNumImportedTables(); + Index getNumDefinedEvents() { + return wasm.events.size() - getNumImportedEvents(); } - - Index getNumDefinedTags() { return wasm.tags.size() - getNumImportedTags(); } }; } // namespace wasm diff -Nru binaryen-108/src/ir/intrinsics.cpp binaryen-99/src/ir/intrinsics.cpp --- binaryen-108/src/ir/intrinsics.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/intrinsics.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/intrinsics.h" -#include "wasm-builder.h" - -namespace wasm { - -static Name BinaryenIntrinsics("binaryen-intrinsics"), - CallWithoutEffects("call.without.effects"); - -bool Intrinsics::isCallWithoutEffects(Function* func) { - return func->module == BinaryenIntrinsics && func->base == CallWithoutEffects; -} - -Call* Intrinsics::isCallWithoutEffects(Expression* curr) { - if (auto* call = curr->dynCast()) { - // The target function may not exist if the module is still being - // constructed. - if (auto* func = module.getFunctionOrNull(call->target)) { - if (isCallWithoutEffects(func)) { - return call; - } - } - } - return nullptr; -} - -} // namespace wasm diff -Nru binaryen-108/src/ir/intrinsics.h binaryen-99/src/ir/intrinsics.h --- binaryen-108/src/ir/intrinsics.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/intrinsics.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_intrinsics_h -#define wasm_ir_intrinsics_h - -#include "pass.h" -#include "wasm-traversal.h" - -// -// See the README.md for background on intrinsic functions. -// -// Intrinsics can be recognized by Intrinsics::isFoo() methods, that check if a -// function is a particular intrinsic, or if a call to a function is so. The -// latter returns nullptr if the input is not that intrinsic, and otherwise the -// intrinsic itself cast to a Call*. -// - -namespace wasm { - -class Intrinsics { - Module& module; - -public: - Intrinsics(Module& module) : module(module) {} - - // - // Check if an instruction is the call.without.effects intrinsic. - // - // (import "binaryen-intrinsics" "call.without.effects" - // (func (..params..) (param $target funcref) (..results..))) - // - // call.without.effects can take any parameters, and in addition a funcref, - // and return any result. - // - // Precise semantics: - // - // * The optimizer will assume this instruction has no side effects. - // * Final lowering turns a call.without.effects into a call of the given - // function with the given parameters. (This will either be a direct call, - // or a call_ref; note that either way, the function reference that appears - // here must have the proper type - if not, you will get an error.) - // - // call.without.effects is useful to be able to get rid of an unused result - // that has side effects. For example, - // - // (drop (call $get-something)) - // - // cannot be removed, as a call has side effects. But if a code generator - // knows that it is fine to not make the call given that the result is - // dropped (perhaps the side effects are to initialize a global cache, for - // example) then instead of emitting - // - // (call $get-something) - // - // it can emit - // - // (call $call.without.effects (ref.func $get-something)) - // - // which will have this behavior in the optimizer if it is dropped: - // - // (drop (call $call.without.effects (ref.func $get-something))) - // => - // (drop (ref.func $get-something)) - // - // Later optimizations can remove the dropped ref.func. Or, if the result is - // actually used, - // - // (local.set $x (call $call.without.effects (ref.func $get-something))) - // => - // (local.set $x (call $get-something)) - // - // Later passes will then turn that into a direct call and further optimize - // things. - // - bool isCallWithoutEffects(Function* func); - Call* isCallWithoutEffects(Expression* curr); -}; - -} // namespace wasm - -#endif // wasm_ir_intrinsics_h diff -Nru binaryen-108/src/ir/iteration.h binaryen-99/src/ir/iteration.h --- binaryen-108/src/ir/iteration.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/iteration.h 2021-01-07 20:01:06.000000000 +0000 @@ -18,6 +18,7 @@ #define wasm_ir_iteration_h #include "ir/properties.h" +#include "wasm-traversal.h" #include "wasm.h" namespace wasm { @@ -40,9 +41,8 @@ // this instruction. For example, includes If::condition // but not If::ifTrue. // -template class AbstractChildIterator { - using Self = AbstractChildIterator; - +template class Scanner> class AbstractChildIterator { + using Self = AbstractChildIterator; struct Iterator { const Self& parent; Index index; @@ -53,103 +53,61 @@ return index != other.index || &parent != &(other.parent); } - bool operator==(const Iterator& other) const { return !(*this != other); } - void operator++() { index++; } - Expression*& operator*() { - return *parent.children[parent.mapIndex(index)]; - } + Expression* operator*() { return parent.children[index]; } }; - friend struct Iterator; - - Index mapIndex(Index index) const { - assert(index < children.size()); - - // The vector of children is in reverse order, as that is how - // wasm-delegations-fields works. To get the order of execution, reverse - // things. - return children.size() - 1 - index; - } - public: - // The vector of children in the order emitted by wasm-delegations-fields - // (which is in reverse execution order). - SmallVector children; + SmallVector children; AbstractChildIterator(Expression* parent) { - auto* self = (Specific*)this; - -#define DELEGATE_ID parent->_id - -#define DELEGATE_START(id) \ - auto* cast = parent->cast(); \ - WASM_UNUSED(cast); - -#define DELEGATE_GET_FIELD(id, field) cast->field - -#define DELEGATE_FIELD_CHILD(id, field) self->addChild(parent, &cast->field); - -#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field) \ - if (cast->field) { \ - self->addChild(parent, &cast->field); \ - } - -#define DELEGATE_FIELD_INT(id, field) -#define DELEGATE_FIELD_INT_ARRAY(id, field) -#define DELEGATE_FIELD_LITERAL(id, field) -#define DELEGATE_FIELD_NAME(id, field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) -#define DELEGATE_FIELD_TYPE(id, field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) -#define DELEGATE_FIELD_ADDRESS(id, field) - -#include "wasm-delegations-fields.def" + struct Traverser : public PostWalker { + Expression* parent; + SmallVector* children; + + // We need to scan subchildren exactly once - just the parent. + bool scanned = false; + + static void scan(Traverser* self, Expression** currp) { + if (!self->scanned) { + self->scanned = true; + Scanner>::scan(self, + currp); + } else { + // This is one of the children. Do not scan further, just note it. + self->children->push_back(*currp); + } + } + } traverser; + traverser.parent = parent; + traverser.children = &children; + traverser.walk(parent); } Iterator begin() const { return Iterator(*this, 0); } Iterator end() const { return Iterator(*this, children.size()); } - - void addChild(Expression* parent, Expression** child) { - children.push_back(child); - } - - // API for accessing children in random order. - Expression*& getChild(Index index) { return *children[mapIndex(index)]; } - - Index getNumChildren() { return children.size(); } }; -class ChildIterator : public AbstractChildIterator { -public: - ChildIterator(Expression* parent) - : AbstractChildIterator(parent) {} -}; - -class ValueChildIterator : public AbstractChildIterator { -public: - ValueChildIterator(Expression* parent) - : AbstractChildIterator(parent) {} - - void addChild(Expression* parent, Expression** child) { - if (Properties::isControlFlowStructure(parent)) { +template +struct ValueChildScanner : PostWalker { + static void scan(SubType* self, Expression** currp) { + auto* curr = *currp; + if (Properties::isControlFlowStructure(curr)) { // If conditions are the only value children of control flow structures - if (auto* iff = parent->dynCast()) { - if (child == &iff->condition) { - children.push_back(child); - } + if (auto* iff = curr->dynCast()) { + self->pushTask(SubType::scan, &iff->condition); } } else { // All children on non-control flow expressions are value children - children.push_back(child); + PostWalker::scan(self, currp); } } }; +using ChildIterator = AbstractChildIterator; +using ValueChildIterator = AbstractChildIterator; + // Returns true if the current expression contains a certain kind of expression, // within the given depth of BFS. If depth is -1, this searches all children. template bool containsChild(Expression* parent, int depth = -1) { diff -Nru binaryen-108/src/ir/label-utils.h binaryen-99/src/ir/label-utils.h --- binaryen-108/src/ir/label-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/label-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,7 +20,9 @@ #include "wasm-traversal.h" #include "wasm.h" -namespace wasm::LabelUtils { +namespace wasm { + +namespace LabelUtils { // Handles branch/loop labels in a function; makes it easy to add new // ones without duplicates @@ -31,7 +33,8 @@ Name getUnique(std::string prefix) { while (1) { auto curr = Name(prefix + std::to_string(counter++)); - if (labels.emplace(curr).second) { + if (labels.find(curr) == labels.end()) { + labels.insert(curr); return curr; } } @@ -45,6 +48,8 @@ size_t counter = 0; }; -} // namespace wasm::LabelUtils +} // namespace LabelUtils + +} // namespace wasm #endif // wasm_ir_label_h diff -Nru binaryen-108/src/ir/linear-execution.h binaryen-99/src/ir/linear-execution.h --- binaryen-108/src/ir/linear-execution.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/linear-execution.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_linear_execution_h -#define wasm_ir_linear_execution_h - -#include -#include -#include - -namespace wasm { - -// Traversal in the order of execution. This is quick and simple, but -// does not provide the same comprehensive information that a full -// conversion to basic blocks would. What it does give is a quick -// way to view straightline execution traces, i.e., that have no -// branching. This can let optimizations get most of what they -// want without the cost of creating another AST. -// -// When execution is no longer linear, this notifies via a call -// to noteNonLinear(). - -template> -struct LinearExecutionWalker : public PostWalker { - LinearExecutionWalker() = default; - - // subclasses should implement this - void noteNonLinear(Expression* curr) { abort(); } - - static void doNoteNonLinear(SubType* self, Expression** currp) { - self->noteNonLinear(*currp); - } - - static void scan(SubType* self, Expression** currp) { - Expression* curr = *currp; - - switch (curr->_id) { - case Expression::Id::InvalidId: - abort(); - case Expression::Id::BlockId: { - self->pushTask(SubType::doVisitBlock, currp); - if (curr->cast()->name.is()) { - self->pushTask(SubType::doNoteNonLinear, currp); - } - auto& list = curr->cast()->list; - for (int i = int(list.size()) - 1; i >= 0; i--) { - self->pushTask(SubType::scan, &list[i]); - } - break; - } - case Expression::Id::IfId: { - self->pushTask(SubType::doVisitIf, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - self->maybePushTask(SubType::scan, &curr->cast()->ifFalse); - self->pushTask(SubType::doNoteNonLinear, currp); - self->pushTask(SubType::scan, &curr->cast()->ifTrue); - self->pushTask(SubType::doNoteNonLinear, currp); - self->pushTask(SubType::scan, &curr->cast()->condition); - break; - } - case Expression::Id::LoopId: { - self->pushTask(SubType::doVisitLoop, currp); - self->pushTask(SubType::scan, &curr->cast()->body); - self->pushTask(SubType::doNoteNonLinear, currp); - break; - } - case Expression::Id::BreakId: { - self->pushTask(SubType::doVisitBreak, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - self->maybePushTask(SubType::scan, &curr->cast()->condition); - self->maybePushTask(SubType::scan, &curr->cast()->value); - break; - } - case Expression::Id::SwitchId: { - self->pushTask(SubType::doVisitSwitch, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - self->pushTask(SubType::scan, &curr->cast()->condition); - self->maybePushTask(SubType::scan, &curr->cast()->value); - break; - } - case Expression::Id::ReturnId: { - self->pushTask(SubType::doVisitReturn, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - self->maybePushTask(SubType::scan, &curr->cast()->value); - break; - } - case Expression::Id::TryId: { - self->pushTask(SubType::doVisitTry, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - auto& list = curr->cast()->catchBodies; - for (int i = int(list.size()) - 1; i >= 0; i--) { - self->pushTask(SubType::scan, &list[i]); - self->pushTask(SubType::doNoteNonLinear, currp); - } - self->pushTask(SubType::scan, &curr->cast()->body); - break; - } - case Expression::Id::ThrowId: { - self->pushTask(SubType::doVisitThrow, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - auto& list = curr->cast()->operands; - for (int i = int(list.size()) - 1; i >= 0; i--) { - self->pushTask(SubType::scan, &list[i]); - } - break; - } - case Expression::Id::RethrowId: { - self->pushTask(SubType::doVisitRethrow, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - break; - } - case Expression::Id::UnreachableId: { - self->pushTask(SubType::doVisitUnreachable, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - break; - } - case Expression::Id::BrOnId: { - self->pushTask(SubType::doVisitBrOn, currp); - self->pushTask(SubType::doNoteNonLinear, currp); - self->maybePushTask(SubType::scan, &curr->cast()->rtt); - self->pushTask(SubType::scan, &curr->cast()->ref); - break; - } - default: { - // All relevant things should have been handled. - assert(!Properties::isControlFlowStructure(curr)); - assert(!Properties::isBranch(curr)); - // other node types do not have control flow, use regular post-order - PostWalker::scan(self, currp); - } - } - } -}; - -} // namespace wasm - -#endif // wasm_ir_linear_execution_h diff -Nru binaryen-108/src/ir/literal-utils.h binaryen-99/src/ir/literal-utils.h --- binaryen-108/src/ir/literal-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/literal-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,7 +20,9 @@ #include "wasm-builder.h" #include "wasm.h" -namespace wasm::LiteralUtils { +namespace wasm { + +namespace LiteralUtils { inline Expression* makeFromInt32(int32_t x, Type type, Module& wasm) { auto* ret = wasm.allocator.alloc(); @@ -29,30 +31,7 @@ return ret; } -inline bool canMakeZero(Type type) { - if (type.isNonNullable()) { - return false; - } - if (type.isRtt() && type.getRtt().hasDepth()) { - // An rtt with depth cannot be constructed as a simple zero: we'd need to - // create not just a zero (an rtt.canon) but also some rtt.subs that add to - // the depth, so disallow that. Also, there is no practical way to create a - // zero Literal for such a type, as we'd need to supply the list of super - // types somehow, and creating a zero Literal is how makeZero works. - return false; - } - if (type.isTuple()) { - for (auto t : type) { - if (!canMakeZero(t)) { - return false; - } - } - } - return true; -} - inline Expression* makeZero(Type type, Module& wasm) { - assert(canMakeZero(type)); // TODO: Remove this function once V8 supports v128.const // (https://bugs.chromium.org/p/v8/issues/detail?id=8460) Builder builder(wasm); @@ -62,6 +41,8 @@ return builder.makeConstantExpression(Literal::makeZeros(type)); } -} // namespace wasm::LiteralUtils +} // namespace LiteralUtils + +} // namespace wasm #endif // wasm_ir_literal_utils_h diff -Nru binaryen-108/src/ir/load-utils.h binaryen-99/src/ir/load-utils.h --- binaryen-108/src/ir/load-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/load-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -19,7 +19,9 @@ #include "wasm.h" -namespace wasm::LoadUtils { +namespace wasm { + +namespace LoadUtils { // checks if the sign of a load matters, which is when an integer // load is of fewer bytes than the size of the type (so we must @@ -35,6 +37,8 @@ // check if a load can be signed (which some opts want to do) inline bool canBeSigned(Load* load) { return !load->isAtomic; } -} // namespace wasm::LoadUtils +} // namespace LoadUtils + +} // namespace wasm #endif // wasm_ir_load_h diff -Nru binaryen-108/src/ir/LocalGraph.cpp binaryen-99/src/ir/LocalGraph.cpp --- binaryen-108/src/ir/LocalGraph.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/LocalGraph.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -135,7 +135,7 @@ // Convert unordered_map to vector. flowBlock.lastSets.reserve(block->contents.lastSets.size()); for (auto set : block->contents.lastSets) { - flowBlock.lastSets.emplace_back(set); + flowBlock.lastSets.emplace_back(std::make_pair(set.first, set.second)); } } assert(entryFlowBlock != nullptr); @@ -227,12 +227,14 @@ // LocalGraph implementation -LocalGraph::LocalGraph(Function* func) : func(func) { +LocalGraph::LocalGraph(Function* func) { LocalGraphInternal::Flower flower(getSetses, locations, func); #ifdef LOCAL_GRAPH_DEBUG std::cout << "LocalGraph::dump\n"; - for (auto& [get, sets] : getSetses) { + for (auto& pair : getSetses) { + auto* get = pair.first; + auto& sets = pair.second; std::cout << "GET\n" << get << " is influenced by\n"; for (auto* set : sets) { std::cout << set << '\n'; @@ -242,72 +244,34 @@ #endif } -bool LocalGraph::equivalent(LocalGet* a, LocalGet* b) { - auto& aSets = getSetses[a]; - auto& bSets = getSetses[b]; - // The simple case of one set dominating two gets easily proves that they must - // have the same value. (Note that we can infer dominance from the fact that - // there is a single set: if the set did not dominate one of the gets then - // there would definitely be another set for that get, the zero initialization - // at the function entry, if nothing else.) - if (aSets.size() != 1 || bSets.size() != 1) { - // TODO: use a LinearExecutionWalker to find trivially equal gets in basic - // blocks. that plus the above should handle 80% of cases. - // TODO: handle chains, merges and other situations - return false; - } - auto* aSet = *aSets.begin(); - auto* bSet = *bSets.begin(); - if (aSet != bSet) { - return false; - } - if (!aSet) { - // They are both nullptr, indicating the implicit value for a parameter - // or the zero for a local. - if (func->isParam(a->index)) { - // For parameters to be equivalent they must have the exact same - // index. - return a->index == b->index; - } else { - // As locals, they are both of value zero, but must have the right - // type as well. - return func->getLocalType(a->index) == func->getLocalType(b->index); - } - } else { - // They are both the same actual set. - return true; - } -} - -void LocalGraph::computeSetInfluences() { - for (auto& [curr, _] : locations) { - if (auto* get = curr->dynCast()) { - for (auto* set : getSetses[get]) { - setInfluences[set].insert(get); - } - } - } -} - -void LocalGraph::computeGetInfluences() { - for (auto& [curr, _] : locations) { +void LocalGraph::computeInfluences() { + for (auto& pair : locations) { + auto* curr = pair.first; if (auto* set = curr->dynCast()) { FindAll findAll(set->value); for (auto* get : findAll.list) { getInfluences[get].insert(set); } + } else { + auto* get = curr->cast(); + for (auto* set : getSetses[get]) { + setInfluences[set].insert(get); + } } } } void LocalGraph::computeSSAIndexes() { std::unordered_map> indexSets; - for (auto& [get, sets] : getSetses) { + for (auto& pair : getSetses) { + auto* get = pair.first; + auto& sets = pair.second; for (auto* set : sets) { indexSets[get->index].insert(set); } } - for (auto& [curr, _] : locations) { + for (auto& pair : locations) { + auto* curr = pair.first; if (auto* set = curr->dynCast()) { auto& sets = indexSets[set->index]; if (sets.size() == 1 && *sets.begin() != curr) { @@ -317,7 +281,9 @@ } } } - for (auto& [index, sets] : indexSets) { + for (auto& pair : indexSets) { + auto index = pair.first; + auto& sets = pair.second; if (sets.size() == 1) { SSAIndexes.insert(index); } diff -Nru binaryen-108/src/ir/local-graph.h binaryen-99/src/ir/local-graph.h --- binaryen-108/src/ir/local-graph.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/local-graph.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,7 +17,6 @@ #ifndef wasm_ir_local_graph_h #define wasm_ir_local_graph_h -#include "support/small_set.h" #include "wasm.h" namespace wasm { @@ -36,14 +35,12 @@ // the constructor computes getSetses, the sets affecting each get LocalGraph(Function* func); - // The local.sets relevant for an index or a get. The most common case is to - // have a single set; after that, to be a phi of 2 items, so we use a small - // set of size 2 to avoid allocations there. - using Sets = SmallSet; + // the local.sets relevant for an index or a get. + typedef std::set Sets; - using GetSetses = std::unordered_map; + typedef std::map GetSetses; - using Locations = std::map; + typedef std::map Locations; // externally useful information GetSetses getSetses; // the sets affecting each get. a nullptr set means the @@ -51,26 +48,15 @@ // param) Locations locations; // where each get and set is (for easy replacing) - // Checks if two gets are equivalent, that is, definitely have the same - // value. - bool equivalent(LocalGet* a, LocalGet* b); - // Optional: compute the influence graphs between sets and gets // (useful for algorithms that propagate changes). - void computeSetInfluences(); - void computeGetInfluences(); - - void computeInfluences() { - computeSetInfluences(); - computeGetInfluences(); - } + void computeInfluences(); // for each get, the sets whose values are influenced by that get - using GetInfluences = std::unordered_set; - std::unordered_map getInfluences; - using SetInfluences = std::unordered_set; - std::unordered_map setInfluences; + std::unordered_map> getInfluences; + // for each set, the gets whose values are influenced by that set + std::unordered_map> setInfluences; // Optional: Compute the local indexes that are SSA, in the sense of // * a single set for all the gets for that local index @@ -98,7 +84,6 @@ bool isSSA(Index x); private: - Function* func; std::set SSAIndexes; }; diff -Nru binaryen-108/src/ir/localize.h binaryen-99/src/ir/localize.h --- binaryen-108/src/ir/localize.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/localize.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,16 +17,13 @@ #ifndef wasm_ir_localizer_h #define wasm_ir_localizer_h -#include "ir/iteration.h" -#include "wasm-builder.h" +#include namespace wasm { // Make an expression available in a local. If already in one, just -// use that local, otherwise use a new local. -// -// Note that if the local is reused, this assumes it is not modified in between -// the set and the get, which the caller must ensure. +// use that local, otherwise use a new local + struct Localizer { Index index; Expression* expr; @@ -43,70 +40,6 @@ } } }; - -// Replaces all children with gets of locals, if they have any effects that -// interact with any of the others, or if they have side effects which cannot be -// removed. -// -// After this, the original input has only local.gets as inputs, or other things -// that have no interacting effects, and so those children can be reordered -// and/or removed as needed. -// -// The sets of the locals are emitted on a |sets| property on the class. Those -// must be emitted right before the input. -// -// This stops at the first unreachable child, as there is no code executing -// after that point anyhow. -// -// TODO: use in more places -struct ChildLocalizer { - std::vector sets; - - ChildLocalizer(Expression* input, - Function* func, - Module* wasm, - const PassOptions& options) { - Builder builder(*wasm); - ChildIterator iterator(input); - auto& children = iterator.children; - auto num = children.size(); - - // Compute the effects of all children. - std::vector effects; - for (Index i = 0; i < num; i++) { - // The children are in reverse order in ChildIterator, but we want to - // process them in the normal order. - auto* child = *children[num - 1 - i]; - effects.emplace_back(options, *wasm, child); - } - - // Go through the children and move to locals those that we need to. - for (Index i = 0; i < num; i++) { - auto** childp = children[num - 1 - i]; - auto* child = *childp; - if (child->type == Type::unreachable) { - break; - } - - // Use a local if we need to. That is the case either if this has side - // effects we can't remove, or if it interacts with other children. - bool needLocal = effects[i].hasUnremovableSideEffects(); - if (!needLocal) { - for (Index j = 0; j < num; j++) { - if (j != i && effects[i].invalidates(effects[j])) { - needLocal = true; - break; - } - } - } - if (needLocal) { - auto local = builder.addVar(func, child->type); - sets.push_back(builder.makeLocalSet(local, child)); - *childp = builder.makeLocalGet(local, child->type); - } - } - } -}; } // namespace wasm diff -Nru binaryen-108/src/ir/local-utils.h binaryen-99/src/ir/local-utils.h --- binaryen-108/src/ir/local-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/local-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -31,8 +31,8 @@ void analyze(Function* func) { analyze(func, func->body); } void analyze(Function* func, Expression* ast) { - num.clear(); num.resize(func->getNumLocals()); + std::fill(num.begin(), num.end(), 0); walk(ast); } @@ -45,21 +45,23 @@ PassOptions& passOptions; LocalGetCounter* localGetCounter = nullptr; - Module& module; + FeatureSet features; - UnneededSetRemover(Function* func, PassOptions& passOptions, Module& module) - : passOptions(passOptions), module(module) { + UnneededSetRemover(Function* func, + PassOptions& passOptions, + FeatureSet features) + : passOptions(passOptions), features(features) { LocalGetCounter counter(func); - UnneededSetRemover inner(counter, func, passOptions, module); + UnneededSetRemover inner(counter, func, passOptions, features); removed = inner.removed; } UnneededSetRemover(LocalGetCounter& localGetCounter, Function* func, PassOptions& passOptions, - Module& module) + FeatureSet features) : passOptions(passOptions), localGetCounter(&localGetCounter), - module(module) { + features(features) { walk(func->body); } @@ -94,7 +96,7 @@ auto* value = set->value; if (set->isTee()) { replaceCurrent(value); - } else if (EffectAnalyzer(passOptions, module, set->value) + } else if (EffectAnalyzer(passOptions, features, set->value) .hasSideEffects()) { Drop* drop = ExpressionManipulator::convert(set); drop->value = value; diff -Nru binaryen-108/src/ir/lubs.cpp binaryen-99/src/ir/lubs.cpp --- binaryen-108/src/ir/lubs.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/lubs.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/lubs.h" -#include "ir/utils.h" -#include "wasm-type.h" -#include "wasm.h" - -namespace wasm { - -namespace LUB { - -LUBFinder getResultsLUB(Function* func, Module& wasm) { - LUBFinder lub; - - if (!wasm.features.hasGC()) { - return lub; - } - - Type originalType = func->getResults(); - if (!originalType.hasRef()) { - // Nothing to refine. - return lub; - } - - // Before we do anything, we must refinalize the function, because otherwise - // its body may contain a block with a forced type, - // - // (func (result X) - // (block (result X) - // (..content with more specific type Y..) - // ) - ReFinalize().walkFunctionInModule(func, &wasm); - - lub.noteUpdatableExpression(func->body); - if (lub.getBestPossible() == originalType) { - return lub; - } - - // Scan the body and look at the returns. First, return expressions. - for (auto* ret : FindAll(func->body).list) { - lub.noteUpdatableExpression(ret->value); - if (lub.getBestPossible() == originalType) { - return lub; - } - } - - // Process return_calls and call_refs. Unlike return expressions which we - // just handled, these only get a type to update, not a value. - auto processReturnType = [&](Type type) { - // Return whether we still look ok to do the optimization. If this is - // false then we can stop here. - lub.note(type); - return lub.getBestPossible() != originalType; - }; - - for (auto* call : FindAll(func->body).list) { - if (call->isReturn && - !processReturnType(wasm.getFunction(call->target)->getResults())) { - return lub; - } - } - for (auto* call : FindAll(func->body).list) { - if (call->isReturn && - !processReturnType(call->heapType.getSignature().results)) { - return lub; - } - } - for (auto* call : FindAll(func->body).list) { - if (call->isReturn) { - auto targetType = call->target->type; - if (targetType == Type::unreachable) { - continue; - } - if (!processReturnType(targetType.getHeapType().getSignature().results)) { - return lub; - } - } - } - - return lub; -} - -} // namespace LUB - -} // namespace wasm diff -Nru binaryen-108/src/ir/lubs.h binaryen-99/src/ir/lubs.h --- binaryen-108/src/ir/lubs.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/lubs.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_lubs_h -#define wasm_ir_lubs_h - -#include "ir/module-utils.h" -#include "wasm.h" - -namespace wasm { - -// -// Helper to find a LUB of a series of expressions. This works incrementally so -// that if we see we are not improving on an existing type then we can stop -// early. It also notes null expressions that can be updated later, and if -// updating them would allow a better LUB it can do so. That is, given this: -// -// (ref.null any) ;; an expression that we can update -// (.. something of type data ..) -// -// We can update that null to type (ref null data) which would allow setting -// that as the LUB. This is important in cases where there is a null initial -// value in a field, for example: we should not let the type there prevent us -// from optimizing - after all, all nulls compare equally anyhow. -// -struct LUBFinder { - LUBFinder() {} - - LUBFinder(Type initialType) { note(initialType); } - - // Note another type to take into account in the lub. - void note(Type type) { lub = Type::getLeastUpperBound(lub, type); } - - // Note an expression that can be updated, that is, that we can modify in - // safe ways if doing so would allow us to get a better lub. The specific - // optimization possible here involves nulls, see the top comment. - void noteUpdatableExpression(Expression* curr) { - if (auto* null = curr->dynCast()) { - nulls.insert(null); - } else { - note(curr->type); - } - } - - void noteNullDefault() { - // A default value is indicated by a null pointer. - nulls.insert(nullptr); - } - - // Returns whether we noted any (reachable) value. This ignores nulls, as they - // do not contribute type information - we do not try to find a lub based on - // them (rather we update them to the LUB). - bool noted() { return lub != Type::unreachable; } - - // Returns the best possible lub. This ignores updatable nulls for the reasons - // mentioned above, since they will not limit us, aside from making the type - // nullable if nulls exist. This does not update the nulls. - Type getBestPossible() { - if (lub == Type::unreachable) { - // Perhaps if we have seen nulls we could compute a lub on them, but it's - // not clear that is helpful. - return lub; - } - - // We have a lub. Make it nullable if we need to. - if (!lub.isNullable() && !nulls.empty()) { - return Type(lub.getHeapType(), Nullable); - } else { - return lub; - } - } - - // Update the nulls for the best possible LUB, if we found one. - void updateNulls() { - auto newType = getBestPossible(); - if (newType != Type::unreachable) { - for (auto* null : nulls) { - // Default null values (represented as nullptr here) do not need to be - // updated. Aside from that, if this null is already of a more specific - // type, also do not update it - it's never worth making a type less - // specific. What we care about here is making sure the nulls are all - // specific enough given the LUB that is being applied. - if (null && !Type::isSubType(null->type, newType)) { - null->finalize(newType); - } - } - } - } - - // Combines the information in another LUBFinder into this one, and returns - // whether we changed anything. - bool combine(const LUBFinder& other) { - // Check if the lub was changed. - auto old = lub; - note(other.lub); - bool changed = old != lub; - - // Check if we added new updatable nulls. - for (auto* null : other.nulls) { - if (nulls.insert(null).second) { - changed = true; - } - } - - return changed; - } - -private: - // The least upper bound. As we go this always contains the latest value based - // on everything we've seen so far, except for nulls. - Type lub = Type::unreachable; - - // Nulls that we can update. A nullptr here indicates an "implicit" null, that - // is, a null default value. - std::unordered_set nulls; -}; - -namespace LUB { - -// Given a function, computes a LUB for its results. The caller can then decide -// to apply a refined type if we found one. -// -// This modifies the called function even if it fails to find a refined type as -// it does a refinalize in order to be able to compute the new types. We could -// roll back that change, but it's not harmful and can help, so we keep it -// regardless. -LUBFinder getResultsLUB(Function* func, Module& wasm); - -} // namespace LUB - -} // namespace wasm - -#endif // wasm_ir_lubs_h diff -Nru binaryen-108/src/ir/manipulation.h binaryen-99/src/ir/manipulation.h --- binaryen-108/src/ir/manipulation.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/manipulation.h 2021-01-07 20:01:06.000000000 +0000 @@ -19,8 +19,9 @@ #include "wasm.h" -namespace wasm::ExpressionManipulator { +namespace wasm { +namespace ExpressionManipulator { // Re-use a node's memory. This helps avoid allocation when optimizing. template inline OutputType* convert(InputType* input) { @@ -74,6 +75,8 @@ // Splice an item into the middle of a block's list void spliceIntoBlock(Block* block, Index index, Expression* add); -} // namespace wasm::ExpressionManipulator +} // namespace ExpressionManipulator + +} // namespace wasm #endif // wams_ir_manipulation_h diff -Nru binaryen-108/src/ir/match.h binaryen-99/src/ir/match.h --- binaryen-108/src/ir/match.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/match.h 2021-01-07 20:01:06.000000000 +0000 @@ -27,7 +27,9 @@ #include "ir/abstract.h" #include "wasm.h" -namespace wasm::Match { +namespace wasm { + +namespace Match { // The available matchers are: // @@ -37,12 +39,12 @@ // argument can be a specific value to match or it can be a pointer to a // value, Literal, or Const* at which to store the matched entity. // -// bval, ival, fval +// ival, fval // -// Match any boolean, any integer or any floating point constant. Takes -// neither, either, or both of two possible arguments: first, a pointer to a -// value, Literal, or Const* at which to store the matched entity and second, -// a specific value to match. +// Match any integer constant or any floating point constant. Takes neither, +// either, or both of two possible arguments: first, a pointer to a value, +// Literal, or Const* at which to store the matched entity and second, a +// specific value to match. // // constant // @@ -393,14 +395,7 @@ return Matcher>(binder, data); } -// {Bool,I32,I64,Int,F32,F64,Float,Number}Lit: -// match `Literal` of the expected `Type` -struct BoolLK { - static bool matchType(Literal lit) { - return lit.type == Type::i32 && (uint32_t)lit.geti32() <= 1U; - } - static int32_t getVal(Literal lit) { return lit.geti32(); } -}; +// {I32,I64,Int,F32,F64,Float,Number}Lit: match `Literal` of the expected `Type` struct I32LK { static bool matchType(Literal lit) { return lit.type == Type::i32; } static int32_t getVal(Literal lit) { return lit.geti32(); } @@ -439,9 +434,6 @@ template struct GetComponent, 0> { decltype(auto) operator()(Literal lit) { return T::getVal(lit); } }; -template inline decltype(auto) BoolLit(Literal* binder, S&& s) { - return Matcher, S>(binder, {}, s); -} template inline decltype(auto) I32Lit(Literal* binder, S&& s) { return Matcher, S>(binder, {}, s); } @@ -609,27 +601,6 @@ // Public matching API -inline decltype(auto) bval() { - return Internal::ConstMatcher( - nullptr, Internal::BoolLit(nullptr, Internal::Any(nullptr))); -} -inline decltype(auto) bval(bool x) { - return Internal::ConstMatcher( - nullptr, Internal::BoolLit(nullptr, Internal::Exact(nullptr, x))); -} -inline decltype(auto) bval(bool* binder) { - return Internal::ConstMatcher( - nullptr, Internal::BoolLit(nullptr, Internal::Any(binder))); -} -inline decltype(auto) bval(Literal* binder) { - return Internal::ConstMatcher( - nullptr, Internal::BoolLit(binder, Internal::Any(nullptr))); -} -inline decltype(auto) bval(Const** binder) { - return Internal::ConstMatcher( - binder, Internal::BoolLit(nullptr, Internal::Any(nullptr))); -} - inline decltype(auto) i32() { return Internal::ConstMatcher( nullptr, Internal::I32Lit(nullptr, Internal::Any(nullptr))); @@ -870,6 +841,8 @@ return Internal::SelectMatcher(binder, s1, s2, s3); } -} // namespace wasm::Match +} // namespace Match + +} // namespace wasm #endif // wasm_ir_match_h diff -Nru binaryen-108/src/ir/memory-utils.cpp binaryen-99/src/ir/memory-utils.cpp --- binaryen-108/src/ir/memory-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/memory-utils.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/memory-utils.h" -#include "wasm.h" - -namespace wasm::MemoryUtils { - -bool flatten(Module& wasm) { - // The presence of any MemoryInit instructions is a problem because they care - // about segment identity, which flattening gets rid of ( when it merges them - // all into one big segment). - ModuleUtils::ParallelFunctionAnalysis analysis( - wasm, [&](Function* func, bool& hasMemoryInit) { - if (func->imported()) { - return; - } - hasMemoryInit = FindAll(func->body).list.size() > 0; - }); - - for (auto& [func, hasMemoryInit] : analysis.map) { - if (hasMemoryInit) { - return false; - } - } - - auto& memory = wasm.memory; - - if (memory.segments.size() == 0) { - return true; - } - - std::vector data; - for (auto& segment : memory.segments) { - if (segment.isPassive) { - return false; - } - auto* offset = segment.offset->dynCast(); - if (!offset) { - return false; - } - } - for (auto& segment : memory.segments) { - auto* offset = segment.offset->dynCast(); - Index start = offset->value.getInteger(); - Index end = start + segment.data.size(); - if (end > data.size()) { - data.resize(end); - } - std::copy(segment.data.begin(), segment.data.end(), data.begin() + start); - } - memory.segments.resize(1); - memory.segments[0].offset->cast()->value = Literal(int32_t(0)); - memory.segments[0].data.swap(data); - - return true; -} - -} // namespace wasm::MemoryUtils diff -Nru binaryen-108/src/ir/memory-utils.h binaryen-99/src/ir/memory-utils.h --- binaryen-108/src/ir/memory-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/memory-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -25,12 +25,51 @@ #include "wasm-builder.h" #include "wasm.h" -namespace wasm::MemoryUtils { +namespace wasm { +namespace MemoryUtils { // Flattens memory into a single data segment, or no segment. If there is // a segment, it starts at 0. +// If ensuredSegmentSize is provided, then a segment is always emitted, +// and of at least that size. // Returns true if successful (e.g. relocatable segments cannot be flattened). -bool flatten(Module& wasm); +inline bool flatten(Memory& memory, + Index ensuredSegmentSize = 0, + Module* module = nullptr) { + if (memory.segments.size() == 0) { + if (ensuredSegmentSize > 0) { + assert(module); // must provide a module if ensuring a size. + Builder builder(*module); + memory.segments.emplace_back(builder.makeConst(int32_t(0))); + memory.segments[0].data.resize(ensuredSegmentSize); + } + return true; + } + std::vector data; + data.resize(ensuredSegmentSize); + for (auto& segment : memory.segments) { + if (segment.isPassive) { + return false; + } + auto* offset = segment.offset->dynCast(); + if (!offset) { + return false; + } + } + for (auto& segment : memory.segments) { + auto* offset = segment.offset->dynCast(); + Index start = offset->value.getInteger(); + Index end = start + segment.data.size(); + if (end > data.size()) { + data.resize(end); + } + std::copy(segment.data.begin(), segment.data.end(), data.begin() + start); + } + memory.segments.resize(1); + memory.segments[0].offset->cast()->value = Literal(int32_t(0)); + memory.segments[0].data.swap(data); + return true; +} // Ensures that the memory exists (of minimal size). inline void ensureExists(Memory& memory) { @@ -159,6 +198,8 @@ memory.segments.swap(mergedSegments); return true; } -} // namespace wasm::MemoryUtils +} // namespace MemoryUtils + +} // namespace wasm #endif // wasm_ir_memory_h diff -Nru binaryen-108/src/ir/module-splitting.cpp binaryen-99/src/ir/module-splitting.cpp --- binaryen-108/src/ir/module-splitting.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/module-splitting.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -18,7 +18,7 @@ // // 1. Create the new secondary module. // -// 2. Export globals, tags, tables, and memories from the primary module and +// 2. Export globals, events, tables, and memories from the primary module and // import them in the secondary module. // // 3. Move the deferred functions from the primary to the secondary module. @@ -54,8 +54,8 @@ // ref.func instructions, they will have to be modified to use a similar layer // of indirection. // -// The code as currently written makes a couple assumptions about the module -// that is being split: +// The code as currently written makes a few assumptions about the module that +// is being split: // // 1. It assumes that mutable-globals is allowed. This could be worked around // by introducing wrapper functions for globals and rewriting secondary @@ -66,9 +66,13 @@ // is exactly one segment that may have a non-constant offset. It also // assumes that all segments are active segments (although Binaryen does // not yet support passive table segments anyway). +// +// 3. It assumes that each function appears in the table at most once. This +// isn't necessarily true in general or even for LLVM output after function +// deduplication. Relaxing this assumption would just require slightly more +// complex code, so it is a good candidate for a follow up PR. #include "ir/module-splitting.h" -#include "ir/element-utils.h" #include "ir/manipulation.h" #include "ir/module-utils.h" #include "ir/names.h" @@ -76,30 +80,42 @@ #include "wasm-builder.h" #include "wasm.h" -namespace wasm::ModuleSplitting { +namespace std { + +// Used in ModuleSplitter::shareImportableItems +template<> struct hash> { + size_t operator()(const pair& p) const { + auto digest = wasm::hash(p.first); + wasm::rehash(digest, p.second); + return digest; + } +}; + +} // namespace std + +namespace wasm { + +namespace ModuleSplitting { namespace { -template void forEachElement(Module& module, F f) { - ModuleUtils::iterActiveElementSegments(module, [&](ElementSegment* segment) { +template void forEachElement(Table& table, F f) { + for (auto& segment : table.segments) { Name base = ""; Index offset = 0; - if (auto* c = segment->offset->dynCast()) { + if (auto* c = segment.offset->dynCast()) { offset = c->value.geti32(); - } else if (auto* g = segment->offset->dynCast()) { + } else if (auto* g = segment.offset->dynCast()) { base = g->name; } - ElementUtils::iterElementSegmentFunctionNames( - segment, [&](Name& entry, Index i) { - f(segment->table, base, offset + i, entry); - }); - }); + for (size_t i = 0; i < segment.data.size(); ++i) { + f(base, offset + i, segment.data[i]); + } + } } struct TableSlotManager { struct Slot { - Name tableName; - // If `global` is empty, then this slot is at a statically known index. Name global; Index index = 0; @@ -108,19 +124,15 @@ Expression* makeExpr(Module& module); }; Module& module; - Table* activeTable = nullptr; - ElementSegment* activeSegment = nullptr; + Table& table; + Table::Segment* activeSegment = nullptr; Slot activeBase; std::map funcIndices; - std::vector activeTableSegments; TableSlotManager(Module& module); - Table* makeTable(); - ElementSegment* makeElementSegment(); - // Returns the table index for `func`, allocating a new index if necessary. - Slot getSlot(Name func, HeapType type); + Slot getSlot(Name func); void addSlot(Name func, Slot slot); }; @@ -137,77 +149,46 @@ } void TableSlotManager::addSlot(Name func, Slot slot) { - // Ignore functions that already have slots. - funcIndices.insert({func, slot}); + auto it = funcIndices.insert(std::make_pair(func, slot)); + assert(it.second && "Function already has multiple table slots"); } -TableSlotManager::TableSlotManager(Module& module) : module(module) { - // TODO: Reject or handle passive element segments - auto it = std::find_if(module.tables.begin(), - module.tables.end(), - [&](std::unique_ptr
& table) { - return table->type == Type::funcref; - }); - if (it == module.tables.end()) { - return; - } - - activeTable = it->get(); - ModuleUtils::iterTableSegments( - module, activeTable->name, [&](ElementSegment* segment) { - activeTableSegments.push_back(segment); - }); +TableSlotManager::TableSlotManager(Module& module) + : module(module), table(module.table) { // If there is exactly one table segment and that segment has a non-constant // offset, append new items to the end of that segment. In all other cases, // append new items at constant offsets after all existing items at constant // offsets. - if (activeTableSegments.size() == 1 && - activeTableSegments[0]->type == Type::funcref && - !activeTableSegments[0]->offset->is()) { - assert(activeTableSegments[0]->offset->is() && + if (table.segments.size() == 1 && !table.segments[0].offset->is()) { + assert(table.segments[0].offset->is() && "Unexpected initializer instruction"); - activeSegment = activeTableSegments[0]; - activeBase = {activeTable->name, - activeTableSegments[0]->offset->cast()->name, - 0}; + activeSegment = &table.segments[0]; + activeBase = {table.segments[0].offset->cast()->name, 0}; } else { // Finds the segment with the highest occupied table slot so that new items // can be inserted contiguously at the end of it without accidentally // overwriting any other items. TODO: be more clever about filling gaps in // the table, if that is ever useful. Index maxIndex = 0; - for (auto& segment : activeTableSegments) { - assert(segment->offset->is() && + for (auto& segment : table.segments) { + assert(segment.offset->is() && "Unexpected non-const segment offset with multiple segments"); - Index segmentBase = segment->offset->cast()->value.geti32(); - if (segmentBase + segment->data.size() >= maxIndex) { - maxIndex = segmentBase + segment->data.size(); - activeSegment = segment; - activeBase = {activeTable->name, "", segmentBase}; + Index segmentBase = segment.offset->cast()->value.geti32(); + if (segmentBase + segment.data.size() >= maxIndex) { + maxIndex = segmentBase + segment.data.size(); + activeSegment = &segment; + activeBase = {"", segmentBase}; } } } - // Initialize funcIndices with the functions already in the table. - forEachElement(module, [&](Name table, Name base, Index offset, Name func) { - addSlot(func, {table, base, offset}); + forEachElement(table, [&](Name base, Index offset, Name func) { + addSlot(func, {base, offset}); }); } -Table* TableSlotManager::makeTable() { - return module.addTable( - Builder::makeTable(Names::getValidTableName(module, Name::fromInt(0)))); -} - -ElementSegment* TableSlotManager::makeElementSegment() { - return module.addElementSegment(Builder::makeElementSegment( - Names::getValidElementSegmentName(module, Name::fromInt(0)), - activeTable->name, - Builder(module).makeConst(int32_t(0)))); -} - -TableSlotManager::Slot TableSlotManager::getSlot(Name func, HeapType type) { +TableSlotManager::Slot TableSlotManager::getSlot(Name func) { auto slotIt = funcIndices.find(func); if (slotIt != funcIndices.end()) { return slotIt->second; @@ -215,38 +196,21 @@ // If there are no segments yet, allocate one. if (activeSegment == nullptr) { - if (activeTable == nullptr) { - activeTable = makeTable(); - activeBase = {activeTable->name, "", 0}; - } - - // None of the existing segments should refer to the active table - assert(std::all_of(module.elementSegments.begin(), - module.elementSegments.end(), - [&](std::unique_ptr& segment) { - return segment->table != activeTable->name; - })); - - activeSegment = makeElementSegment(); + table.exists = true; + assert(table.segments.size() == 0); + table.segments.emplace_back(Builder(module).makeConst(int32_t(0))); + activeSegment = &table.segments.back(); } - Slot newSlot = {activeBase.tableName, - activeBase.global, + Slot newSlot = {activeBase.global, activeBase.index + Index(activeSegment->data.size())}; - - Builder builder(module); - activeSegment->data.push_back(builder.makeRefFunc(func, type)); - + activeSegment->data.push_back(func); addSlot(func, newSlot); - if (activeTable->initial <= newSlot.index) { - activeTable->initial = newSlot.index + 1; - // TODO: handle the active table not being the dylink table (#3823) - if (module.dylinkSection) { - module.dylinkSection->tableSize = activeTable->initial; - } + if (table.initial <= newSlot.index) { + table.initial = newSlot.index + 1; } - if (activeTable->max <= newSlot.index) { - activeTable->max = newSlot.index + 1; + if (table.max <= newSlot.index) { + table.max = newSlot.index + 1; } return newSlot; } @@ -264,15 +228,10 @@ TableSlotManager tableManager; - Names::MinifiedNameGenerator minified; - // Map from internal function names to (one of) their corresponding export // names. std::map exportedPrimaryFuncs; - // Map placeholder indices to the names of the functions they replace. - std::map placeholderMap; - // Initialization helpers static std::unique_ptr initSecondary(const Module& primary); static std::pair, std::set> @@ -347,14 +306,8 @@ if (exportIt != exportedPrimaryFuncs.end()) { exportName = exportIt->second; } else { - if (config.minimizeNewExportNames) { - do { - exportName = config.newExportPrefix + minified.getName(); - } while (primary.getExportOrNull(exportName) != nullptr); - } else { - exportName = Names::getValidExportName( - primary, config.newExportPrefix + funcName.c_str()); - } + exportName = Names::getValidExportName( + primary, config.newExportPrefix + funcName.c_str()); primary.addExport( Builder::makeExport(exportName, funcName, ExternalKind::Function)); exportedPrimaryFuncs[funcName] = exportName; @@ -363,7 +316,7 @@ // module. if (secondary.getFunctionOrNull(funcName) == nullptr) { auto func = - Builder::makeFunction(funcName, primary.getFunction(funcName)->type, {}); + Builder::makeFunction(funcName, primary.getFunction(funcName)->sig, {}); func->module = config.importNamespace; func->base = exportName; secondary.addFunction(std::move(func)); @@ -396,16 +349,18 @@ // We've already created a thunk for this function continue; } - auto* func = primary.addFunction(Builder::makeFunction( - secondaryFunc, secondary.getFunction(secondaryFunc)->type, {})); + auto tableSlot = tableManager.getSlot(secondaryFunc); + auto func = std::make_unique(); + + func->name = secondaryFunc; + func->sig = secondary.getFunction(secondaryFunc)->sig; std::vector args; - Type params = func->getParams(); - for (size_t i = 0, size = params.size(); i < size; ++i) { - args.push_back(builder.makeLocalGet(i, params[i])); - } - auto tableSlot = tableManager.getSlot(secondaryFunc, func->type); - func->body = builder.makeCallIndirect( - tableSlot.tableName, tableSlot.makeExpr(primary), args, func->type); + for (size_t i = 0, size = func->sig.params.size(); i < size; ++i) { + args.push_back(builder.makeLocalGet(i, func->sig.params[i])); + } + func->body = + builder.makeCallIndirect(tableSlot.makeExpr(primary), args, func->sig); + primary.addFunction(std::move(func)); } } @@ -417,20 +372,15 @@ Builder builder; CallIndirector(ModuleSplitter& parent) : parent(parent), builder(parent.primary) {} - // Avoid visitRefFunc on element segment data - void walkElementSegment(ElementSegment* segment) {} void visitCall(Call* curr) { if (!parent.secondaryFuncs.count(curr->target)) { return; } - auto* func = parent.secondary.getFunction(curr->target); - auto tableSlot = parent.tableManager.getSlot(curr->target, func->type); - replaceCurrent( - builder.makeCallIndirect(tableSlot.tableName, - tableSlot.makeExpr(parent.primary), - curr->operands, - func->type, - curr->isReturn)); + replaceCurrent(builder.makeCallIndirect( + parent.tableManager.getSlot(curr->target).makeExpr(parent.primary), + curr->operands, + parent.secondary.getFunction(curr->target)->sig, + curr->isReturn)); } void visitRefFunc(RefFunc* curr) { assert(false && "TODO: handle ref.func as well"); @@ -475,19 +425,14 @@ } void ModuleSplitter::setupTablePatching() { - if (!tableManager.activeTable) { - return; - } - - std::map replacedElems; + std::map replacedElems; // Replace table references to secondary functions with an imported // placeholder that encodes the table index in its name: // `importNamespace`.`index`. - forEachElement(primary, [&](Name, Name, Index index, Name& elem) { + forEachElement(primary.table, [&](Name, Index index, Name& elem) { if (secondaryFuncs.count(elem)) { - placeholderMap[index] = elem; + replacedElems[index] = elem; auto* secondaryFunc = secondary.getFunction(elem); - replacedElems[index] = secondaryFunc; auto placeholder = std::make_unique(); placeholder->module = config.placeholderNamespace; placeholder->base = std::to_string(index); @@ -495,7 +440,7 @@ primary, std::string("placeholder_") + std::string(placeholder->base.c_str())); placeholder->hasExplicitName = false; - placeholder->type = secondaryFunc->type; + placeholder->sig = secondaryFunc->sig; elem = placeholder->name; primary.addFunction(std::move(placeholder)); } @@ -506,13 +451,10 @@ return; } - auto secondaryTable = - ModuleUtils::copyTable(tableManager.activeTable, secondary); - if (tableManager.activeBase.global.size()) { - assert(tableManager.activeTableSegments.size() == 1 && + assert(primary.table.segments.size() == 1 && "Unexpected number of segments with non-const base"); - assert(secondary.tables.size() == 1 && secondary.elementSegments.empty()); + assert(secondary.table.segments.size() == 0); // Since addition is not currently allowed in initializer expressions, we // need to start the new secondary segment where the primary segment starts. // The secondary segment will contain the same primary functions as the @@ -521,50 +463,38 @@ // to be imported into the second module. TODO: use better strategies here, // such as using ref.func in the start function or standardizing addition in // initializer expressions. - ElementSegment* primarySeg = tableManager.activeTableSegments.front(); - std::vector secondaryElems; - secondaryElems.reserve(primarySeg->data.size()); + const Table::Segment& primarySeg = primary.table.segments.front(); + std::vector secondaryElems; + secondaryElems.reserve(primarySeg.data.size()); // Copy functions from the primary segment to the secondary segment, // replacing placeholders and creating new exports and imports as necessary. auto replacement = replacedElems.begin(); for (Index i = 0; - i < primarySeg->data.size() && replacement != replacedElems.end(); + i < primarySeg.data.size() && replacement != replacedElems.end(); ++i) { if (replacement->first == i) { - // primarySeg->data[i] is a placeholder, so use the secondary function. - auto* func = replacement->second; - auto* ref = Builder(secondary).makeRefFunc(func->name, func->type); - secondaryElems.push_back(ref); + // primarySeg.data[i] is a placeholder, so use the secondary function. + secondaryElems.push_back(replacement->second); ++replacement; - } else if (auto* get = primarySeg->data[i]->dynCast()) { - exportImportFunction(get->func); - auto* copied = - ExpressionManipulator::copy(primarySeg->data[i], secondary); - secondaryElems.push_back(copied); + } else { + exportImportFunction(primarySeg.data[i]); + secondaryElems.push_back(primarySeg.data[i]); } } - auto offset = ExpressionManipulator::copy(primarySeg->offset, secondary); - auto secondarySeg = std::make_unique( - secondaryTable->name, offset, secondaryTable->type, secondaryElems); - secondarySeg->setName(primarySeg->name, primarySeg->hasExplicitName); - secondary.addElementSegment(std::move(secondarySeg)); + auto offset = ExpressionManipulator::copy(primarySeg.offset, secondary); + secondary.table.segments.emplace_back(offset, secondaryElems); return; } // Create active table segments in the secondary module to patch in the // original functions when it is instantiated. Index currBase = replacedElems.begin()->first; - std::vector currData; + std::vector currData; auto finishSegment = [&]() { auto* offset = Builder(secondary).makeConst(int32_t(currBase)); - auto secondarySeg = std::make_unique( - secondaryTable->name, offset, secondaryTable->type, currData); - Name name = Names::getValidElementSegmentName( - secondary, Name::fromInt(secondary.elementSegments.size())); - secondarySeg->setName(name, false); - secondary.addElementSegment(std::move(secondarySeg)); + secondary.table.segments.emplace_back(offset, currData); }; for (auto curr = replacedElems.begin(); curr != replacedElems.end(); ++curr) { if (curr->first != currBase + currData.size()) { @@ -572,8 +502,7 @@ currBase = curr->first; currData.clear(); } - auto* func = curr->second; - currData.push_back(Builder(secondary).makeRefFunc(func->name, func->type)); + currData.push_back(curr->second); } if (currData.size()) { finishSegment(); @@ -622,13 +551,12 @@ primary.memory, secondary.memory, "memory", ExternalKind::Memory); } - for (auto& table : primary.tables) { - auto secondaryTable = secondary.getTableOrNull(table->name); - if (!secondaryTable) { - secondaryTable = ModuleUtils::copyTable(table.get(), secondary); - } - - makeImportExport(*table, *secondaryTable, "table", ExternalKind::Table); + if (primary.table.exists) { + secondary.table.exists = true; + secondary.table.initial = primary.table.initial; + secondary.table.max = primary.table.max; + makeImportExport( + primary.table, secondary.table, "table", ExternalKind::Table); } for (auto& global : primary.globals) { @@ -647,19 +575,21 @@ secondary.addGlobal(std::move(secondaryGlobal)); } - for (auto& tag : primary.tags) { - auto secondaryTag = std::make_unique(); - secondaryTag->sig = tag->sig; - makeImportExport(*tag, *secondaryTag, "tag", ExternalKind::Tag); - secondary.addTag(std::move(secondaryTag)); + for (auto& event : primary.events) { + auto secondaryEvent = std::make_unique(); + secondaryEvent->attribute = event->attribute; + secondaryEvent->sig = event->sig; + makeImportExport(*event, *secondaryEvent, "event", ExternalKind::Event); + secondary.addEvent(std::move(secondaryEvent)); } } } // anonymous namespace -Results splitFunctions(Module& primary, const Config& config) { - ModuleSplitter split(primary, config); - return {std::move(split.secondaryPtr), std::move(split.placeholderMap)}; +std::unique_ptr splitFunctions(Module& primary, const Config& config) { + return std::move(ModuleSplitter(primary, config).secondaryPtr); } -} // namespace wasm::ModuleSplitting +} // namespace ModuleSplitting + +} // namespace wasm diff -Nru binaryen-108/src/ir/module-splitting.h binaryen-99/src/ir/module-splitting.h --- binaryen-108/src/ir/module-splitting.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/module-splitting.h 2021-01-07 20:01:06.000000000 +0000 @@ -26,7 +26,7 @@ // functions. The secondary module imports all of its dependencies from the // primary module. // -// This code currently makes a couple assumptions about the modules that will be +// This code currently makes a few assumptions about the modules that will be // split and will fail assertions if those assumptions are not true. // // 1) It assumes that mutable-globals are allowed. @@ -34,6 +34,8 @@ // 2) It assumes that either all segment offsets are constants or there is // exactly one segment that may have a non-constant offset. // +// 3) It assumes that each function appears in the table at most once. +// // These requirements will be relaxed as necessary in the future, but for now // this code should be considered experimental and used with care. @@ -42,7 +44,9 @@ #include "wasm.h" -namespace wasm::ModuleSplitting { +namespace wasm { + +namespace ModuleSplitting { struct Config { // The set of functions to keep in the primary module. All others are split @@ -60,20 +64,13 @@ // used to differentiate between "real" exports of the module and exports that // should only be consumed by the secondary module. std::string newExportPrefix = ""; - // Whether the export names of newly created exports should be minimized. If - // false, the original function names will be used (after `newExportPrefix`) - // as the new export names. - bool minimizeNewExportNames = false; -}; - -struct Results { - std::unique_ptr secondary; - std::map placeholderMap; }; // Returns the new secondary module and modifies the `primary` module in place. -Results splitFunctions(Module& primary, const Config& config); +std::unique_ptr splitFunctions(Module& primary, const Config& config); + +} // namespace ModuleSplitting -} // namespace wasm::ModuleSplitting +} // namespace wasm #endif // wasm_ir_module_splitting_h diff -Nru binaryen-108/src/ir/module-utils.cpp binaryen-99/src/ir/module-utils.cpp --- binaryen-108/src/ir/module-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/module-utils.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "module-utils.h" -#include "support/insert_ordered.h" -#include "support/topological_sort.h" - -namespace wasm::ModuleUtils { - -namespace { - -// Helper for collecting HeapTypes and their frequencies. -struct Counts : public InsertOrderedMap { - void note(HeapType type) { - if (!type.isBasic()) { - (*this)[type]++; - } - } - void note(Type type) { - for (HeapType ht : type.getHeapTypeChildren()) { - note(ht); - } - } - // Ensure a type is included without increasing its count. - void include(HeapType type) { - if (!type.isBasic()) { - (*this)[type]; - } - } -}; - -struct CodeScanner - : PostWalker> { - Counts& counts; - - CodeScanner(Module& wasm, Counts& counts) : counts(counts) { - setModule(&wasm); - } - - void visitExpression(Expression* curr) { - if (auto* call = curr->dynCast()) { - counts.note(call->heapType); - } else if (curr->is()) { - counts.note(curr->type); - } else if (curr->is() || curr->is()) { - counts.note(curr->type.getRtt().heapType); - } else if (auto* make = curr->dynCast()) { - handleMake(make); - } else if (auto* make = curr->dynCast()) { - handleMake(make); - } else if (auto* make = curr->dynCast()) { - handleMake(make); - } else if (auto* cast = curr->dynCast()) { - handleCast(cast); - } else if (auto* cast = curr->dynCast()) { - handleCast(cast); - } else if (auto* cast = curr->dynCast()) { - if (cast->op == BrOnCast || cast->op == BrOnCastFail) { - handleCast(cast); - } - } else if (auto* get = curr->dynCast()) { - counts.note(get->ref->type); - } else if (auto* set = curr->dynCast()) { - counts.note(set->ref->type); - } else if (Properties::isControlFlowStructure(curr)) { - if (curr->type.isTuple()) { - // TODO: Allow control flow to have input types as well - counts.note(Signature(Type::none, curr->type)); - } else { - counts.note(curr->type); - } - } - } - - template void handleMake(T* curr) { - if (!curr->rtt && curr->type != Type::unreachable) { - counts.note(curr->type.getHeapType()); - } - } - - template void handleCast(T* curr) { - // Some operations emit a HeapType in the binary format, if they are - // static and not dynamic (if dynamic, the RTT provides the heap type). - if (!curr->rtt) { - counts.note(curr->intendedType); - } - } -}; - -Counts getHeapTypeCounts(Module& wasm) { - // Collect module-level info. - Counts counts; - CodeScanner(wasm, counts).walkModuleCode(&wasm); - for (auto& curr : wasm.tags) { - counts.note(curr->sig); - } - for (auto& curr : wasm.tables) { - counts.note(curr->type); - } - for (auto& curr : wasm.elementSegments) { - counts.note(curr->type); - } - - // Collect info from functions in parallel. - ModuleUtils::ParallelFunctionAnalysis - analysis(wasm, [&](Function* func, Counts& counts) { - counts.note(func->type); - for (auto type : func->vars) { - counts.note(type); - } - if (!func->imported()) { - CodeScanner(wasm, counts).walk(func->body); - } - }); - - // Combine the function info with the module info. - for (auto& [_, functionCounts] : analysis.map) { - for (auto& [sig, count] : functionCounts) { - counts[sig] += count; - } - } - - // Recursively traverse each reference type, which may have a child type that - // is itself a reference type. This reflects an appearance in the binary - // format that is in the type section itself. As we do this we may find more - // and more types, as nested children of previous ones. Each such type will - // appear in the type section once, so we just need to visit it once. Also - // track which recursion groups we've already processed to avoid quadratic - // behavior when there is a single large group. - InsertOrderedSet newTypes; - for (auto& [type, _] : counts) { - newTypes.insert(type); - } - std::unordered_set includedGroups; - while (!newTypes.empty()) { - auto iter = newTypes.begin(); - auto ht = *iter; - newTypes.erase(iter); - for (HeapType child : ht.getHeapTypeChildren()) { - if (!child.isBasic()) { - if (!counts.count(child)) { - newTypes.insert(child); - } - counts.note(child); - } - } - - if (auto super = ht.getSuperType()) { - if (!counts.count(*super)) { - newTypes.insert(*super); - // We should unconditionally count supertypes, but while the type system - // is in flux, skip counting them to keep the type orderings in nominal - // test outputs more similar to the orderings in the equirecursive - // outputs. FIXME - counts.include(*super); - } - } - - // Make sure we've noted the complete recursion group of each type as well. - auto recGroup = ht.getRecGroup(); - if (includedGroups.insert(recGroup).second) { - for (auto type : recGroup) { - if (!counts.count(type)) { - newTypes.insert(type); - counts.include(type); - } - } - } - } - - return counts; -} - -void setIndices(IndexedHeapTypes& indexedTypes) { - for (Index i = 0; i < indexedTypes.types.size(); i++) { - indexedTypes.indices[indexedTypes.types[i]] = i; - } -} - -} // anonymous namespace - -std::vector collectHeapTypes(Module& wasm) { - Counts counts = getHeapTypeCounts(wasm); - std::vector types; - types.reserve(counts.size()); - for (auto& [type, _] : counts) { - types.push_back(type); - } - return types; -} - -IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm) { - TypeSystem system = getTypeSystem(); - Counts counts = getHeapTypeCounts(wasm); - - if (system == TypeSystem::Equirecursive) { - // Sort by frequency and then original insertion order. - std::vector> sorted(counts.begin(), - counts.end()); - std::stable_sort(sorted.begin(), sorted.end(), [&](auto a, auto b) { - return a.second > b.second; - }); - - // Collect the results. - IndexedHeapTypes indexedTypes; - for (Index i = 0; i < sorted.size(); ++i) { - indexedTypes.types.push_back(sorted[i].first); - } - - setIndices(indexedTypes); - return indexedTypes; - } - - // Types have to be arranged into topologically ordered recursion groups. - // Under isorecrsive typing, the topological sort has to take all referenced - // rec groups into account but under nominal typing it only has to take - // supertypes into account. First, sort the groups by average use count among - // their members so that the later topological sort will place frequently used - // types first. - struct GroupInfo { - size_t index; - double useCount = 0; - std::unordered_set preds; - std::vector sortedPreds; - GroupInfo(size_t index) : index(index) {} - bool operator<(const GroupInfo& other) const { - if (useCount != other.useCount) { - return useCount < other.useCount; - } - return index > other.index; - } - }; - - struct GroupInfoMap : std::unordered_map { - void sort(std::vector& groups) { - std::sort(groups.begin(), groups.end(), [&](auto& a, auto& b) { - return this->at(a) < this->at(b); - }); - } - }; - - // Collect the information that will be used to sort the recursion groups. - GroupInfoMap groupInfos; - for (auto& [type, _] : counts) { - RecGroup group = type.getRecGroup(); - // Try to initialize a new info or get the existing info. - auto& info = groupInfos.insert({group, {groupInfos.size()}}).first->second; - // Update the reference count. - info.useCount += counts.at(type); - // Collect predecessor groups. - switch (system) { - case TypeSystem::Isorecursive: - for (auto child : type.getReferencedHeapTypes()) { - if (!child.isBasic()) { - RecGroup otherGroup = child.getRecGroup(); - if (otherGroup != group) { - info.preds.insert(otherGroup); - } - } - } - break; - case TypeSystem::Nominal: - if (auto super = type.getSuperType()) { - info.preds.insert(super->getRecGroup()); - } - break; - case TypeSystem::Equirecursive: - WASM_UNREACHABLE( - "Equirecursive types should already have been handled"); - } - } - - // Fix up the use counts to be averages to ensure groups are used comensurate - // with the amount of index space they occupy. Skip this for nominal types - // since their internal group size is always 1. - if (system != TypeSystem::Nominal) { - for (auto& [group, info] : groupInfos) { - info.useCount /= group.size(); - } - } - - // Sort the predecessors so the most used will be visited first. - for (auto& [group, info] : groupInfos) { - info.sortedPreds.insert( - info.sortedPreds.end(), info.preds.begin(), info.preds.end()); - groupInfos.sort(info.sortedPreds); - info.preds.clear(); - } - - struct RecGroupSort : TopologicalSort { - GroupInfoMap& groupInfos; - RecGroupSort(GroupInfoMap& groupInfos) : groupInfos(groupInfos) { - // Sort all the groups so the topological sort visits the most used first. - std::vector sortedGroups; - sortedGroups.reserve(groupInfos.size()); - for (auto& [group, _] : groupInfos) { - sortedGroups.push_back(group); - } - groupInfos.sort(sortedGroups); - for (auto group : sortedGroups) { - push(group); - } - } - - void pushPredecessors(RecGroup group) { - for (auto pred : groupInfos.at(group).sortedPreds) { - push(pred); - } - } - }; - - // Perform the topological sort and collect the types. - IndexedHeapTypes indexedTypes; - indexedTypes.types.reserve(counts.size()); - for (auto group : RecGroupSort(groupInfos)) { - for (auto member : group) { - indexedTypes.types.push_back(member); - } - } - setIndices(indexedTypes); - return indexedTypes; -} - -} // namespace wasm::ModuleUtils diff -Nru binaryen-108/src/ir/module-utils.h binaryen-99/src/ir/module-utils.h --- binaryen-108/src/ir/module-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/module-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,7 +17,6 @@ #ifndef wasm_ir_module_h #define wasm_ir_module_h -#include "ir/element-utils.h" #include "ir/find_all.h" #include "ir/manipulation.h" #include "ir/properties.h" @@ -25,15 +24,14 @@ #include "support/unique_deferring_queue.h" #include "wasm.h" -namespace wasm::ModuleUtils { +namespace wasm { -// Copies a function into a module. If newName is provided it is used as the -// name of the function (otherwise the original name is copied). -inline Function* -copyFunction(Function* func, Module& out, Name newName = Name()) { - auto ret = std::make_unique(); - ret->name = newName.is() ? newName : func->name; - ret->type = func->type; +namespace ModuleUtils { + +inline Function* copyFunction(Function* func, Module& out) { + auto* ret = new Function(); + ret->name = func->name; + ret->sig = func->sig; ret->vars = func->vars; ret->localNames = func->localNames; ret->localIndices = func->localIndices; @@ -43,7 +41,8 @@ ret->base = func->base; // TODO: copy Stack IR assert(!func->stackIR); - return out.addFunction(std::move(ret)); + out.addFunction(ret); + return ret; } inline Global* copyGlobal(Global* global, Module& out) { @@ -62,50 +61,15 @@ return ret; } -inline Tag* copyTag(Tag* tag, Module& out) { - auto* ret = new Tag(); - ret->name = tag->name; - ret->sig = tag->sig; - out.addTag(ret); +inline Event* copyEvent(Event* event, Module& out) { + auto* ret = new Event(); + ret->name = event->name; + ret->attribute = event->attribute; + ret->sig = event->sig; + out.addEvent(ret); return ret; } -inline ElementSegment* copyElementSegment(const ElementSegment* segment, - Module& out) { - auto copy = [&](std::unique_ptr&& ret) { - ret->name = segment->name; - ret->hasExplicitName = segment->hasExplicitName; - ret->type = segment->type; - ret->data.reserve(segment->data.size()); - for (auto* item : segment->data) { - ret->data.push_back(ExpressionManipulator::copy(item, out)); - } - - return out.addElementSegment(std::move(ret)); - }; - - if (segment->table.isNull()) { - return copy(std::make_unique()); - } else { - auto offset = ExpressionManipulator::copy(segment->offset, out); - return copy(std::make_unique(segment->table, offset)); - } -} - -inline Table* copyTable(const Table* table, Module& out) { - auto ret = std::make_unique
(); - ret->name = table->name; - ret->hasExplicitName = table->hasExplicitName; - ret->type = table->type; - ret->module = table->module; - ret->base = table->base; - - ret->initial = table->initial; - ret->max = table->max; - - return out.addTable(std::move(ret)); -} - inline void copyModule(const Module& in, Module& out) { // we use names throughout, not raw pointers, so simple copying is fine // for everything *but* expressions @@ -118,16 +82,13 @@ for (auto& curr : in.globals) { copyGlobal(curr.get(), out); } - for (auto& curr : in.tags) { - copyTag(curr.get(), out); - } - for (auto& curr : in.elementSegments) { - copyElementSegment(curr.get(), out); + for (auto& curr : in.events) { + copyEvent(curr.get(), out); } - for (auto& curr : in.tables) { - copyTable(curr.get(), out); + out.table = in.table; + for (auto& segment : out.table.segments) { + segment.offset = ExpressionManipulator::copy(segment.offset, out); } - out.memory = in.memory; for (auto& segment : out.memory.segments) { segment.offset = ExpressionManipulator::copy(segment.offset, out); @@ -135,8 +96,6 @@ out.start = in.start; out.userSections = in.userSections; out.debugInfoFileNames = in.debugInfoFileNames; - out.features = in.features; - out.typeNames = in.typeNames; } inline void clearModule(Module& wasm) { @@ -152,10 +111,10 @@ // call this redirect all of its uses. template inline void renameFunctions(Module& wasm, T& map) { // Update the function itself. - for (auto& [oldName, newName] : map) { - if (Function* F = wasm.getFunctionOrNull(oldName)) { - assert(!wasm.getFunctionOrNull(newName) || F->name == newName); - F->name = newName; + for (auto& pair : map) { + if (Function* F = wasm.getFunctionOrNull(pair.first)) { + assert(!wasm.getFunctionOrNull(pair.second) || F->name == pair.second); + F->name = pair.second; } } wasm.updateMaps(); @@ -167,7 +126,11 @@ } }; maybeUpdate(wasm.start); - ElementUtils::iterAllElementFunctionNames(&wasm, maybeUpdate); + for (auto& segment : wasm.table.segments) { + for (auto& name : segment.data) { + maybeUpdate(name); + } + } for (auto& exp : wasm.exports) { if (exp->kind == ExternalKind::Function) { maybeUpdate(exp->value); @@ -206,40 +169,14 @@ } template inline void iterImportedTables(Module& wasm, T visitor) { - for (auto& import : wasm.tables) { - if (import->imported()) { - visitor(import.get()); - } + if (wasm.table.exists && wasm.table.imported()) { + visitor(&wasm.table); } } template inline void iterDefinedTables(Module& wasm, T visitor) { - for (auto& import : wasm.tables) { - if (!import->imported()) { - visitor(import.get()); - } - } -} - -template -inline void iterTableSegments(Module& wasm, Name table, T visitor) { - // Just a precaution so that we don't iterate over passive elem segments by - // accident - assert(table.is() && "Table name must not be null"); - - for (auto& segment : wasm.elementSegments) { - if (segment->table == table) { - visitor(segment.get()); - } - } -} - -template -inline void iterActiveElementSegments(Module& wasm, T visitor) { - for (auto& segment : wasm.elementSegments) { - if (segment->table.is()) { - visitor(segment.get()); - } + if (wasm.table.exists && !wasm.table.imported()) { + visitor(&wasm.table); } } @@ -276,16 +213,16 @@ } } -template inline void iterImportedTags(Module& wasm, T visitor) { - for (auto& import : wasm.tags) { +template inline void iterImportedEvents(Module& wasm, T visitor) { + for (auto& import : wasm.events) { if (import->imported()) { visitor(import.get()); } } } -template inline void iterDefinedTags(Module& wasm, T visitor) { - for (auto& import : wasm.tags) { +template inline void iterDefinedEvents(Module& wasm, T visitor) { + for (auto& import : wasm.events) { if (!import->imported()) { visitor(import.get()); } @@ -297,24 +234,18 @@ iterImportedTables(wasm, visitor); iterImportedGlobals(wasm, visitor); iterImportedFunctions(wasm, visitor); - iterImportedTags(wasm, visitor); + iterImportedEvents(wasm, visitor); } // Helper class for performing an operation on all the functions in the module, // in parallel, with an Info object for each one that can contain results of // some computation that the operation performs. -// The operation performed should not modify the wasm module in any way, by -// default - otherwise, set the Mutability to Mutable. (This is not enforced at -// compile time - TODO find a way - but at runtime in pass-debug mode it is -// checked.) -template using DefaultMap = std::map; -template class MapT = DefaultMap> -struct ParallelFunctionAnalysis { +// The operation performend should not modify the wasm module in any way. +// TODO: enforce this +template struct ParallelFunctionAnalysis { Module& wasm; - typedef MapT Map; + typedef std::map Map; Map map; typedef std::function Func; @@ -335,7 +266,7 @@ struct Mapper : public WalkerPass> { bool isFunctionParallel() override { return true; } - bool modifiesBinaryenIR() override { return Mut; } + bool modifiesBinaryenIR() override { return false; } Mapper(Module& module, Map& map, Func work) : module(module), map(map), work(work) {} @@ -416,7 +347,9 @@ map.swap(analysis.map); // Find what is called by what. - for (auto& [func, info] : map) { + for (auto& pair : map) { + auto* func = pair.first; + auto& info = pair.second; for (auto* target : info.callsTo) { map[target].calledBy.insert(func); } @@ -459,20 +392,197 @@ } }; -// Helper function for collecting all the non-basic heap types used in the -// module, i.e. the types that would appear in the type section. -std::vector collectHeapTypes(Module& wasm); - -struct IndexedHeapTypes { - std::vector types; - std::unordered_map indices; -}; +// Helper function for collecting all the types that are declared in a module, +// which means the HeapTypes (that are non-basic, that is, not eqref etc., which +// do not need to be defined). +// +// Used when emitting or printing a module to give HeapTypes canonical +// indices. HeapTypes are sorted in order of decreasing frequency to minize the +// size of their collective encoding. Both a vector mapping indices to +// HeapTypes and a map mapping HeapTypes to indices are produced. +inline void collectHeapTypes(Module& wasm, + std::vector& types, + std::unordered_map& typeIndices) { + struct Counts : public std::unordered_map { + bool isRelevant(Type type) { + if (type.isRef()) { + return !type.getHeapType().isBasic(); + } + return type.isRtt(); + } + void note(HeapType type) { (*this)[type]++; } + void maybeNote(Type type) { + if (isRelevant(type)) { + note(type.getHeapType()); + } + } + }; + + // Collect the type use counts for a single function + auto updateCounts = [&](Function* func, Counts& counts) { + if (func->imported()) { + return; + } + struct TypeCounter + : PostWalker> { + Counts& counts; + + TypeCounter(Counts& counts) : counts(counts) {} + + void visitExpression(Expression* curr) { + if (auto* call = curr->dynCast()) { + counts.note(call->sig); + } else if (curr->is()) { + counts.maybeNote(curr->type); + } else if (curr->is() || curr->is()) { + counts.note(curr->type.getRtt().heapType); + } else if (auto* get = curr->dynCast()) { + counts.maybeNote(get->ref->type); + } else if (auto* set = curr->dynCast()) { + counts.maybeNote(set->ref->type); + } else if (Properties::isControlFlowStructure(curr)) { + counts.maybeNote(curr->type); + if (curr->type.isTuple()) { + // TODO: Allow control flow to have input types as well + counts.note(Signature(Type::none, curr->type)); + } + } + } + }; + TypeCounter(counts).walk(func->body); + }; + + ModuleUtils::ParallelFunctionAnalysis analysis(wasm, updateCounts); + + // Collect all the counts. + Counts counts; + for (auto& curr : wasm.functions) { + counts.note(curr->sig); + for (auto type : curr->vars) { + counts.maybeNote(type); + if (type.isTuple()) { + for (auto t : type) { + counts.maybeNote(t); + } + } + } + } + for (auto& curr : wasm.events) { + counts.note(curr->sig); + } + for (auto& curr : wasm.globals) { + counts.maybeNote(curr->type); + } + for (auto& pair : analysis.map) { + Counts& functionCounts = pair.second; + for (auto& innerPair : functionCounts) { + counts[innerPair.first] += innerPair.second; + } + } + // A generic utility to traverse the child types of a type. + // TODO: work with tlively to refactor this to a shared place + auto walkRelevantChildren = [&](HeapType type, + std::function callback) { + auto callIfRelevant = [&](Type type) { + if (counts.isRelevant(type)) { + callback(type.getHeapType()); + } + }; + if (type.isSignature()) { + auto sig = type.getSignature(); + for (Type type : {sig.params, sig.results}) { + for (auto element : type) { + callIfRelevant(element); + } + } + } else if (type.isArray()) { + callIfRelevant(type.getArray().element.type); + } else if (type.isStruct()) { + auto fields = type.getStruct().fields; + for (auto field : fields) { + callIfRelevant(field.type); + } + } + }; + // Recursively traverse each reference type, which may have a child type that + // is itself a reference type. This reflects an appearance in the binary + // format that is in the type section itself. + // As we do this we may find more and more types, as nested children of + // previous ones. Each such type will appear in the type section once, so + // we just need to visit it once. + // TODO: handle struct and array fields + std::unordered_set newTypes; + for (auto& pair : counts) { + newTypes.insert(pair.first); + } + while (!newTypes.empty()) { + auto iter = newTypes.begin(); + auto type = *iter; + newTypes.erase(iter); + walkRelevantChildren(type, [&](HeapType type) { + if (!counts.count(type)) { + newTypes.insert(type); + } + counts.note(type); + }); + } + + // We must sort all the dependencies of a type before it. For example, + // (func (param (ref (func)))) must appear after (func). To do that, find the + // depth of dependencies of each type. For example, if A depends on B + // which depends on C, then A's depth is 2, B's is 1, and C's is 0 (assuming + // no other dependencies). + Counts depthOfDependencies; + std::unordered_map> isDependencyOf; + // To calculate the depth of dependencies, we'll do a flow analysis, visiting + // each type as we find out new things about it. + std::set toVisit; + for (auto& pair : counts) { + auto type = pair.first; + depthOfDependencies[type] = 0; + toVisit.insert(type); + walkRelevantChildren(type, [&](HeapType childType) { + isDependencyOf[childType].insert(type); // XXX flip? + }); + } + while (!toVisit.empty()) { + auto iter = toVisit.begin(); + auto type = *iter; + toVisit.erase(iter); + // Anything that depends on this has a depth of dependencies equal to this + // type's, plus this type itself. + auto newDepth = depthOfDependencies[type] + 1; + if (newDepth > counts.size()) { + Fatal() << "Cyclic types detected, cannot sort them."; + } + for (auto& other : isDependencyOf[type]) { + if (depthOfDependencies[other] < newDepth) { + // We found something new to propagate. + depthOfDependencies[other] = newDepth; + toVisit.insert(other); + } + } + } + // Sort by frequency and then simplicity, and also keeping every type + // before things that depend on it. + std::vector> sorted(counts.begin(), counts.end()); + std::sort(sorted.begin(), sorted.end(), [&](auto a, auto b) { + if (depthOfDependencies[a.first] != depthOfDependencies[b.first]) { + return depthOfDependencies[a.first] < depthOfDependencies[b.first]; + } + if (a.second != b.second) { + return a.second > b.second; + } + return a.first < b.first; + }); + for (Index i = 0; i < sorted.size(); ++i) { + typeIndices[sorted[i].first] = i; + types.push_back(sorted[i].first); + } +} -// Similar to `collectHeapTypes`, but provides fast lookup of the index for each -// type as well. Also orders the types to be valid and sorts the types by -// frequency of use to minimize code size. -IndexedHeapTypes getOptimizedIndexedHeapTypes(Module& wasm); +} // namespace ModuleUtils -} // namespace wasm::ModuleUtils +} // namespace wasm #endif // wasm_ir_module_h diff -Nru binaryen-108/src/ir/names.cpp binaryen-99/src/ir/names.cpp --- binaryen-108/src/ir/names.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/names.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/names.h" -#include - -namespace wasm::Names { - -// Reserved words in JS that we will not emit up to size 4 - size 5 and above -// would mean we use an astronomical number of symbols, which is not realistic -// anyhow. -static std::unordered_set reserved = {"do", - "if", - "in", - "for", - "new", - "try", - "var", - "env", - "let", - "case", - "else", - "enum", - "void", - "this", - "with"}; - -// Possible initial letters. -static std::string validInitialChars = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"; - -// Possible later letters. -static std::string validLaterChars = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$0123456789"; - -std::string MinifiedNameGenerator::getName() { - std::string name; - do { - size_t n = state++; - std::stringstream ss; - ss << validInitialChars[n % validInitialChars.size()]; - n /= validInitialChars.size(); - // `m` is the number of `state` counts each of the `n` represents. - size_t m = validInitialChars.size(); - while (n) { - if (n % (validLaterChars.size() + 1) == 0) { - // Skip states that contain zeros in later positions. - state += m; - ++n; - } - ss << validLaterChars[(n % (validLaterChars.size() + 1)) - 1]; - n /= (validLaterChars.size() + 1); - m *= (validLaterChars.size() + 1); - } - name = ss.str(); - } while (reserved.count(name)); - return name; -} - -} // namespace wasm::Names diff -Nru binaryen-108/src/ir/names.h binaryen-99/src/ir/names.h --- binaryen-108/src/ir/names.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/names.h 2021-01-07 20:01:06.000000000 +0000 @@ -13,28 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef wasm_ir_names_h #define wasm_ir_names_h #include "wasm.h" -namespace wasm::Names { +namespace wasm { + +namespace Names { // Add explicit names for function locals not yet named, and do not // modify existing names inline void ensureNames(Function* func) { std::unordered_set seen; - for (auto& [_, name] : func->localNames) { - seen.insert(name); + for (auto& pair : func->localNames) { + seen.insert(pair.second); } Index nameIndex = seen.size(); for (Index i = 0; i < func->getNumLocals(); i++) { if (!func->hasLocalName(i)) { while (1) { auto name = Name::fromInt(nameIndex++); - if (seen.emplace(name).second) { + if (seen.count(name) == 0) { func->localNames[i] = name; func->localIndices[name] = i; + seen.insert(name); break; } } @@ -44,7 +48,8 @@ // Given a root of a name, finds a valid name with perhaps a number appended // to it, by calling a function to check if a name is valid. -inline Name getValidName(Name root, std::function check) { +inline Name +getValidName(Module& module, Name root, std::function check) { if (check(root)) { return root; } @@ -60,38 +65,24 @@ } inline Name getValidExportName(Module& module, Name root) { - return getValidName(root, - [&](Name test) { return !module.getExportOrNull(test); }); + return getValidName( + module, root, [&](Name test) { return !module.getExportOrNull(test); }); } inline Name getValidGlobalName(Module& module, Name root) { - return getValidName(root, - [&](Name test) { return !module.getGlobalOrNull(test); }); + return getValidName( + module, root, [&](Name test) { return !module.getGlobalOrNull(test); }); } inline Name getValidFunctionName(Module& module, Name root) { return getValidName( - root, [&](Name test) { return !module.getFunctionOrNull(test); }); + module, root, [&](Name test) { return !module.getFunctionOrNull(test); }); } -inline Name getValidTableName(Module& module, Name root) { - return getValidName(root, - [&](Name test) { return !module.getTableOrNull(test); }); -} -inline Name getValidTagName(Module& module, Name root) { - return getValidName(root, - [&](Name test) { return !module.getTagOrNull(test); }); -} -inline Name getValidElementSegmentName(Module& module, Name root) { +inline Name getValidEventName(Module& module, Name root) { return getValidName( - root, [&](Name test) { return !module.getElementSegmentOrNull(test); }); + module, root, [&](Name test) { return !module.getEventOrNull(test); }); } -class MinifiedNameGenerator { - size_t state = 0; - -public: - // Get a fresh minified name. - std::string getName(); -}; +} // namespace Names -} // namespace wasm::Names +} // namespace wasm #endif // wasm_ir_names_h diff -Nru binaryen-108/src/ir/numbering.h binaryen-99/src/ir/numbering.h --- binaryen-108/src/ir/numbering.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/numbering.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_numberings_h -#define wasm_ir_numberings_h - -#include "ir/properties.h" -#include "wasm.h" - -namespace wasm { - -// General value numbering: Returns a number for an expression. Expressions with -// the same number must be identical in value; expressions with different values -// might happen to be identical at runtime. -class ValueNumbering { -public: - // Get the value numbering of an arbitrary expression. - Index getValue(Expression* expr) { - if (Properties::isConstantExpression(expr)) { - return getValue(Properties::getLiterals(expr)); - } else { - auto iter = expressionValues.find(expr); - if (iter != expressionValues.end()) { - return iter->second; - } - // TODO: full GVN to check for different expressions with the same value. - return expressionValues[expr] = getUniqueValue(); - } - } - - // Get the value numbering of an arbitrary set of constants. - Index getValue(Literals lit) { - auto iter = literalValues.find(lit); - if (iter != literalValues.end()) { - return iter->second; - } - return literalValues[lit] = getUniqueValue(); - } - - // Return a new unique value. Normally this is called internally, but there - // are also use cases for the user of the class to call this, when they want - // to get a new value that will not collide with any others. - Index getUniqueValue() { return nextValue++; } - -private: - Index nextValue = 0; - - // Cache the value numbers of literals and expressions. - std::unordered_map literalValues; - std::unordered_map expressionValues; -}; - -} // namespace wasm - -#endif // wasm_ir_numberings_h diff -Nru binaryen-108/src/ir/ordering.h binaryen-99/src/ir/ordering.h --- binaryen-108/src/ir/ordering.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/ordering.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_reorderer_h -#define wasm_ir_reorderer_h - -#include -#include - -namespace wasm { - -// -// Given two expressions that appear in a specific order - first and then -// second - this helper can create a sequence in which we return the value of -// the first. If the two expressions can be reordered, this simply returns -// -// (second, first) -// -// If side effects prevent that, it will use a local to save the value of the -// first, and return it at the end, -// -// (temp = first, second, temp) -// -Expression* getResultOfFirst(Expression* first, - Expression* second, - Function* func, - Module* wasm, - const PassOptions& passOptions) { - assert(first->type.isConcrete()); - - Builder builder(*wasm); - - if (EffectAnalyzer::canReorder(passOptions, *wasm, first, second)) { - return builder.makeSequence(second, first); - } - - auto type = first->type; - auto index = Builder::addVar(func, type); - return builder.makeBlock({builder.makeLocalSet(index, first), - second, - builder.makeLocalGet(index, type)}); -} - -} // namespace wasm - -#endif // wasm_ir_reorderer_h diff -Nru binaryen-108/src/ir/parents.h binaryen-99/src/ir/parents.h --- binaryen-108/src/ir/parents.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/parents.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,8 +17,6 @@ #ifndef wasm_ir_parents_h #define wasm_ir_parents_h -#include "parsing.h" - namespace wasm { struct Parents { diff -Nru binaryen-108/src/ir/possible-constant.h binaryen-99/src/ir/possible-constant.h --- binaryen-108/src/ir/possible-constant.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/possible-constant.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,175 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_possible_constant_h -#define wasm_ir_possible_constant_h - -#include - -#include "ir/properties.h" -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm { - -// Represents data about what constant values are possible in a particular -// place. There may be no values, or one, or many, or if a non-constant value is -// possible, then all we can say is that the value is "unknown" - it can be -// anything. The values can either be literal values (Literal) or the names of -// immutable globals (Name). -// -// Currently this just looks for a single constant value, and even two constant -// values are treated as unknown. It may be worth optimizing more than that TODO -struct PossibleConstantValues { -private: - // No possible value. - struct None : public std::monostate {}; - - // Many possible values, and so this represents unknown data: we cannot infer - // anything there. - struct Many : public std::monostate {}; - - using Variant = std::variant; - Variant value; - -public: - PossibleConstantValues() : value(None()) {} - - // Notes the contents of an expression and update our internal knowledge based - // on it and all previous values noted. - void note(Expression* expr, Module& wasm) { - // If this is a constant literal value, note that. - if (Properties::isConstantExpression(expr)) { - note(Properties::getLiteral(expr)); - return; - } - - // If this is an immutable global that we get, note that. - if (auto* get = expr->dynCast()) { - auto* global = wasm.getGlobal(get->name); - if (global->mutable_ == Immutable) { - note(get->name); - return; - } - } - - // Otherwise, this is not something we can reason about. - noteUnknown(); - } - - // Note either a Literal or a Name. - template void note(T curr) { - if (std::get_if(&value)) { - // This is the first value. - value = curr; - return; - } - - if (std::get_if(&value)) { - // This was already representing multiple values; nothing changes. - return; - } - - // This is a subsequent value. Check if it is different from all previous - // ones. - if (Variant(curr) != value) { - noteUnknown(); - } - } - - // Notes a value that is unknown - it can be anything. We have failed to - // identify a constant value here. - void noteUnknown() { value = Many(); } - - // Combine the information in a given PossibleConstantValues to this one. This - // is the same as if we have called note*() on us with all the history of - // calls to that other object. - // - // Returns whether we changed anything. - bool combine(const PossibleConstantValues& other) { - if (std::get_if(&other.value)) { - return false; - } - - if (std::get_if(&value)) { - value = other.value; - return true; - } - - if (std::get_if(&value)) { - return false; - } - - if (other.value != value) { - value = Many(); - return true; - } - - return false; - } - - // Check if all the values are identical and constant. - bool isConstant() const { - return !std::get_if(&value) && !std::get_if(&value); - } - - bool isConstantLiteral() const { return std::get_if(&value); } - - bool isConstantGlobal() const { return std::get_if(&value); } - - // Returns the single constant value. - Literal getConstantLiteral() const { - assert(isConstant()); - return std::get(value); - } - - Name getConstantGlobal() const { - assert(isConstant()); - return std::get(value); - } - - // Assuming we have a single value, make an expression containing that value. - Expression* makeExpression(Module& wasm) { - Builder builder(wasm); - if (isConstantLiteral()) { - return builder.makeConstantExpression(getConstantLiteral()); - } else { - auto name = getConstantGlobal(); - return builder.makeGlobalGet(name, wasm.getGlobal(name)->type); - } - } - - // Returns whether we have ever noted a value. - bool hasNoted() const { return !std::get_if(&value); } - - void dump(std::ostream& o) { - o << '['; - if (!hasNoted()) { - o << "unwritten"; - } else if (!isConstant()) { - o << "unknown"; - } else if (isConstantLiteral()) { - o << getConstantLiteral(); - } else if (isConstantGlobal()) { - o << '$' << getConstantGlobal(); - } - o << ']'; - } -}; - -} // namespace wasm - -#endif // wasm_ir_possible_constant_h diff -Nru binaryen-108/src/ir/properties.cpp binaryen-99/src/ir/properties.cpp --- binaryen-108/src/ir/properties.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/properties.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/properties.h" -#include "wasm-traversal.h" - -namespace wasm::Properties { - -bool isGenerative(Expression* curr, FeatureSet features) { - // Practically no wasm instructions are generative. Exceptions occur only in - // GC atm. - if (!features.hasGC()) { - return false; - } - - struct Scanner : public PostWalker { - bool generative = false; - void visitStructNew(StructNew* curr) { generative = true; } - void visitArrayNew(ArrayNew* curr) { generative = true; } - void visitArrayInit(ArrayInit* curr) { generative = true; } - } scanner; - scanner.walk(curr); - return scanner.generative; -} - -} // namespace wasm::Properties diff -Nru binaryen-108/src/ir/properties.h binaryen-99/src/ir/properties.h --- binaryen-108/src/ir/properties.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/properties.h 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,9 @@ #include "ir/match.h" #include "wasm.h" -namespace wasm::Properties { +namespace wasm { + +namespace Properties { inline bool emitsBoolean(Expression* curr) { if (auto* unary = curr->dynCast()) { @@ -67,27 +69,24 @@ curr->is(); } -// Check if an expression is a control flow construct with a name, which implies -// it may have breaks or delegates to it. +// Check if an expression is a control flow construct with a name, +// which implies it may have breaks to it. inline bool isNamedControlFlow(Expression* curr) { if (auto* block = curr->dynCast()) { return block->name.is(); } else if (auto* loop = curr->dynCast()) { return loop->name.is(); - } else if (auto* try_ = curr->dynCast()) { - return try_->name.is(); } return false; } // A constant expression is something like a Const: it has a fixed value known // at compile time, and passes that propagate constants can try to propagate it. -// Constant expressions are also allowed in global initializers in wasm. Also -// when two constant expressions compare equal at compile time, their values at -// runtime will be equal as well. +// Constant expressions are also allowed in global initializers in wasm. // TODO: look into adding more things here like RttCanon. inline bool isSingleConstantExpression(const Expression* curr) { - return curr->is() || curr->is() || curr->is(); + return curr->is() || curr->is() || curr->is() || + (curr->is() && curr->cast()->value->is()); } inline bool isConstantExpression(const Expression* curr) { @@ -105,10 +104,6 @@ return false; } -inline bool isBranch(const Expression* curr) { - return curr->is() || curr->is() || curr->is(); -} - inline Literal getLiteral(const Expression* curr) { if (auto* c = curr->dynCast()) { return c->value; @@ -145,12 +140,6 @@ if (curr->type != Type::i32) { return nullptr; } - if (auto* unary = curr->dynCast()) { - if (unary->op == ExtendS8Int32 || unary->op == ExtendS16Int32) { - return unary->value; - } - return nullptr; - } using namespace Match; int32_t leftShift = 0, rightShift = 0; Expression* extended = nullptr; @@ -167,19 +156,8 @@ // gets the size of the sign-extended value inline Index getSignExtBits(Expression* curr) { assert(curr->type == Type::i32); - if (auto* unary = curr->dynCast()) { - switch (unary->op) { - case ExtendS8Int32: - return 8; - case ExtendS16Int32: - return 16; - default: - WASM_UNREACHABLE("invalid unary operation"); - } - } else { - auto* rightShift = curr->cast()->right; - return 32 - Bits::getEffectiveShifts(rightShift); - } + auto* rightShift = curr->cast()->right; + return 32 - Bits::getEffectiveShifts(rightShift); } // Check if an expression is almost a sign-extend: perhaps the inner shift @@ -239,20 +217,9 @@ // and other operations that receive a value and let it flow through them. If // there is no value falling through, returns the node itself (as that is the // value that trivially falls through, with 0 steps in the middle). -// -// Note that this returns the value that would fall through if one does in fact -// do so. For example, the final element in a block may not fall through if we -// hit a return or a trap or an exception is thrown before we get there. -// -// This method returns the 'immediate' fallthrough, that is, the immediate -// child of this expression. See getFallthrough for a method that looks all the -// way to the final value falling through, potentially through multiple -// intermediate expressions. -// -// TODO: Receive a Module instead of FeatureSet, to pass to EffectAnalyzer? -inline Expression* getImmediateFallthrough(Expression* curr, - const PassOptions& passOptions, - Module& module) { +inline Expression* getFallthrough(Expression* curr, + const PassOptions& passOptions, + FeatureSet features) { // If the current node is unreachable, there is no value // falling through. if (curr->type == Type::unreachable) { @@ -260,91 +227,36 @@ } if (auto* set = curr->dynCast()) { if (set->isTee()) { - return set->value; + return getFallthrough(set->value, passOptions, features); } } else if (auto* block = curr->dynCast()) { // if no name, we can't be broken to, and then can look at the fallthrough if (!block->name.is() && block->list.size() > 0) { - return block->list.back(); + return getFallthrough(block->list.back(), passOptions, features); } } else if (auto* loop = curr->dynCast()) { - return loop->body; + return getFallthrough(loop->body, passOptions, features); } else if (auto* iff = curr->dynCast()) { if (iff->ifFalse) { // Perhaps just one of the two actually returns. if (iff->ifTrue->type == Type::unreachable) { - return iff->ifFalse; + return getFallthrough(iff->ifFalse, passOptions, features); } else if (iff->ifFalse->type == Type::unreachable) { - return iff->ifTrue; + return getFallthrough(iff->ifTrue, passOptions, features); } } } else if (auto* br = curr->dynCast()) { if (br->condition && br->value) { - return br->value; + return getFallthrough(br->value, passOptions, features); } } else if (auto* tryy = curr->dynCast()) { - if (!EffectAnalyzer(passOptions, module, tryy->body).throws()) { - return tryy->body; + if (!EffectAnalyzer(passOptions, features, tryy->body).throws) { + return getFallthrough(tryy->body, passOptions, features); } - } else if (auto* as = curr->dynCast()) { - return as->ref; - } else if (auto* as = curr->dynCast()) { - return as->value; - } else if (auto* br = curr->dynCast()) { - return br->ref; } return curr; } -// Similar to getImmediateFallthrough, but looks through multiple children to -// find the final value that falls through. -inline Expression* getFallthrough(Expression* curr, - const PassOptions& passOptions, - Module& module) { - while (1) { - auto* next = getImmediateFallthrough(curr, passOptions, module); - if (next == curr) { - return curr; - } - curr = next; - } -} - -inline Index getNumChildren(Expression* curr) { - Index ret = 0; - -#define DELEGATE_ID curr->_id - -#define DELEGATE_START(id) \ - auto* cast = curr->cast(); \ - WASM_UNUSED(cast); - -#define DELEGATE_GET_FIELD(id, field) cast->field - -#define DELEGATE_FIELD_CHILD(id, field) ret++; - -#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field) \ - if (cast->field) { \ - ret++; \ - } - -#define DELEGATE_FIELD_INT(id, field) -#define DELEGATE_FIELD_INT_ARRAY(id, field) -#define DELEGATE_FIELD_LITERAL(id, field) -#define DELEGATE_FIELD_NAME(id, field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) -#define DELEGATE_FIELD_TYPE(id, field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) -#define DELEGATE_FIELD_ADDRESS(id, field) - -#include "wasm-delegations-fields.def" - - return ret; -} - // Returns whether the resulting value here must fall through without being // modified. For example, a tee always does so. That is, this returns false if // and only if the return value may have some computation performed on it to @@ -364,76 +276,8 @@ curr->is(); } -inline bool canEmitSelectWithArms(Expression* ifTrue, Expression* ifFalse) { - // A select only allows a single value in its arms in the spec: - // https://webassembly.github.io/spec/core/valid/instructions.html#xref-syntax-instructions-syntax-instr-parametric-mathsf-select-t-ast - return ifTrue->type.isSingle() && ifFalse->type.isSingle(); -} - -// A "generative" expression is one that can generate different results for the -// same inputs, and that difference is *not* explained by other expressions that -// interact with this one. This is an intrinsic/internal property of the -// expression. -// -// To see the issue more concretely, consider these: -// -// x = load(100); -// .. -// y = load(100); -// -// versus -// -// x = struct.new(); -// .. -// y = struct.new(); -// -// Are x and y identical in both cases? For loads, we can look at the code -// in ".." to see: if there are no possible stores to memory, then the -// result is identical (and we have EffectAnalyzer for that). For the GC -// allocations, though, it doesn't matter what is in "..": there is nothing -// in the wasm that we can check to find out if the results are the same or -// not. (In fact, in this case they are always not the same.) So the -// generativity is "intrinsic" to the expression and it is because each call to -// struct.new generates a new value. -// -// Thus, loads are nondeterministic but not generative, while GC allocations -// are in fact generative. Note that "generative" need not mean "allocation" as -// if wasm were to add "get current time" or "get a random number" instructions -// then those would also be generative - generating a new current time value or -// a new random number on each execution, respectively. -// -// * Note that NaN nondeterminism is ignored here. It is a valid wasm -// implementation to have deterministic NaN behavior, and we optimize under -// that simplifying assumption. -// * Note that calls are ignored here. In theory this concept could be defined -// either way for them - that is, we could potentially define them as -// generative, as they might contain such an instruction, or we could define -// this property as only looking at code in the current function. We choose -// the latter because calls are already handled best in other manners (using -// EffectAnalyzer). -// -bool isGenerative(Expression* curr, FeatureSet features); - -inline bool isValidInConstantExpression(Expression* expr, FeatureSet features) { - if (isSingleConstantExpression(expr) || expr->is() || - expr->is() || expr->is() || expr->is() || - expr->is() || expr->is() || expr->is()) { - return true; - } - - if (features.hasExtendedConst()) { - if (expr->is()) { - auto bin = static_cast(expr); - if (bin->op == AddInt64 || bin->op == SubInt64 || bin->op == MulInt64 || - bin->op == AddInt32 || bin->op == SubInt32 || bin->op == MulInt32) { - return true; - } - } - } - - return false; -} +} // namespace Properties -} // namespace wasm::Properties +} // namespace wasm #endif // wasm_ir_properties_h diff -Nru binaryen-108/src/ir/ReFinalize.cpp binaryen-99/src/ir/ReFinalize.cpp --- binaryen-108/src/ir/ReFinalize.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/ReFinalize.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -44,19 +44,16 @@ curr->type = Type::none; return; } + // Get the least upper bound type of the last element and all branch return + // values + curr->type = curr->list.back()->type; if (curr->name.is()) { - auto iter = breakTypes.find(curr->name); - if (iter != breakTypes.end()) { - // Set the type to be a supertype of the branch types and the flowed-out - // type. TODO: calculate proper LUBs to compute a new correct type in this - // situation. - auto& types = iter->second; - types.insert(curr->list.back()->type); - curr->type = Type::getLeastUpperBound(types); + auto iter = breakValues.find(curr->name); + if (iter != breakValues.end()) { + curr->type = Type::getLeastUpperBound(curr->type, iter->second); return; } } - curr->type = curr->list.back()->type; if (curr->type == Type::unreachable) { return; } @@ -115,6 +112,7 @@ void ReFinalize::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { curr->finalize(); } +void ReFinalize::visitPrefetch(Prefetch* curr) { curr->finalize(); } void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); } void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); } void ReFinalize::visitMemoryCopy(MemoryCopy* curr) { curr->finalize(); } @@ -128,20 +126,24 @@ void ReFinalize::visitMemorySize(MemorySize* curr) { curr->finalize(); } void ReFinalize::visitMemoryGrow(MemoryGrow* curr) { curr->finalize(); } void ReFinalize::visitRefNull(RefNull* curr) { curr->finalize(); } -void ReFinalize::visitRefIs(RefIs* curr) { curr->finalize(); } +void ReFinalize::visitRefIsNull(RefIsNull* curr) { curr->finalize(); } void ReFinalize::visitRefFunc(RefFunc* curr) { // TODO: should we look up the function and update the type from there? This // could handle a change to the function's type, but is also not really what // this class has been meant to do. } void ReFinalize::visitRefEq(RefEq* curr) { curr->finalize(); } -void ReFinalize::visitTableGet(TableGet* curr) { curr->finalize(); } -void ReFinalize::visitTableSet(TableSet* curr) { curr->finalize(); } -void ReFinalize::visitTableSize(TableSize* curr) { curr->finalize(); } -void ReFinalize::visitTableGrow(TableGrow* curr) { curr->finalize(); } void ReFinalize::visitTry(Try* curr) { curr->finalize(); } void ReFinalize::visitThrow(Throw* curr) { curr->finalize(); } void ReFinalize::visitRethrow(Rethrow* curr) { curr->finalize(); } +void ReFinalize::visitBrOnExn(BrOnExn* curr) { + curr->finalize(); + if (curr->exnref->type == Type::unreachable) { + replaceUntaken(curr->exnref, nullptr); + } else { + updateBreakValueType(curr->name, curr->sent); + } +} void ReFinalize::visitNop(Nop* curr) { curr->finalize(); } void ReFinalize::visitUnreachable(Unreachable* curr) { curr->finalize(); } void ReFinalize::visitPop(Pop* curr) { curr->finalize(); } @@ -152,12 +154,12 @@ void ReFinalize::visitCallRef(CallRef* curr) { curr->finalize(); } void ReFinalize::visitRefTest(RefTest* curr) { curr->finalize(); } void ReFinalize::visitRefCast(RefCast* curr) { curr->finalize(); } -void ReFinalize::visitBrOn(BrOn* curr) { +void ReFinalize::visitBrOnCast(BrOnCast* curr) { curr->finalize(); if (curr->type == Type::unreachable) { replaceUntaken(curr->ref, nullptr); } else { - updateBreakValueType(curr->name, curr->getSentType()); + updateBreakValueType(curr->name, curr->getCastType()); } } void ReFinalize::visitRttCanon(RttCanon* curr) { curr->finalize(); } @@ -166,17 +168,14 @@ void ReFinalize::visitStructGet(StructGet* curr) { curr->finalize(); } void ReFinalize::visitStructSet(StructSet* curr) { curr->finalize(); } void ReFinalize::visitArrayNew(ArrayNew* curr) { curr->finalize(); } -void ReFinalize::visitArrayInit(ArrayInit* curr) { curr->finalize(); } void ReFinalize::visitArrayGet(ArrayGet* curr) { curr->finalize(); } void ReFinalize::visitArraySet(ArraySet* curr) { curr->finalize(); } void ReFinalize::visitArrayLen(ArrayLen* curr) { curr->finalize(); } -void ReFinalize::visitArrayCopy(ArrayCopy* curr) { curr->finalize(); } -void ReFinalize::visitRefAs(RefAs* curr) { curr->finalize(); } void ReFinalize::visitFunction(Function* curr) { // we may have changed the body from unreachable to none, which might be bad // if the function has a return value - if (curr->getResults() != Type::none && curr->body->type == Type::none) { + if (curr->sig.results != Type::none && curr->body->type == Type::none) { Builder builder(*getModule()); curr->body = builder.blockify(curr->body, builder.makeUnreachable()); } @@ -185,16 +184,17 @@ void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); } void ReFinalize::visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); } void ReFinalize::visitTable(Table* curr) { WASM_UNREACHABLE("unimp"); } -void ReFinalize::visitElementSegment(ElementSegment* curr) { - WASM_UNREACHABLE("unimp"); -} void ReFinalize::visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); } -void ReFinalize::visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); } +void ReFinalize::visitEvent(Event* curr) { WASM_UNREACHABLE("unimp"); } void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); } void ReFinalize::updateBreakValueType(Name name, Type type) { if (type != Type::unreachable) { - breakTypes[name].insert(type); + if (breakValues.count(name) == 0) { + breakValues[name] = type; + } else { + breakValues[name] = Type::getLeastUpperBound(breakValues[name], type); + } } } diff -Nru binaryen-108/src/ir/stack-utils.cpp binaryen-99/src/ir/stack-utils.cpp --- binaryen-108/src/ir/stack-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/stack-utils.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -65,10 +65,10 @@ } params = Type(inputs); if (expr->type == Type::unreachable) { - kind = Polymorphic; + unreachable = true; results = Type::none; } else { - kind = Fixed; + unreachable = false; results = expr->type; } } @@ -83,6 +83,48 @@ }); } +bool StackSignature::satisfies(Signature sig) const { + if (sig.params.size() < params.size() || + sig.results.size() < results.size()) { + // Not enough values provided or too many produced + return false; + } + bool paramSuffixMatches = + std::equal(params.begin(), + params.end(), + sig.params.end() - params.size(), + [](const Type& consumed, const Type& provided) { + return Type::isSubType(provided, consumed); + }); + if (!paramSuffixMatches) { + return false; + } + bool resultSuffixMatches = + std::equal(results.begin(), + results.end(), + sig.results.end() - results.size(), + [](const Type& produced, const Type& expected) { + return Type::isSubType(produced, expected); + }); + if (!resultSuffixMatches) { + return false; + } + if (unreachable) { + // The unreachable can consume any additional provided params and produce + // any additional expected results, so we are done. + return true; + } + // Any additional provided params will pass through untouched, so they must be + // equivalent to the additional produced results. + return std::equal(sig.params.begin(), + sig.params.end() - params.size(), + sig.results.begin(), + sig.results.end() - results.size(), + [](const Type& produced, const Type& expected) { + return Type::isSubType(produced, expected); + }); +} + StackSignature& StackSignature::operator+=(const StackSignature& next) { assert(composes(next)); std::vector stack(results.begin(), results.end()); @@ -91,7 +133,7 @@ if (stack.size() >= required) { stack.resize(stack.size() - required); } else { - if (kind == Fixed) { + if (!unreachable) { // Prepend the unsatisfied params of `next` to the current params size_t unsatisfied = required - stack.size(); std::vector newParams(next.params.begin(), @@ -102,9 +144,9 @@ stack.clear(); } // Add stack values according to next's results - if (next.kind == Polymorphic) { + if (next.unreachable) { results = next.results; - kind = Polymorphic; + unreachable = true; } else { stack.insert(stack.end(), next.results.begin(), next.results.end()); results = Type(stack); @@ -118,141 +160,6 @@ return sig; } -bool StackSignature::isSubType(StackSignature a, StackSignature b) { - if (a.params.size() > b.params.size() || - a.results.size() > b.results.size()) { - // `a` consumes or produces more values than `b` can provides or expects. - return false; - } - if (a.kind == Fixed && b.kind == Polymorphic) { - // Non-polymorphic sequences cannot be typed as being polymorphic. - return false; - } - bool paramSuffixMatches = - std::equal(a.params.begin(), - a.params.end(), - b.params.end() - a.params.size(), - [](const Type& consumed, const Type& provided) { - return Type::isSubType(provided, consumed); - }); - if (!paramSuffixMatches) { - return false; - } - bool resultSuffixMatches = - std::equal(a.results.begin(), - a.results.end(), - b.results.end() - a.results.size(), - [](const Type& produced, const Type& expected) { - return Type::isSubType(produced, expected); - }); - if (!resultSuffixMatches) { - return false; - } - if (a.kind == Polymorphic) { - // The polymorphism can consume any additional provided params and produce - // any additional expected results, so we are done. - return true; - } - // Any additional provided params will pass through untouched, so they must be - // compatible with the additional produced results. - return std::equal(b.params.begin(), - b.params.end() - a.params.size(), - b.results.begin(), - b.results.end() - a.results.size(), - [](const Type& provided, const Type& expected) { - return Type::isSubType(provided, expected); - }); -} - -bool StackSignature::haveLeastUpperBound(StackSignature a, StackSignature b) { - // If a signature is polymorphic, the LUB could extend its params and results - // arbitrarily. Otherwise, the LUB must extend its params and results - // uniformly so that each additional param is a subtype of the corresponding - // additional result. - auto extensionCompatible = [](auto self, auto other) -> bool { - if (self.kind == Polymorphic) { - return true; - } - // If no extension, then no problem. - if (self.params.size() >= other.params.size() && - self.results.size() >= other.results.size()) { - return true; - } - auto extSize = other.params.size() - self.params.size(); - if (extSize != other.results.size() - self.results.size()) { - return false; - } - return std::equal(other.params.begin(), - other.params.begin() + extSize, - other.results.begin(), - other.results.begin() + extSize, - [](const Type& param, const Type& result) { - return Type::isSubType(param, result); - }); - }; - if (!extensionCompatible(a, b) || !extensionCompatible(b, a)) { - return false; - } - - auto valsCompatible = [](auto as, auto bs, auto compatible) -> bool { - // Canonicalize so the as are shorter and any unshared prefix is on bs. - if (bs.size() < as.size()) { - std::swap(as, bs); - } - // Check that shared values after the unshared prefix have are compatible. - size_t diff = bs.size() - as.size(); - for (size_t i = 0, shared = as.size(); i < shared; ++i) { - if (!compatible(as[i], bs[i + diff])) { - return false; - } - } - return true; - }; - - bool paramsOk = valsCompatible(a.params, b.params, [](Type a, Type b) { - assert(a == b && "TODO: calculate greatest lower bound to handle " - "contravariance correctly"); - return true; - }); - bool resultsOk = valsCompatible(a.results, b.results, [](Type a, Type b) { - return Type::getLeastUpperBound(a, b) != Type::none; - }); - return paramsOk && resultsOk; -} - -StackSignature StackSignature::getLeastUpperBound(StackSignature a, - StackSignature b) { - assert(haveLeastUpperBound(a, b)); - - auto combineVals = [](auto as, auto bs, auto combine) -> std::vector { - // Canonicalize so the as are shorter and any unshared prefix is on bs. - if (bs.size() < as.size()) { - std::swap(as, bs); - } - // Combine shared values after the unshared prefix. - size_t diff = bs.size() - as.size(); - std::vector vals(bs.begin(), bs.begin() + diff); - for (size_t i = 0, shared = as.size(); i < shared; ++i) { - vals.push_back(combine(as[i], bs[i + diff])); - } - return vals; - }; - - auto params = combineVals(a.params, b.params, [&](Type a, Type b) { - assert(a == b && "TODO: calculate greatest lower bound to handle " - "contravariance correctly"); - return a; - }); - - auto results = combineVals(a.results, b.results, [&](Type a, Type b) { - return Type::getLeastUpperBound(a, b); - }); - - Kind kind = - a.kind == Polymorphic && b.kind == Polymorphic ? Polymorphic : Fixed; - return StackSignature{Type(params), Type(results), kind}; -} - StackFlow::StackFlow(Block* block) { // Encapsulates the logic for treating the block and its children // uniformly. The end of the block is treated as if it consumed values @@ -265,10 +172,9 @@ for (auto* expr : block->list) { process(expr, StackSignature(expr)); } - auto kind = block->type == Type::unreachable ? StackSignature::Polymorphic - : StackSignature::Fixed; - Type params = block->type == Type::unreachable ? Type::none : block->type; - process(block, StackSignature(params, Type::none, kind)); + bool unreachable = block->type == Type::unreachable; + Type params = unreachable ? Type::none : block->type; + process(block, StackSignature(params, Type::none, unreachable)); }; // We need to make an initial pass through the block to figure out how many @@ -291,7 +197,7 @@ } // Handle unreachable or produce results - if (sig.kind == StackSignature::Polymorphic) { + if (sig.unreachable) { if (lastUnreachable) { producedByUnreachable[lastUnreachable] = produced; produced = 0; @@ -318,14 +224,13 @@ "Block inputs not yet supported"); // Unreachable instructions consume all available values - size_t consumed = sig.kind == StackSignature::Polymorphic + size_t consumed = sig.unreachable ? std::max(values.size(), sig.params.size()) : sig.params.size(); // We previously calculated how many values unreachable instructions produce - size_t produced = sig.kind == StackSignature::Polymorphic - ? producedByUnreachable[expr] - : sig.results.size(); + size_t produced = + sig.unreachable ? producedByUnreachable[expr] : sig.results.size(); srcs[expr] = std::vector(consumed); dests[expr] = std::vector(produced); @@ -379,7 +284,7 @@ } // Update the last unreachable instruction - if (sig.kind == StackSignature::Polymorphic) { + if (sig.unreachable) { assert(producedByUnreachable[lastUnreachable] == 0); lastUnreachable = expr; } @@ -397,9 +302,8 @@ for (auto& dest : exprDests->second) { results.push_back(dest.type); } - auto kind = expr->type == Type::unreachable ? StackSignature::Polymorphic - : StackSignature::Fixed; - return StackSignature(Type(params), Type(results), kind); + bool unreachable = expr->type == Type::unreachable; + return StackSignature(Type(params), Type(results), unreachable); } } // namespace wasm diff -Nru binaryen-108/src/ir/stack-utils.h binaryen-99/src/ir/stack-utils.h --- binaryen-108/src/ir/stack-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/stack-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -16,7 +16,55 @@ // // stack-utils.h: Utilities for manipulating and analyzing stack machine code in -// the form of Poppy IR. See src/passes/Poppify.cpp for Poppy IR documentation. +// the form of Poppy IR. +// +// Poppy IR represents stack machine code using normal Binaryen IR types by +// imposing the following constraints: +// +// 1. Function bodies and children of control flow (except If conditions) must +// be blocks. +// +// 2. Blocks may have any Expressions except for Pops as children. The sequence +// of instructions in a block follows the same validation rules as in +// WebAssembly. That means that any expression may have a concrete type, not +// just the final expression in the block. +// +// 3. All other children must be Pops, which are used to determine the input +// stack type of each instruction. Pops may not have `unreachable` type. +// +// 4. Only control flow structures and instructions that have polymorphic +// unreachable behavior in WebAssembly may have unreachable type. Blocks may +// be unreachable when they are not branch targets and when they have an +// unreachable child. Note that this means a block may be unreachable even +// if it would otherwise have a concrete type, unlike in Binaryen IR. +// +// For example, the following Binaryen IR Function: +// +// (func $foo (result i32) +// (i32.add +// (i32.const 42) +// (i32.const 5) +// ) +// ) +// +// would look like this in Poppy IR: +// +// (func $foo (result i32) +// (block +// (i32.const 42) +// (i32.const 5) +// (i32.add +// (i32.pop) +// (i32.pop) +// ) +// ) +// ) +// +// Notice that the sequence of instructions in the block is now identical to the +// sequence of instructions in raw WebAssembly. Also note that Poppy IR's +// validation rules are largely additional on top of the normal Binaryen IR +// validation rules, with the only exceptions being block body validation and +// block unreahchability rules. // #ifndef wasm_ir_stack_h @@ -40,12 +88,12 @@ } // namespace StackUtils // Stack signatures are like regular function signatures, but they are used to -// represent the stack parameters and results of arbitrary sequences of stack -// machine instructions. Stack signatures that represent instruction sequences -// including unreachable instructions are `Polymorphic` and otherwise they are -// `Fixed`. For example, the following instruction sequences both have params -// {i32, i32} and results {f32}, but sequence A is `Fixed` while sequence B is -// `Polymorphic.` +// represent the stack parameters and results of arbitrary sequences of stacky +// instructions. They have to record whether they cover an unreachable +// instruction because their composition takes into account the polymorphic +// results of unreachable instructions. For example, the following instruction +// sequences both have params {i32, i32} and results {f32}, but only sequence B +// is unreachable: // // A: // i32.add @@ -59,8 +107,8 @@ // // Notice that this distinction is important because sequence B can be the body // of the blocks below but sequence A cannot. In other words, the stack -// signature of sequence B is a subtype of the signatures of these blocks, but -// the stack signature of sequence A is not. +// signature of sequence B satisfies the signatures of these blocks, but the +// stack signature of sequence A does not. // // (block (param f64 i32 i32) (result f32) ... ) // (block (param i32 i32) (result f64 f32) ... ) @@ -69,14 +117,12 @@ struct StackSignature { Type params; Type results; - enum Kind { - Fixed, - Polymorphic, - } kind; - - StackSignature() : params(Type::none), results(Type::none), kind(Fixed) {} - StackSignature(Type params, Type results, Kind kind) - : params(params), results(results), kind(kind) {} + bool unreachable; + + StackSignature() + : params(Type::none), results(Type::none), unreachable(false) {} + StackSignature(Type params, Type results, bool unreachable = false) + : params(params), results(results), unreachable(unreachable) {} StackSignature(const StackSignature&) = default; StackSignature& operator=(const StackSignature&) = default; @@ -89,7 +135,7 @@ // compose. template explicit StackSignature(InputIt first, InputIt last) - : params(Type::none), results(Type::none), kind(Fixed) { + : params(Type::none), results(Type::none), unreachable(false) { // TODO: It would be more efficient to build the signature directly and // construct the params in reverse to avoid quadratic behavior. while (first != last) { @@ -100,79 +146,18 @@ // Return `true` iff `next` composes after this stack signature. bool composes(const StackSignature& next) const; + // Whether a block whose contents have this stack signature could be typed + // with `sig`. + bool satisfies(Signature sig) const; + // Compose stack signatures. Assumes they actually compose. StackSignature& operator+=(const StackSignature& next); StackSignature operator+(const StackSignature& next) const; bool operator==(const StackSignature& other) const { return params == other.params && results == other.results && - kind == other.kind; + unreachable == other.unreachable; } - - // Whether a block whose contents have stack signature `a` could be typed with - // stack signature `b`, i.e. whether it could be used in a context that - // expects signature `b`. Formally, where `a` is the LHS and `b` the RHS: - // - // [t1*] -> [t2*] <: [s1* t1'*] -> [s2* t2'*] iff - // - // - t1' <: t1 - // - t2 <: t2' - // - s1 <: s2 - // - // Note that neither signature is polymorphic in this rule and that the - // cardinalities of t1* and t1'*, t2* and t2'*, and s1* and s2* must match. - // - // [t1*] -> [t2*] {poly} <: [s1* t1'*] -> [s2* t2'*] {poly?} iff - // - // - [t1*] -> [t2*] <: [t1'*] -> [t2'*] - // - // Note that s1* and s2* can have different cardinalities and arbitrary types - // in this rule. - // - // As an example of the first rule, consider this instruction sequence: - // - // ref.as_func - // drop - // i32.add - // - // The most specific type you could give this sequence is [i32, i32, anyref] - // -> [i32]. But it could also be used in a context that expects [i32, i32, - // funcref] -> [i32] because ref.as_func can accept funcref or any other - // subtype of anyref. That's where the contravariance comes from. This - // instruction sequence could also be used anywhere that expects [f32, i32, - // i32, anyref] -> [f32, i32] because the f32 simply stays on the stack - // throughout the sequence. That's where the the prefix extension comes from. - // - // For the second rule, consider this sequence: - // - // ref.as_func - // drop - // i32.add - // unreachable - // i32.const 0 - // - // This instruction sequence has the specific type [i32, i32, anyref] -> [i32] - // {poly}. It can be used in any situation the previous block can be used in, - // but can additionally be used in contexts that expect something like [f32, - // i32, i32, anyref] -> [v128, i32]. Because of the polymorphism, the - // additional prefixes on the params and results do not need to match. - // - // Note that a fixed stack signature (without a {poly}) is never a subtype of - // any polymorphic stack signature (with a {poly}). This makes sense because a - // sequence of instructions that has no polymorphic behavior cannot be given a - // type that says it does have polymorphic behavior. - // - // Also, [] -> [] {poly} is the bottom type here; it is a subtype of every - // other stack signature. This corresponds to the `unreachable` instruction - // being able to be given any stack signature. - static bool isSubType(StackSignature a, StackSignature b); - - // Returns true iff `a` and `b` have a LUB, i.e. a minimal StackSignature that - // could type block contents of either type `a` or type `b`. - static bool haveLeastUpperBound(StackSignature a, StackSignature b); - - // Returns the LUB of `a` and `b`. Assumes that the LUB exists. - static StackSignature getLeastUpperBound(StackSignature a, StackSignature b); }; // Calculates stack machine data flow, associating the sources and destinations diff -Nru binaryen-108/src/ir/struct-utils.h binaryen-99/src/ir/struct-utils.h --- binaryen-108/src/ir/struct-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/struct-utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,280 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_struct_utils_h -#define wasm_ir_struct_utils_h - -#include "ir/subtypes.h" -#include "wasm.h" - -namespace wasm { - -namespace StructUtils { - -// A vector of a template type's values. One such vector will be used per struct -// type, where each element in the vector represents a field. We always assume -// that the vectors are pre-initialized to the right length before accessing any -// data, which this class enforces using assertions, and which is implemented in -// StructValuesMap. -template struct StructValues : public std::vector { - T& operator[](size_t index) { - assert(index < this->size()); - return std::vector::operator[](index); - } - - const T& operator[](size_t index) const { - assert(index < this->size()); - return std::vector::operator[](index); - } -}; - -// Maps heap types to a StructValues for that heap type. -// -// Also provides a combineInto() helper that combines one map into another. This -// depends on the underlying T defining a combine() method. -template -struct StructValuesMap : public std::unordered_map> { - // When we access an item, if it does not already exist, create it with a - // vector of the right length for that type. - StructValues& operator[](HeapType type) { - auto inserted = this->insert({type, {}}); - auto& values = inserted.first->second; - if (inserted.second) { - values.resize(type.getStruct().fields.size()); - } - return values; - } - - void combineInto(StructValuesMap& combinedInfos) const { - for (auto& [type, info] : *this) { - for (Index i = 0; i < info.size(); i++) { - combinedInfos[type][i].combine(info[i]); - } - } - } - - void dump(std::ostream& o) { - o << "dump " << this << '\n'; - for (auto& [type, vec] : (*this)) { - o << "dump " << type << " " << &vec << ' '; - for (auto x : vec) { - x.dump(o); - o << " "; - }; - o << '\n'; - } - } -}; - -// Map of functions to StructValuesMap. This lets us compute in parallel while -// we walk the module, and afterwards we will merge them all. -template -struct FunctionStructValuesMap - : public std::unordered_map> { - FunctionStructValuesMap(Module& wasm) { - // Initialize the data for each function in preparation for parallel - // computation. - for (auto& func : wasm.functions) { - (*this)[func.get()]; - } - } - - // Combine information across functions. - void combineInto(StructValuesMap& combinedInfos) const { - for (auto& kv : *this) { - const StructValuesMap& infos = kv.second; - infos.combineInto(combinedInfos); - } - } -}; - -// A generic scanner that finds struct operations and calls hooks to update -// information. Subclasses must define these methods: -// -// * Note an expression written into a field. -// -// void noteExpression(Expression* expr, HeapType type, Index index, T& info); -// -// * Note a default value written during creation. -// -// void noteDefault(Type fieldType, HeapType type, Index index, T& info); -// -// * Note a copied value (read from this field and written to the same, possibly -// in another object). -// -// void noteCopy(HeapType type, Index index, T& info); -// -// * Note a read -// -// void noteRead(HeapType type, Index index, T& info); -// -// We track information from struct.new and struct.set/struct.get separately, -// because in struct.new we know more about the type - we know the actual exact -// type being written to, and not just that it is of a subtype of the -// instruction's type, which helps later. -template -struct StructScanner - : public WalkerPass>> { - bool isFunctionParallel() override { return true; } - - StructScanner(FunctionStructValuesMap& functionNewInfos, - FunctionStructValuesMap& functionSetGetInfos) - : functionNewInfos(functionNewInfos), - functionSetGetInfos(functionSetGetInfos) {} - - void visitStructNew(StructNew* curr) { - auto type = curr->type; - if (type == Type::unreachable) { - return; - } - - // Note writes to all the fields of the struct. - auto heapType = type.getHeapType(); - auto& fields = heapType.getStruct().fields; - auto& infos = functionNewInfos[this->getFunction()][heapType]; - for (Index i = 0; i < fields.size(); i++) { - if (curr->isWithDefault()) { - static_cast(this)->noteDefault( - fields[i].type, heapType, i, infos[i]); - } else { - noteExpressionOrCopy(curr->operands[i], heapType, i, infos[i]); - } - } - } - - void visitStructSet(StructSet* curr) { - auto type = curr->ref->type; - if (type == Type::unreachable) { - return; - } - - // Note a write to this field of the struct. - noteExpressionOrCopy(curr->value, - type.getHeapType(), - curr->index, - functionSetGetInfos[this->getFunction()] - [type.getHeapType()][curr->index]); - } - - void visitStructGet(StructGet* curr) { - auto type = curr->ref->type; - if (type == Type::unreachable) { - return; - } - - auto heapType = type.getHeapType(); - auto index = curr->index; - static_cast(this)->noteRead( - heapType, - index, - functionSetGetInfos[this->getFunction()][heapType][index]); - } - - void - noteExpressionOrCopy(Expression* expr, HeapType type, Index index, T& info) { - // Look at the value falling through, if it has the exact same type - // (otherwise, we'd need to consider both the type actually written and the - // type of the fallthrough, somehow). - auto* fallthrough = Properties::getFallthrough( - expr, this->getPassOptions(), *this->getModule()); - if (fallthrough->type == expr->type) { - expr = fallthrough; - } - if (auto* get = expr->dynCast()) { - if (get->index == index && get->ref->type != Type::unreachable && - get->ref->type.getHeapType() == type) { - static_cast(this)->noteCopy(type, index, info); - return; - } - } - static_cast(this)->noteExpression(expr, type, index, info); - } - - FunctionStructValuesMap& functionNewInfos; - FunctionStructValuesMap& functionSetGetInfos; -}; - -// Helper class to propagate information about fields to sub- and/or super- -// classes in the type hierarchy. While propagating it calls a method -// -// to.combine(from) -// -// which combines the information from |from| into |to|, and should return true -// if we changed something. -template class TypeHierarchyPropagator { -public: - TypeHierarchyPropagator(Module& wasm) : subTypes(wasm) {} - - SubTypes subTypes; - - void propagateToSuperTypes(StructValuesMap& infos) { - propagate(infos, false, true); - } - - void propagateToSubTypes(StructValuesMap& infos) { - propagate(infos, true, false); - } - - void propagateToSuperAndSubTypes(StructValuesMap& infos) { - propagate(infos, true, true); - } - -private: - void propagate(StructValuesMap& combinedInfos, - bool toSubTypes, - bool toSuperTypes) { - UniqueDeferredQueue work; - for (auto& [type, _] : combinedInfos) { - work.push(type); - } - while (!work.empty()) { - auto type = work.pop(); - auto& infos = combinedInfos[type]; - - if (toSuperTypes) { - // Propagate shared fields to the supertype. - if (auto superType = type.getSuperType()) { - auto& superInfos = combinedInfos[*superType]; - auto& superFields = superType->getStruct().fields; - for (Index i = 0; i < superFields.size(); i++) { - if (superInfos[i].combine(infos[i])) { - work.push(*superType); - } - } - } - } - - if (toSubTypes) { - // Propagate shared fields to the subtypes. - auto numFields = type.getStruct().fields.size(); - for (auto subType : subTypes.getSubTypes(type)) { - auto& subInfos = combinedInfos[subType]; - for (Index i = 0; i < numFields; i++) { - if (subInfos[i].combine(infos[i])) { - work.push(subType); - } - } - } - } - } - } -}; - -} // namespace StructUtils - -} // namespace wasm - -#endif // wasm_ir_struct_utils_h diff -Nru binaryen-108/src/ir/subtypes.h binaryen-99/src/ir/subtypes.h --- binaryen-108/src/ir/subtypes.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/subtypes.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_subtypes_h -#define wasm_ir_subtypes_h - -#include "ir/module-utils.h" -#include "wasm.h" - -namespace wasm { - -// Analyze subtyping relationships and provide useful interfaces to discover -// them. -struct SubTypes { - SubTypes(Module& wasm) { - types = ModuleUtils::collectHeapTypes(wasm); - for (auto type : types) { - note(type); - } - } - - const std::vector& getSubTypes(HeapType type) { - return typeSubTypes[type]; - } - - // Get all subtypes of a type, and their subtypes and so forth, recursively. - std::vector getAllSubTypes(HeapType type) { - std::vector ret, work; - work.push_back(type); - while (!work.empty()) { - auto curr = work.back(); - work.pop_back(); - for (auto sub : getSubTypes(curr)) { - ret.push_back(sub); - work.push_back(sub); - } - } - return ret; - } - - // Get all supertypes of a type. The order in the output vector is with the - // immediate supertype first, then its supertype, and so forth. - std::vector getAllSuperTypes(HeapType type) { - std::vector ret; - while (1) { - auto super = type.getSuperType(); - if (!super) { - return ret; - } - ret.push_back(*super); - type = *super; - } - } - - std::vector types; - -private: - // Add a type to the graph. - void note(HeapType type) { - if (auto super = type.getSuperType()) { - typeSubTypes[*super].push_back(type); - } - } - - // Maps a type to its subtypes. - std::unordered_map> typeSubTypes; -}; - -} // namespace wasm - -#endif // wasm_ir_subtypes_h diff -Nru binaryen-108/src/ir/table-utils.cpp binaryen-99/src/ir/table-utils.cpp --- binaryen-108/src/ir/table-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/table-utils.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,84 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "table-utils.h" -#include "element-utils.h" -#include "find_all.h" -#include "module-utils.h" - -namespace wasm::TableUtils { - -std::set getFunctionsNeedingElemDeclare(Module& wasm) { - // Without reference types there are no ref.funcs or elem declare. - if (!wasm.features.hasReferenceTypes()) { - return {}; - } - - // Find all the names in the tables. - - std::unordered_set tableNames; - ElementUtils::iterAllElementFunctionNames( - &wasm, [&](Name name) { tableNames.insert(name); }); - - // Find all the names in ref.funcs. - using Names = std::unordered_set; - - ModuleUtils::ParallelFunctionAnalysis analysis( - wasm, [&](Function* func, Names& names) { - if (func->imported()) { - return; - } - for (auto* refFunc : FindAll(func->body).list) { - names.insert(refFunc->func); - } - }); - - // Find the names that need to be declared. - - std::set ret; - - for (auto& kv : analysis.map) { - auto& names = kv.second; - for (auto name : names) { - if (!tableNames.count(name)) { - ret.insert(name); - } - } - } - - return ret; -} - -bool usesExpressions(ElementSegment* curr, Module* module) { - // Binaryen IR always has ref.funcs for functions in tables for uniformity, - // so that by itself does not indicate if expressions should be used when - // emitting the table or not. But definitely anything that is not a ref.func - // implies we are post-MVP and must use expressions. - bool allElementsRefFunc = - std::all_of(curr->data.begin(), curr->data.end(), [](Expression* entry) { - return entry->is(); - }); - - // If the table has a specialized (non-MVP) type, then the segment must - // declare a type that is a subtype of that, so it must use the post-MVP form - // of using expressions. - bool hasTableOfSpecializedType = - curr->table.is() && module->getTable(curr->table)->type != Type::funcref; - - return !allElementsRefFunc || hasTableOfSpecializedType; -} - -} // namespace wasm::TableUtils diff -Nru binaryen-108/src/ir/table-utils.h binaryen-99/src/ir/table-utils.h --- binaryen-108/src/ir/table-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/table-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,49 +17,44 @@ #ifndef wasm_ir_table_h #define wasm_ir_table_h -#include "ir/element-utils.h" #include "ir/literal-utils.h" -#include "ir/module-utils.h" #include "wasm-traversal.h" #include "wasm.h" -namespace wasm::TableUtils { +namespace wasm { + +namespace TableUtils { struct FlatTable { std::vector names; bool valid; - FlatTable(Module& wasm, Table& table) { + FlatTable(Table& table) { valid = true; - ModuleUtils::iterTableSegments( - wasm, table.name, [&](ElementSegment* segment) { - auto offset = segment->offset; - if (!offset->is() || !segment->type.isFunction()) { - // TODO: handle some non-constant segments - valid = false; - return; - } - Index start = offset->cast()->value.geti32(); - Index end = start + segment->data.size(); - if (end > names.size()) { - names.resize(end); - } - ElementUtils::iterElementSegmentFunctionNames( - segment, [&](Name entry, Index i) { names[start + i] = entry; }); - }); + for (auto& segment : table.segments) { + auto offset = segment.offset; + if (!offset->is()) { + // TODO: handle some non-constant segments + valid = false; + return; + } + Index start = offset->cast()->value.geti32(); + Index end = start + segment.data.size(); + if (end > names.size()) { + names.resize(end); + } + for (Index i = 0; i < segment.data.size(); i++) { + names[start + i] = segment.data[i]; + } + } } }; -inline ElementSegment* getSingletonSegment(Table& table, Module& wasm) { - std::vector tableSegments; - ModuleUtils::iterTableSegments( - wasm, table.name, [&](ElementSegment* segment) { - tableSegments.push_back(segment); - }); - if (tableSegments.size() != 1) { +inline Table::Segment& getSingletonSegment(Table& table, Module& wasm) { + if (table.segments.size() != 1) { Fatal() << "Table doesn't have a singleton segment."; } - return tableSegments[0]; + return table.segments[0]; } // Appends a name to the table. This assumes the table has 0 or 1 segments, @@ -70,10 +65,10 @@ // module has a single table segment, and that the dylink section indicates // we can validly append to that segment, see the check below. inline Index append(Table& table, Name name, Module& wasm) { - auto* segment = getSingletonSegment(table, wasm); - auto tableIndex = segment->data.size(); + auto& segment = getSingletonSegment(table, wasm); + auto tableIndex = segment.data.size(); if (wasm.dylinkSection) { - if (segment->data.size() != wasm.dylinkSection->tableSize) { + if (segment.data.size() != wasm.dylinkSection->tableSize) { Fatal() << "Appending to the table in a module with a dylink section " "that has tableSize which indicates it wants to reserve more " "table space than the actual table elements in the module. " @@ -82,37 +77,25 @@ } wasm.dylinkSection->tableSize++; } - - auto* func = wasm.getFunctionOrNull(name); - assert(func != nullptr && "Cannot append non-existing function to a table."); - segment->data.push_back(Builder(wasm).makeRefFunc(name, func->type)); - table.initial++; + segment.data.push_back(name); + table.initial = table.initial + 1; return tableIndex; } // Checks if a function is already in the table. Returns that index if so, // otherwise appends it. inline Index getOrAppend(Table& table, Name name, Module& wasm) { - auto segment = getSingletonSegment(table, wasm); - for (Index i = 0; i < segment->data.size(); i++) { - if (auto* get = segment->data[i]->dynCast()) { - if (get->func == name) { - return i; - } + auto& segment = getSingletonSegment(table, wasm); + for (Index i = 0; i < segment.data.size(); i++) { + if (segment.data[i] == name) { + return i; } } return append(table, name, wasm); } -// Functions that we take a reference to, but are not in a Table, but get an -// "elem declare" mention in the text and binary formats. -std::set getFunctionsNeedingElemDeclare(Module& wasm); - -// Returns whether a segment uses arbitrary wasm expressions, as opposed to the -// original tables from the MVP that use function indices. (Some post-MVP tables -// do so, and some do not, depending on their type and use.) -bool usesExpressions(ElementSegment* curr, Module* module); +} // namespace TableUtils -} // namespace wasm::TableUtils +} // namespace wasm #endif // wasm_ir_table_h diff -Nru binaryen-108/src/ir/trapping.h binaryen-99/src/ir/trapping.h --- binaryen-108/src/ir/trapping.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/trapping.h 2021-01-07 20:01:06.000000000 +0000 @@ -58,11 +58,11 @@ void addToModule() { if (!immediate) { - for (auto& [_, func] : functions) { - wasm.addFunction(func); + for (auto& pair : functions) { + wasm.addFunction(pair.second); } - for (auto& [_, func] : imports) { - wasm.addFunction(func); + for (auto& pair : imports) { + wasm.addFunction(pair.second); } } functions.clear(); diff -Nru binaryen-108/src/ir/type-updating.cpp binaryen-99/src/ir/type-updating.cpp --- binaryen-108/src/ir/type-updating.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/type-updating.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,419 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "type-updating.h" -#include "find_all.h" -#include "ir/module-utils.h" -#include "ir/utils.h" -#include "wasm-type.h" -#include "wasm.h" - -namespace wasm { - -GlobalTypeRewriter::GlobalTypeRewriter(Module& wasm) : wasm(wasm) {} - -void GlobalTypeRewriter::update() { - indexedTypes = ModuleUtils::getOptimizedIndexedHeapTypes(wasm); - if (indexedTypes.types.empty()) { - return; - } - typeBuilder.grow(indexedTypes.types.size()); - - // Create the temporary heap types. - for (Index i = 0; i < indexedTypes.types.size(); i++) { - auto type = indexedTypes.types[i]; - if (type.isSignature()) { - auto sig = type.getSignature(); - TypeList newParams, newResults; - for (auto t : sig.params) { - newParams.push_back(getTempType(t)); - } - for (auto t : sig.results) { - newResults.push_back(getTempType(t)); - } - Signature newSig(typeBuilder.getTempTupleType(newParams), - typeBuilder.getTempTupleType(newResults)); - modifySignature(indexedTypes.types[i], newSig); - typeBuilder.setHeapType(i, newSig); - } else if (type.isStruct()) { - auto struct_ = type.getStruct(); - // Start with a copy to get mutability/packing/etc. - auto newStruct = struct_; - for (auto& field : newStruct.fields) { - field.type = getTempType(field.type); - } - modifyStruct(indexedTypes.types[i], newStruct); - typeBuilder.setHeapType(i, newStruct); - } else if (type.isArray()) { - auto array = type.getArray(); - // Start with a copy to get mutability/packing/etc. - auto newArray = array; - newArray.element.type = getTempType(newArray.element.type); - modifyArray(indexedTypes.types[i], newArray); - typeBuilder.setHeapType(i, newArray); - } else { - WASM_UNREACHABLE("bad type"); - } - - // Apply a super, if there is one - if (auto super = type.getSuperType()) { - typeBuilder.setSubType(i, indexedTypes.indices[*super]); - } - } - - auto buildResults = typeBuilder.build(); -#ifndef NDEBUG - if (auto* err = buildResults.getError()) { - Fatal() << "Internal GlobalTypeRewriter build error: " << err->reason - << " at index " << err->index; - } -#endif - auto& newTypes = *buildResults; - - // Map the old types to the new ones. This uses the fact that type indices - // are the same in the old and new types, that is, we have not added or - // removed types, just modified them. - using OldToNewTypes = std::unordered_map; - OldToNewTypes oldToNewTypes; - for (Index i = 0; i < indexedTypes.types.size(); i++) { - oldToNewTypes[indexedTypes.types[i]] = newTypes[i]; - } - - // Replace all the old types in the module with the new ones. - struct CodeUpdater - : public WalkerPass< - PostWalker>> { - bool isFunctionParallel() override { return true; } - - OldToNewTypes& oldToNewTypes; - - CodeUpdater(OldToNewTypes& oldToNewTypes) : oldToNewTypes(oldToNewTypes) {} - - CodeUpdater* create() override { return new CodeUpdater(oldToNewTypes); } - - Type getNew(Type type) { - if (type.isRef()) { - return Type(getNew(type.getHeapType()), type.getNullability()); - } - if (type.isRtt()) { - return Type(Rtt(type.getRtt().depth, getNew(type.getHeapType()))); - } - if (type.isTuple()) { - auto tuple = type.getTuple(); - for (auto& t : tuple.types) { - t = getNew(t); - } - return Type(tuple); - } - return type; - } - - HeapType getNew(HeapType type) { - if (type.isBasic()) { - return type; - } - if (type.isFunction() || type.isData()) { - assert(oldToNewTypes.count(type)); - return oldToNewTypes[type]; - } - return type; - } - - Signature getNew(Signature sig) { - return Signature(getNew(sig.params), getNew(sig.results)); - } - - void visitExpression(Expression* curr) { - // Update the type to the new one. - curr->type = getNew(curr->type); - - // Update any other type fields as well. - -#define DELEGATE_ID curr->_id - -#define DELEGATE_START(id) \ - auto* cast = curr->cast(); \ - WASM_UNUSED(cast); - -#define DELEGATE_GET_FIELD(id, field) cast->field - -#define DELEGATE_FIELD_TYPE(id, field) cast->field = getNew(cast->field); - -#define DELEGATE_FIELD_HEAPTYPE(id, field) cast->field = getNew(cast->field); - -#define DELEGATE_FIELD_CHILD(id, field) -#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field) -#define DELEGATE_FIELD_INT(id, field) -#define DELEGATE_FIELD_INT_ARRAY(id, field) -#define DELEGATE_FIELD_LITERAL(id, field) -#define DELEGATE_FIELD_NAME(id, field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) -#define DELEGATE_FIELD_ADDRESS(id, field) - -#include "wasm-delegations-fields.def" - } - }; - - CodeUpdater updater(oldToNewTypes); - PassRunner runner(&wasm); - updater.run(&runner, &wasm); - updater.walkModuleCode(&wasm); - - // Update global locations that refer to types. - for (auto& table : wasm.tables) { - table->type = updater.getNew(table->type); - } - for (auto& elementSegment : wasm.elementSegments) { - elementSegment->type = updater.getNew(elementSegment->type); - } - for (auto& global : wasm.globals) { - global->type = updater.getNew(global->type); - } - for (auto& func : wasm.functions) { - func->type = updater.getNew(func->type); - for (auto& var : func->vars) { - var = updater.getNew(var); - } - } - for (auto& tag : wasm.tags) { - tag->sig = updater.getNew(tag->sig); - } - - // Update type names. - for (auto& [old, new_] : oldToNewTypes) { - if (wasm.typeNames.count(old)) { - wasm.typeNames[new_] = wasm.typeNames[old]; - } - } -} - -Type GlobalTypeRewriter::getTempType(Type type) { - if (type.isBasic()) { - return type; - } - if (type.isRef()) { - auto heapType = type.getHeapType(); - if (!indexedTypes.indices.count(heapType)) { - // This type was not present in the module, but is now being used when - // defining new types. That is fine; just use it. - return type; - } - return typeBuilder.getTempRefType( - typeBuilder.getTempHeapType(indexedTypes.indices[heapType]), - type.getNullability()); - } - if (type.isRtt()) { - auto rtt = type.getRtt(); - auto newRtt = rtt; - auto heapType = type.getHeapType(); - if (!indexedTypes.indices.count(heapType)) { - // See above with references. - return type; - } - newRtt.heapType = - typeBuilder.getTempHeapType(indexedTypes.indices[heapType]); - return typeBuilder.getTempRttType(newRtt); - } - if (type.isTuple()) { - auto& tuple = type.getTuple(); - auto newTuple = tuple; - for (auto& t : newTuple.types) { - t = getTempType(t); - } - return typeBuilder.getTempTupleType(newTuple); - } - WASM_UNREACHABLE("bad type"); -} - -namespace TypeUpdating { - -bool canHandleAsLocal(Type type) { - // Defaultable types are always ok. For non-nullable types, we can handle them - // using defaultable ones + ref.as_non_nulls. - return type.isDefaultable() || type.isRef(); -} - -void handleNonDefaultableLocals(Function* func, Module& wasm) { - // Check if this is an issue. - if (wasm.features.hasGCNNLocals()) { - return; - } - bool hasNonNullable = false; - for (auto type : func->vars) { - if (type.isNonNullable()) { - hasNonNullable = true; - break; - } - } - if (!hasNonNullable) { - return; - } - - // Rewrite the local.gets. - Builder builder(wasm); - for (auto** getp : FindAllPointers(func->body).list) { - auto* get = (*getp)->cast(); - if (!func->isVar(get->index)) { - // We do not need to process params, which can legally be non-nullable. - continue; - } - *getp = fixLocalGet(get, wasm); - } - - // Update tees, whose type must match the local (if the wasm spec changes for - // the type to be that of the value, then this can be removed). - for (auto** setp : FindAllPointers(func->body).list) { - auto* set = (*setp)->cast(); - if (!func->isVar(set->index)) { - // We do not need to process params, which can legally be non-nullable. - continue; - } - // Non-tees do not change, and unreachable tees can be ignored here as their - // type is unreachable anyhow. - if (!set->isTee() || set->type == Type::unreachable) { - continue; - } - auto type = func->getLocalType(set->index); - if (type.isNonNullable()) { - set->type = Type(type.getHeapType(), Nullable); - *setp = builder.makeRefAs(RefAsNonNull, set); - } - } - - // Rewrite the types of the function's vars (which we can do now, after we - // are done using them to know which local.gets etc to fix). - for (auto& type : func->vars) { - type = getValidLocalType(type, wasm.features); - } -} - -Type getValidLocalType(Type type, FeatureSet features) { - assert(canHandleAsLocal(type)); - if (type.isNonNullable() && !features.hasGCNNLocals()) { - type = Type(type.getHeapType(), Nullable); - } - return type; -} - -Expression* fixLocalGet(LocalGet* get, Module& wasm) { - if (get->type.isNonNullable() && !wasm.features.hasGCNNLocals()) { - // The get should now return a nullable value, and a ref.as_non_null - // fixes that up. - get->type = getValidLocalType(get->type, wasm.features); - return Builder(wasm).makeRefAs(RefAsNonNull, get); - } - return get; -} - -void updateParamTypes(Function* func, - const std::vector& newParamTypes, - Module& wasm) { - // Before making this update, we must be careful if the param was "reused", - // specifically, if it is assigned a less-specific type in the body then - // we'd get a validation error when we refine it. To handle that, if a less- - // specific type is assigned simply switch to a new local, that is, we can - // do a fixup like this: - // - // function foo(x : oldType) { - // .. - // x = (oldType)val; - // - // => - // - // function foo(x : newType) { - // var x_oldType = x; // assign the param immediately to a fixup var - // .. - // x_oldType = (oldType)val; // fixup var is used throughout the body - // - // Later optimization passes may be able to remove the extra var, and can - // take advantage of the refined argument type while doing so. - - // A map of params that need a fixup to the new fixup var used for it. - std::unordered_map paramFixups; - - FindAll sets(func->body); - - for (auto* set : sets.list) { - auto index = set->index; - if (func->isParam(index) && !paramFixups.count(index) && - !Type::isSubType(set->value->type, newParamTypes[index])) { - paramFixups[index] = Builder::addVar(func, func->getLocalType(index)); - } - } - - FindAll gets(func->body); - - // Apply the fixups we identified that we need. - if (!paramFixups.empty()) { - // Write the params immediately to the fixups. - Builder builder(wasm); - std::vector contents; - for (Index index = 0; index < func->getNumParams(); index++) { - auto iter = paramFixups.find(index); - if (iter != paramFixups.end()) { - auto fixup = iter->second; - contents.push_back(builder.makeLocalSet( - fixup, builder.makeLocalGet(index, newParamTypes[index]))); - } - } - contents.push_back(func->body); - func->body = builder.makeBlock(contents); - - // Update gets and sets using the param to use the fixup. - for (auto* get : gets.list) { - auto iter = paramFixups.find(get->index); - if (iter != paramFixups.end()) { - get->index = iter->second; - } - } - for (auto* set : sets.list) { - auto iter = paramFixups.find(set->index); - if (iter != paramFixups.end()) { - set->index = iter->second; - } - } - } - - // Update local.get/local.tee operations that use the modified param type. - for (auto* get : gets.list) { - auto index = get->index; - if (func->isParam(index)) { - get->type = newParamTypes[index]; - } - } - for (auto* set : sets.list) { - auto index = set->index; - if (func->isParam(index) && set->isTee()) { - set->type = newParamTypes[index]; - set->finalize(); - } - } - - // Propagate the new get and set types outwards. - ReFinalize().walkFunctionInModule(func, &wasm); - - if (!paramFixups.empty()) { - // We have added locals, and must handle non-nullability of them. - TypeUpdating::handleNonDefaultableLocals(func, wasm); - } -} - -} // namespace TypeUpdating - -} // namespace wasm diff -Nru binaryen-108/src/ir/type-updating.h binaryen-99/src/ir/type-updating.h --- binaryen-108/src/ir/type-updating.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/type-updating.h 2021-01-07 20:01:06.000000000 +0000 @@ -18,35 +18,17 @@ #define wasm_ir_type_updating_h #include "ir/branch-utils.h" -#include "ir/module-utils.h" #include "wasm-traversal.h" namespace wasm { -// -// A class that tracks type dependencies between nodes, letting you update types -// efficiently when removing and altering code incrementally. -// -// Altering code can alter types beyond the current node in the following ways: -// -// 1. Removing a break can make a block unreachable, if nothing else reaches -// it. -// 2. Altering the type of a child to unreachable can make the parent -// unreachable. -// -// Most passes don't do either of the above and can just do replaceCurrent when -// replacing one thing with another, which is fine as no types need to be -// updated outside of the item being replaced. Passes that do one of the two -// things mentioned need to update types in the IR affected by the change (which -// can include any of the parent nodes, in general) and they have two main ways -// to do so: -// -// * Call ReFinalize() after making all their changes. The IR will be in an -// invalid state while making the changes, and only fixed up at the end by -// ReFinalize(), but often that is good enough. -// * Use this class, TypeUpdater. This lets you update the IR after each -// incremental change that you perform, keeping the IR valid constantly. -// +// a class that tracks type dependencies between nodes, letting you +// update types efficiently when removing and altering code. +// altering code can alter types in the following way: +// * removing a break can make a block unreachable, if nothing else +// reaches it +// * altering the type of a child to unreachable can make the parent +// unreachable struct TypeUpdater : public ExpressionStackWalker> { @@ -323,104 +305,6 @@ } }; -// Rewrites global heap types across an entire module, allowing changes to be -// made while doing so. -class GlobalTypeRewriter { -public: - Module& wasm; - - GlobalTypeRewriter(Module& wasm); - virtual ~GlobalTypeRewriter() {} - - // Main entry point. This performs the entire process of creating new heap - // types and calling the hooks below, then applies the new types throughout - // the module. - void update(); - - // Subclasses can implement these methods to modify the new set of types that - // we map to. By default, we simply copy over the types, and these functions - // are the hooks to apply changes through. The methods receive as input the - // old type, and a structure that they can modify. That structure is the one - // used to define the new type in the TypeBuilder. - virtual void modifyStruct(HeapType oldType, Struct& struct_) {} - virtual void modifyArray(HeapType oldType, Array& array) {} - virtual void modifySignature(HeapType oldType, Signature& sig) {} - - // Map an old type to a temp type. This can be called from the above hooks, - // so that they can use a proper temp type of the TypeBuilder while modifying - // things. - Type getTempType(Type type); - - using SignatureUpdates = std::unordered_map; - - // Helper for the repeating pattern of just updating Signature types using a - // map of old heap type => new Signature. - static void updateSignatures(const SignatureUpdates& updates, Module& wasm) { - if (updates.empty()) { - return; - } - - class SignatureRewriter : public GlobalTypeRewriter { - const SignatureUpdates& updates; - - public: - SignatureRewriter(Module& wasm, const SignatureUpdates& updates) - : GlobalTypeRewriter(wasm), updates(updates) { - update(); - } - - void modifySignature(HeapType oldSignatureType, Signature& sig) override { - auto iter = updates.find(oldSignatureType); - if (iter != updates.end()) { - sig.params = getTempType(iter->second.params); - sig.results = getTempType(iter->second.results); - } - } - } rewriter(wasm, updates); - } - -private: - TypeBuilder typeBuilder; - - // The old types and their indices. - ModuleUtils::IndexedHeapTypes indexedTypes; -}; - -namespace TypeUpdating { - -// Checks whether a type is valid as a local, or whether -// handleNonDefaultableLocals() can handle it if not. -bool canHandleAsLocal(Type type); - -// Finds non-nullable locals, which are currently not supported, and handles -// them. Atm this turns them into nullable ones, and adds ref.as_non_null on -// their uses (which keeps the type of the users identical). -// This may also handle other types of nondefaultable locals in the future. -void handleNonDefaultableLocals(Function* func, Module& wasm); - -// Returns the type that a local should be, after handling of non- -// defaultability. -Type getValidLocalType(Type type, FeatureSet features); - -// Given a local.get, returns a proper replacement for it, taking into account -// the extra work we need to do to handle non-defaultable values (e.g., add a -// ref.as_non_null around it, if the local should be non-nullable but is not). -Expression* fixLocalGet(LocalGet* get, Module& wasm); - -// Applies new types of parameters to a function. This does all the necessary -// changes aside from altering the function type, which the caller is expected -// to do (the caller might simply change the type, but in other cases the caller -// might be rewriting the types and need to preserve their identity in terms of -// nominal typing, so we don't change the type here). The specific things this -// function does are to update the types of local.get/tee operations, -// refinalize, etc., basically all operations necessary to ensure validation -// with the new types. -void updateParamTypes(Function* func, - const std::vector& newParamTypes, - Module& wasm); - -} // namespace TypeUpdating - } // namespace wasm #endif // wasm_ir_type_updating_h diff -Nru binaryen-108/src/ir/utils.h binaryen-99/src/ir/utils.h --- binaryen-108/src/ir/utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/ir/utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -33,17 +33,11 @@ void visitExpression(Expression* curr) { size++; } - // Measure the number of expressions. static Index measure(Expression* tree) { Measurer measurer; measurer.walk(tree); return measurer.size; } - - // A rough estimate of average binary size per expression. The number here is - // based on measurements on real-world (MVP) wasm files, on which observed - // ratios were 2.2 - 2.8. - static constexpr double BytesPerExpr = 2.5; }; struct ExpressionAnalyzer { @@ -82,20 +76,9 @@ return flexibleEqual(left, right, comparer); } - // Returns true if the expression is handled by the hasher. - using ExprHasher = std::function; - static bool nothingHasher(Expression*, size_t&) { return false; } - - static size_t flexibleHash(Expression* curr, ExprHasher hasher); - // hash an expression, ignoring superficial details like specific internal // names - static size_t hash(Expression* curr) { - return flexibleHash(curr, nothingHasher); - } - - // hash an expression, ignoring child nodes. - static size_t shallowHash(Expression* curr); + static size_t hash(Expression* curr); }; // Re-Finalizes all node types. This can be run after code was modified in @@ -124,22 +107,22 @@ ReFinalize() { name = "refinalize"; } // block finalization is O(bad) if we do each block by itself, so do it in - // bulk, tracking break value types so we just do a linear pass. - std::unordered_map> breakTypes; + // bulk, tracking break value types so we just do a linear pass + + std::map breakValues; #define DELEGATE(CLASS_TO_VISIT) \ void visit##CLASS_TO_VISIT(CLASS_TO_VISIT* curr); -#include "wasm-delegations.def" +#include "wasm-delegations.h" void visitFunction(Function* curr); void visitExport(Export* curr); void visitGlobal(Global* curr); void visitTable(Table* curr); - void visitElementSegment(ElementSegment* curr); void visitMemory(Memory* curr); - void visitTag(Tag* curr); + void visitEvent(Event* curr); void visitModule(Module* curr); private: @@ -156,14 +139,13 @@ #define DELEGATE(CLASS_TO_VISIT) \ void visit##CLASS_TO_VISIT(CLASS_TO_VISIT* curr) { curr->finalize(); } -#include "wasm-delegations.def" +#include "wasm-delegations.h" void visitExport(Export* curr) { WASM_UNREACHABLE("unimp"); } void visitGlobal(Global* curr) { WASM_UNREACHABLE("unimp"); } void visitTable(Table* curr) { WASM_UNREACHABLE("unimp"); } - void visitElementSegment(ElementSegment* curr) { WASM_UNREACHABLE("unimp"); } void visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); } - void visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); } + void visitEvent(Event* curr) { WASM_UNREACHABLE("unimp"); } void visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); } // given a stack of nested expressions, update them all from child to parent @@ -240,10 +222,8 @@ if (maybeDrop(curr->body)) { acted = true; } - for (auto* catchBody : curr->catchBodies) { - if (maybeDrop(catchBody)) { - acted = true; - } + if (maybeDrop(curr->catchBody)) { + acted = true; } if (acted) { reFinalize(); @@ -254,7 +234,7 @@ void doWalkFunction(Function* curr) { ReFinalize().walkFunctionInModule(curr, getModule()); walk(curr->body); - if (curr->getResults() == Type::none && curr->body->type.isConcrete()) { + if (curr->sig.results == Type::none && curr->body->type.isConcrete()) { curr->body = Builder(*getModule()).makeDrop(curr->body); } ReFinalize().walkFunctionInModule(curr, getModule()); diff -Nru binaryen-108/src/js/binaryen.js-extern-post.js binaryen-99/src/js/binaryen.js-extern-post.js --- binaryen-108/src/js/binaryen.js-extern-post.js 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/src/js/binaryen.js-extern-post.js 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,8 @@ + +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = binaryen; +else if (typeof define === 'function' && define['amd']) + define([], function() { return binaryen; }); +else if (typeof exports === 'object') + exports["binaryen"] = binaryen; \ No newline at end of file diff -Nru binaryen-108/src/js/binaryen.js-extern-pre.js binaryen-99/src/js/binaryen.js-extern-pre.js --- binaryen-108/src/js/binaryen.js-extern-pre.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/js/binaryen.js-extern-pre.js 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,2 @@ -// FIXME: The Emscripten shell requires this variable to be present, even though -// we are building to ES6 (where it doesn't exist) and the .wasm blob is inlined -// see: https://github.com/emscripten-core/emscripten/issues/11792 -var __dirname = ""; +var binaryen = {}; +(function() { \ No newline at end of file diff -Nru binaryen-108/src/js/binaryen.jsoo-extern-pre.js binaryen-99/src/js/binaryen.jsoo-extern-pre.js --- binaryen-108/src/js/binaryen.jsoo-extern-pre.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/js/binaryen.jsoo-extern-pre.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -// js_of_ocaml needs a special syntax for exposing variables to the compiler -// and it is not built for nodejs so we don't need the __dirname hack - -//Provides: Binaryen -var Binaryen = {}; - diff -Nru binaryen-108/src/js/binaryen.js-post.js binaryen-99/src/js/binaryen.js-post.js --- binaryen-108/src/js/binaryen.js-post.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/js/binaryen.js-post.js 2021-01-07 20:01:06.000000000 +0000 @@ -35,10 +35,10 @@ ['v128', 'Vec128'], ['funcref', 'Funcref'], ['externref', 'Externref'], + ['exnref', 'Exnref'], ['anyref', 'Anyref'], ['eqref', 'Eqref'], ['i31ref', 'I31ref'], - ['dataref', 'Dataref'], ['unreachable', 'Unreachable'], ['auto', 'Auto'] ].forEach(entry => { @@ -82,22 +82,18 @@ 'SIMDTernary', 'SIMDShift', 'SIMDLoad', - 'SIMDLoadStoreLane', 'MemoryInit', 'DataDrop', 'MemoryCopy', 'MemoryFill', 'RefNull', - 'RefIs', + 'RefIsNull', 'RefFunc', 'RefEq', - 'TableGet', - 'TableSet', - 'TableSize', - 'TableGrow', 'Try', 'Throw', 'Rethrow', + 'BrOnExn', 'TupleMake', 'TupleExtract', 'Pop', @@ -106,14 +102,13 @@ 'CallRef', 'RefTest', 'RefCast', - 'BrOn', + 'BrOnCast', 'RttCanon', 'RttSub', 'StructNew', 'StructGet', 'StructSet', 'ArrayNew', - 'ArrayInit', 'ArrayGet', 'ArraySet', 'ArrayLen' @@ -127,7 +122,7 @@ 'Table', 'Memory', 'Global', - 'Tag' + 'Event' ].forEach(name => { Module['ExternalKinds'][name] = Module['External' + name] = Module['_BinaryenExternal' + name](); }); @@ -147,9 +142,6 @@ 'Multivalue', 'GC', 'Memory64', - 'TypedFunctionReferences', - 'RelaxedSIMD', - 'ExtendedConst', 'All' ].forEach(name => { Module['Features'][name] = Module['_BinaryenFeature' + name](); @@ -349,12 +341,6 @@ 'LeUVecI32x4', 'GeSVecI32x4', 'GeUVecI32x4', - 'EqVecI64x2', - 'NeVecI64x2', - 'LtSVecI64x2', - 'GtSVecI64x2', - 'LeSVecI64x2', - 'GeSVecI64x2', 'EqVecF32x4', 'NeVecF32x4', 'LtVecF32x4', @@ -373,10 +359,9 @@ 'XorVec128', 'AndNotVec128', 'BitselectVec128', - 'AnyTrueVec128', - 'PopcntVecI8x16', 'AbsVecI8x16', 'NegVecI8x16', + 'AnyTrueVecI8x16', 'AllTrueVecI8x16', 'BitmaskVecI8x16', 'ShlVecI8x16', @@ -388,6 +373,7 @@ 'SubVecI8x16', 'SubSatSVecI8x16', 'SubSatUVecI8x16', + 'MulVecI8x16', 'MinSVecI8x16', 'MinUVecI8x16', 'MaxSVecI8x16', @@ -395,6 +381,7 @@ 'AvgrUVecI8x16', 'AbsVecI16x8', 'NegVecI16x8', + 'AnyTrueVecI16x8', 'AllTrueVecI16x8', 'BitmaskVecI16x8', 'ShlVecI16x8', @@ -412,18 +399,10 @@ 'MaxSVecI16x8', 'MaxUVecI16x8', 'AvgrUVecI16x8', - 'Q15MulrSatSVecI16x8', - 'ExtMulLowSVecI16x8', - 'ExtMulHighSVecI16x8', - 'ExtMulLowUVecI16x8', - 'ExtMulHighUVecI16x8', 'DotSVecI16x8ToVecI32x4', - 'ExtMulLowSVecI32x4', - 'ExtMulHighSVecI32x4', - 'ExtMulLowUVecI32x4', - 'ExtMulHighUVecI32x4', 'AbsVecI32x4', 'NegVecI32x4', + 'AnyTrueVecI32x4', 'AllTrueVecI32x4', 'BitmaskVecI32x4', 'ShlVecI32x4', @@ -436,23 +415,18 @@ 'MinUVecI32x4', 'MaxSVecI32x4', 'MaxUVecI32x4', - 'AbsVecI64x2', 'NegVecI64x2', - 'AllTrueVecI64x2', - 'BitmaskVecI64x2', 'ShlVecI64x2', 'ShrSVecI64x2', 'ShrUVecI64x2', 'AddVecI64x2', 'SubVecI64x2', 'MulVecI64x2', - 'ExtMulLowSVecI64x2', - 'ExtMulHighSVecI64x2', - 'ExtMulLowUVecI64x2', - 'ExtMulHighUVecI64x2', 'AbsVecF32x4', 'NegVecF32x4', 'SqrtVecF32x4', + 'QFMAVecF32x4', + 'QFMSVecF32x4', 'AddVecF32x4', 'SubVecF32x4', 'MulVecF32x4', @@ -468,6 +442,8 @@ 'AbsVecF64x2', 'NegVecF64x2', 'SqrtVecF64x2', + 'QFMAVecF64x2', + 'QFMSVecF64x2', 'AddVecF64x2', 'SubVecF64x2', 'MulVecF64x2', @@ -480,65 +456,37 @@ 'FloorVecF64x2', 'TruncVecF64x2', 'NearestVecF64x2', - 'ExtAddPairwiseSVecI8x16ToI16x8', - 'ExtAddPairwiseUVecI8x16ToI16x8', - 'ExtAddPairwiseSVecI16x8ToI32x4', - 'ExtAddPairwiseUVecI16x8ToI32x4', 'TruncSatSVecF32x4ToVecI32x4', 'TruncSatUVecF32x4ToVecI32x4', + 'TruncSatSVecF64x2ToVecI64x2', + 'TruncSatUVecF64x2ToVecI64x2', 'ConvertSVecI32x4ToVecF32x4', 'ConvertUVecI32x4ToVecF32x4', - 'Load8SplatVec128', - 'Load16SplatVec128', - 'Load32SplatVec128', - 'Load64SplatVec128', - 'Load8x8SVec128', - 'Load8x8UVec128', - 'Load16x4SVec128', - 'Load16x4UVec128', - 'Load32x2SVec128', - 'Load32x2UVec128', - 'Load32ZeroVec128', - 'Load64ZeroVec128', - 'Load8LaneVec128', - 'Load16LaneVec128', - 'Load32LaneVec128', - 'Load64LaneVec128', - 'Store8LaneVec128', - 'Store16LaneVec128', - 'Store32LaneVec128', - 'Store64LaneVec128', + 'ConvertSVecI64x2ToVecF64x2', + 'ConvertUVecI64x2ToVecF64x2', + 'LoadSplatVec8x16', + 'LoadSplatVec16x8', + 'LoadSplatVec32x4', + 'LoadSplatVec64x2', + 'LoadExtSVec8x8ToVecI16x8', + 'LoadExtUVec8x8ToVecI16x8', + 'LoadExtSVec16x4ToVecI32x4', + 'LoadExtUVec16x4ToVecI32x4', + 'LoadExtSVec32x2ToVecI64x2', + 'LoadExtUVec32x2ToVecI64x2', 'NarrowSVecI16x8ToVecI8x16', 'NarrowUVecI16x8ToVecI8x16', 'NarrowSVecI32x4ToVecI16x8', 'NarrowUVecI32x4ToVecI16x8', - 'ExtendLowSVecI8x16ToVecI16x8', - 'ExtendHighSVecI8x16ToVecI16x8', - 'ExtendLowUVecI8x16ToVecI16x8', - 'ExtendHighUVecI8x16ToVecI16x8', - 'ExtendLowSVecI16x8ToVecI32x4', - 'ExtendHighSVecI16x8ToVecI32x4', - 'ExtendLowUVecI16x8ToVecI32x4', - 'ExtendHighUVecI16x8ToVecI32x4', - 'ExtendLowSVecI32x4ToVecI64x2', - 'ExtendHighSVecI32x4ToVecI64x2', - 'ExtendLowUVecI32x4ToVecI64x2', - 'ExtendHighUVecI32x4ToVecI64x2', - 'ConvertLowSVecI32x4ToVecF64x2', - 'ConvertLowUVecI32x4ToVecF64x2', - 'TruncSatZeroSVecF64x2ToVecI32x4', - 'TruncSatZeroUVecF64x2ToVecI32x4', - 'DemoteZeroVecF64x2ToVecF32x4', - 'PromoteLowVecF32x4ToVecF64x2', - 'SwizzleVecI8x16', - 'RefIsNull', - 'RefIsFunc', - 'RefIsData', - 'RefIsI31', - 'RefAsNonNull', - 'RefAsFunc', - 'RefAsData', - 'RefAsI31', + 'WidenLowSVecI8x16ToVecI16x8', + 'WidenHighSVecI8x16ToVecI16x8', + 'WidenLowUVecI8x16ToVecI16x8', + 'WidenHighUVecI8x16ToVecI16x8', + 'WidenLowSVecI16x8ToVecI32x4', + 'WidenHighSVecI16x8ToVecI32x4', + 'WidenLowUVecI16x8ToVecI32x4', + 'WidenHighUVecI16x8ToVecI32x4', + 'SwizzleVec8x16', ].forEach(name => { Module['Operations'][name] = Module[name] = Module['_Binaryen' + name](); }); @@ -554,13 +502,10 @@ 'WritesGlobal', 'ReadsMemory', 'WritesMemory', - 'ReadsTable', - 'WritesTable', 'ImplicitTrap', 'IsAtomic', 'Throws', 'DanglingPop', - 'TrapsNeverHappen', 'Any' ].forEach(name => { Module['SideEffects'][name] = Module['_BinaryenSideEffect' + name](); @@ -628,9 +573,9 @@ // 'callIndirect', 'returnCall', 'returnCallIndirect' are deprecated and may // be removed in a future release. Please use the the snake_case names // instead. - self['callIndirect'] = self['call_indirect'] = function(table, target, operands, params, results) { + self['callIndirect'] = self['call_indirect'] = function(target, operands, params, results) { return preserveStack(() => - Module['_BinaryenCallIndirect'](module, strToStack(table), target, i32sToStack(operands), operands.length, params, results) + Module['_BinaryenCallIndirect'](module, target, i32sToStack(operands), operands.length, params, results) ); }; self['returnCall'] = self['return_call'] = function(name, operands, type) { @@ -638,9 +583,9 @@ Module['_BinaryenReturnCall'](module, strToStack(name), i32sToStack(operands), operands.length, type) ); }; - self['returnCallIndirect'] = self['return_call_indirect'] = function(table, target, operands, params, results) { + self['returnCallIndirect'] = self['return_call_indirect'] = function(target, operands, params, results) { return preserveStack(() => - Module['_BinaryenReturnCallIndirect'](module, strToStack(table), target, i32sToStack(operands), operands.length, params, results) + Module['_BinaryenReturnCallIndirect'](module, target, i32sToStack(operands), operands.length, params, results) ); }; @@ -668,21 +613,6 @@ } } - self['table'] = { - 'get'(name, index, type) { - return Module['_BinaryenTableGet'](module, strToStack(name), index, type); - }, - 'set'(name, index, value) { - return Module['_BinaryenTableSet'](module, strToStack(name), index, value); - }, - 'size'(name) { - return Module['_BinaryenTableSize'](module, strToStack(name)); - }, - 'grow'(name, value, delta) { - return Module['_BinaryenTableGrow'](module, strToStack(name), value, delta); - } - } - self['memory'] = { 'size'() { return Module['_BinaryenMemorySize'](module); @@ -1496,66 +1426,6 @@ 'load'(offset, align, ptr) { return Module['_BinaryenLoad'](module, 16, false, offset, align, Module['v128'], ptr); }, - 'load8_splat'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load8SplatVec128'], offset, align, ptr); - }, - 'load16_splat'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load16SplatVec128'], offset, align, ptr); - }, - 'load32_splat'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32SplatVec128'], offset, align, ptr); - }, - 'load64_splat'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load64SplatVec128'], offset, align, ptr); - }, - 'load8x8_s'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load8x8SVec128'], offset, align, ptr); - }, - 'load8x8_u'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load8x8UVec128'], offset, align, ptr); - }, - 'load16x4_s'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load16x4SVec128'], offset, align, ptr); - }, - 'load16x4_u'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load16x4UVec128'], offset, align, ptr); - }, - 'load32x2_s'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32x2SVec128'], offset, align, ptr); - }, - 'load32x2_u'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32x2UVec128'], offset, align, ptr); - }, - 'load32_zero'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load32ZeroVec128'], offset, align, ptr); - }, - 'load64_zero'(offset, align, ptr) { - return Module['_BinaryenSIMDLoad'](module, Module['Load64ZeroVec128'], offset, align, ptr); - }, - 'load8_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load8LaneVec128'], offset, align, index, ptr, vec); - }, - 'load16_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load16LaneVec128'], offset, align, index, ptr, vec); - }, - 'load32_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load32LaneVec128'], offset, align, index, ptr, vec); - }, - 'load64_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Load64LaneVec128'], offset, align, index, ptr, vec); - }, - 'store8_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store8LaneVec128'], offset, align, index, ptr, vec); - }, - 'store16_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store16LaneVec128'], offset, align, index, ptr, vec); - }, - 'store32_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store32LaneVec128'], offset, align, index, ptr, vec); - }, - 'store64_lane'(offset, align, index, ptr, vec) { - return Module['_BinaryenSIMDLoadStoreLane'](module, Module['Store64LaneVec128'], offset, align, index, ptr, vec); - }, 'store'(offset, align, ptr, value) { return Module['_BinaryenStore'](module, 16, offset, align, ptr, value, Module['v128']); }, @@ -1569,9 +1439,6 @@ 'not'(value) { return Module['_BinaryenUnary'](module, Module['NotVec128'], value); }, - 'any_true'(value) { - return Module['_BinaryenUnary'](module, Module['AnyTrueVec128'], value); - }, 'and'(left, right) { return Module['_BinaryenBinary'](module, Module['AndVec128'], left, right); }, @@ -1593,12 +1460,6 @@ }; self['i8x16'] = { - 'shuffle'(left, right, mask) { - return preserveStack(() => Module['_BinaryenSIMDShuffle'](module, left, right, i8sToStack(mask))); - }, - 'swizzle'(left, right) { - return Module['_BinaryenBinary'](module, Module['SwizzleVecI8x16'], left, right); - }, 'splat'(value) { return Module['_BinaryenUnary'](module, Module['SplatVecI8x16'], value); }, @@ -1647,15 +1508,15 @@ 'neg'(value) { return Module['_BinaryenUnary'](module, Module['NegVecI8x16'], value); }, + 'any_true'(value) { + return Module['_BinaryenUnary'](module, Module['AnyTrueVecI8x16'], value); + }, 'all_true'(value) { return Module['_BinaryenUnary'](module, Module['AllTrueVecI8x16'], value); }, 'bitmask'(value) { return Module['_BinaryenUnary'](module, Module['BitmaskVecI8x16'], value); }, - 'popcnt'(value) { - return Module['_BinaryenUnary'](module, Module['PopcntVecI8x16'], value); - }, 'shl'(vec, shift) { return Module['_BinaryenSIMDShift'](module, Module['ShlVecI8x16'], vec, shift); }, @@ -1683,6 +1544,9 @@ 'sub_saturate_u'(left, right) { return Module['_BinaryenBinary'](module, Module['SubSatUVecI8x16'], left, right); }, + 'mul'(left, right) { + return Module['_BinaryenBinary'](module, Module['MulVecI8x16'], left, right); + }, 'min_s'(left, right) { return Module['_BinaryenBinary'](module, Module['MinSVecI8x16'], left, right); }, @@ -1755,6 +1619,9 @@ 'neg'(value) { return Module['_BinaryenUnary'](module, Module['NegVecI16x8'], value); }, + 'any_true'(value) { + return Module['_BinaryenUnary'](module, Module['AnyTrueVecI16x8'], value); + }, 'all_true'(value) { return Module['_BinaryenUnary'](module, Module['AllTrueVecI16x8'], value); }, @@ -1806,44 +1673,29 @@ 'avgr_u'(left, right) { return Module['_BinaryenBinary'](module, Module['AvgrUVecI16x8'], left, right); }, - 'q15mulr_sat_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['Q15MulrSatSVecI16x8'], left, right); - }, - 'extmul_low_i8x16_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulLowSVecI16x8'], left, right); - }, - 'extmul_high_i8x16_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulHighSVecI16x8'], left, right); - }, - 'extmul_low_i8x16_u'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulLowUVecI16x8'], left, right); - }, - 'extmul_high_i8x16_u'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulHighUVecI16x8'], left, right); - }, - 'extadd_pairwise_i8x16_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtAddPairwiseSVecI8x16ToI16x8'], value); - }, - 'extadd_pairwise_i8x16_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtAddPairwiseUVecI8x16ToI16x8'], value); - }, 'narrow_i32x4_s'(left, right) { return Module['_BinaryenBinary'](module, Module['NarrowSVecI32x4ToVecI16x8'], left, right); }, 'narrow_i32x4_u'(left, right) { return Module['_BinaryenBinary'](module, Module['NarrowUVecI32x4ToVecI16x8'], left, right); }, - 'extend_low_i8x16_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendLowSVecI8x16ToVecI16x8'], value); + 'widen_low_i8x16_s'(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowSVecI8x16ToVecI16x8'], value); + }, + 'widen_high_i8x16_s'(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighSVecI8x16ToVecI16x8'], value); + }, + 'widen_low_i8x16_u'(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowUVecI8x16ToVecI16x8'], value); }, - 'extend_high_i8x16_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendHighSVecI8x16ToVecI16x8'], value); + 'widen_high_i8x16_u'(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighUVecI8x16ToVecI16x8'], value); }, - 'extend_low_i8x16_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendLowUVecI8x16ToVecI16x8'], value); + 'load8x8_s'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadExtSVec8x8ToVecI16x8'], offset, align, ptr); }, - 'extend_high_i8x16_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendHighUVecI8x16ToVecI16x8'], value); + 'load8x8_u'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadExtUVec8x8ToVecI16x8'], offset, align, ptr); }, }; @@ -1893,6 +1745,9 @@ 'neg'(value) { return Module['_BinaryenUnary'](module, Module['NegVecI32x4'], value); }, + 'any_true'(value) { + return Module['_BinaryenUnary'](module, Module['AnyTrueVecI32x4'], value); + }, 'all_true'(value) { return Module['_BinaryenUnary'](module, Module['AllTrueVecI32x4'], value); }, @@ -1932,47 +1787,29 @@ 'dot_i16x8_s'(left, right) { return Module['_BinaryenBinary'](module, Module['DotSVecI16x8ToVecI32x4'], left, right); }, - 'extmul_low_i16x8_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulLowSVecI32x4'], left, right); - }, - 'extmul_high_i16x8_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulHighSVecI32x4'], left, right); - }, - 'extmul_low_i16x8_u'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulLowUVecI32x4'], left, right); - }, - 'extmul_high_i16x8_u'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulHighUVecI32x4'], left, right); - }, - 'extadd_pairwise_i16x8_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtAddPairwiseSVecI16x8ToI32x4'], value); - }, - 'extadd_pairwise_i16x8_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtAddPairwiseUVecI16x8ToI32x4'], value); - }, 'trunc_sat_f32x4_s'(value) { return Module['_BinaryenUnary'](module, Module['TruncSatSVecF32x4ToVecI32x4'], value); }, 'trunc_sat_f32x4_u'(value) { return Module['_BinaryenUnary'](module, Module['TruncSatUVecF32x4ToVecI32x4'], value); }, - 'extend_low_i16x8_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendLowSVecI16x8ToVecI32x4'], value); + 'widen_low_i16x8_s'(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowSVecI16x8ToVecI32x4'], value); }, - 'extend_high_i16x8_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendHighSVecI16x8ToVecI32x4'], value); + 'widen_high_i16x8_s'(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighSVecI16x8ToVecI32x4'], value); }, - 'extend_low_i16x8_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendLowUVecI16x8ToVecI32x4'], value); + 'widen_low_i16x8_u'(value) { + return Module['_BinaryenUnary'](module, Module['WidenLowUVecI16x8ToVecI32x4'], value); }, - 'extend_high_i16x8_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendHighUVecI16x8ToVecI32x4'], value); + 'widen_high_i16x8_u'(value) { + return Module['_BinaryenUnary'](module, Module['WidenHighUVecI16x8ToVecI32x4'], value); }, - 'trunc_sat_f64x2_s_zero'(value) { - return Module['_BinaryenUnary'](module, Module['TruncSatZeroSVecF64x2ToVecI32x4'], value); + 'load16x4_s'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadExtSVec16x4ToVecI32x4'], offset, align, ptr); }, - 'trunc_sat_f64x2_u_zero'(value) { - return Module['_BinaryenUnary'](module, Module['TruncSatZeroUVecF64x2ToVecI32x4'], value); + 'load16x4_u'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadExtUVec16x4ToVecI32x4'], offset, align, ptr); }, }; @@ -1986,36 +1823,9 @@ 'replace_lane'(vec, index, value) { return Module['_BinaryenSIMDReplace'](module, Module['ReplaceLaneVecI64x2'], vec, index, value); }, - 'eq'(left, right) { - return Module['_BinaryenBinary'](module, Module['EqVecI64x2'], left, right); - }, - 'ne'(left, right) { - return Module['_BinaryenBinary'](module, Module['NeVecI64x2'], left, right); - }, - 'lt_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['LtSVecI64x2'], left, right); - }, - 'gt_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['GtSVecI64x2'], left, right); - }, - 'le_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['LeSVecI64x2'], left, right); - }, - 'ge_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['GeSVecI64x2'], left, right); - }, - 'abs'(value) { - return Module['_BinaryenUnary'](module, Module['AbsVecI64x2'], value); - }, 'neg'(value) { return Module['_BinaryenUnary'](module, Module['NegVecI64x2'], value); }, - 'all_true'(value) { - return Module['_BinaryenUnary'](module, Module['AllTrueVecI64x2'], value); - }, - 'bitmask'(value) { - return Module['_BinaryenUnary'](module, Module['BitmaskVecI64x2'], value); - }, 'shl'(vec, shift) { return Module['_BinaryenSIMDShift'](module, Module['ShlVecI64x2'], vec, shift); }, @@ -2034,29 +1844,17 @@ 'mul'(left, right) { return Module['_BinaryenBinary'](module, Module['MulVecI64x2'], left, right); }, - 'extmul_low_i32x4_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulLowSVecI64x2'], left, right); - }, - 'extmul_high_i32x4_s'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulHighSVecI64x2'], left, right); - }, - 'extmul_low_i32x4_u'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulLowUVecI64x2'], left, right); + 'trunc_sat_f64x2_s'(value) { + return Module['_BinaryenUnary'](module, Module['TruncSatSVecF64x2ToVecI64x2'], value); }, - 'extmul_high_i32x4_u'(left, right) { - return Module['_BinaryenBinary'](module, Module['ExtMulHighUVecI64x2'], left, right); + 'trunc_sat_f64x2_u'(value) { + return Module['_BinaryenUnary'](module, Module['TruncSatUVecF64x2ToVecI64x2'], value); }, - 'extend_low_i32x4_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendLowSVecI32x4ToVecI64x2'], value); - }, - 'extend_high_i32x4_s'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendHighSVecI32x4ToVecI64x2'], value); - }, - 'extend_low_i32x4_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendLowUVecI32x4ToVecI64x2'], value); + 'load32x2_s'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadExtSVec32x2ToVecI64x2'], offset, align, ptr); }, - 'extend_high_i32x4_u'(value) { - return Module['_BinaryenUnary'](module, Module['ExtendHighUVecI32x4ToVecI64x2'], value); + 'load32x2_u'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadExtUVec32x2ToVecI64x2'], offset, align, ptr); }, }; @@ -2097,6 +1895,12 @@ 'sqrt'(value) { return Module['_BinaryenUnary'](module, Module['SqrtVecF32x4'], value); }, + 'qfma'(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMAVecF32x4'], a, b, c); + }, + 'qfms'(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMSVecF32x4'], a, b, c); + }, 'add'(left, right) { return Module['_BinaryenBinary'](module, Module['AddVecF32x4'], left, right); }, @@ -2139,9 +1943,6 @@ 'convert_i32x4_u'(value) { return Module['_BinaryenUnary'](module, Module['ConvertUVecI32x4ToVecF32x4'], value); }, - 'demote_f64x2_zero'(value) { - return Module['_BinaryenUnary'](module, Module['DemoteZeroVecF64x2ToVecF32x4'], value); - }, }; self['f64x2'] = { @@ -2181,6 +1982,12 @@ 'sqrt'(value) { return Module['_BinaryenUnary'](module, Module['SqrtVecF64x2'], value); }, + 'qfma'(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMAVecF64x2'], a, b, c); + }, + 'qfms'(a, b, c) { + return Module['_BinaryenSIMDTernary'](module, Module['QFMSVecF64x2'], a, b, c); + }, 'add'(left, right) { return Module['_BinaryenBinary'](module, Module['AddVecF64x2'], left, right); }, @@ -2217,14 +2024,41 @@ 'nearest'(value) { return Module['_BinaryenUnary'](module, Module['NearestVecF64x2'], value); }, - 'convert_low_i32x4_s'(value) { - return Module['_BinaryenUnary'](module, Module['ConvertLowSVecI32x4ToVecF64x2'], value); + 'convert_i64x2_s'(value) { + return Module['_BinaryenUnary'](module, Module['ConvertSVecI64x2ToVecF64x2'], value); + }, + 'convert_i64x2_u'(value) { + return Module['_BinaryenUnary'](module, Module['ConvertUVecI64x2ToVecF64x2'], value); + }, + }; + + self['v8x16'] = { + 'shuffle'(left, right, mask) { + return preserveStack(() => Module['_BinaryenSIMDShuffle'](module, left, right, i8sToStack(mask))); + }, + 'swizzle'(left, right) { + return Module['_BinaryenBinary'](module, Module['SwizzleVec8x16'], left, right); + }, + 'load_splat'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadSplatVec8x16'], offset, align, ptr); + }, + }; + + self['v16x8'] = { + 'load_splat'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadSplatVec16x8'], offset, align, ptr); }, - 'convert_low_i32x4_u'(value) { - return Module['_BinaryenUnary'](module, Module['ConvertLowUVecI32x4ToVecF64x2'], value); + }; + + self['v32x4'] = { + 'load_splat'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadSplatVec32x4'], offset, align, ptr); }, - 'promote_low_f32x4'(value) { - return Module['_BinaryenUnary'](module, Module['PromoteLowVecF32x4ToVecF64x2'], value); + }; + + self['v64x2'] = { + 'load_splat'(offset, align, ptr) { + return Module['_BinaryenSIMDLoad'](module, Module['LoadSplatVec64x2'], offset, align, ptr); }, }; @@ -2240,6 +2074,12 @@ } }; + self['exnref'] = { + 'pop'() { + return Module['_BinaryenPop'](module, Module['exnref']); + } + }; + self['anyref'] = { 'pop'() { return Module['_BinaryenPop'](module, Module['anyref']); @@ -2258,39 +2098,12 @@ } }; - self['dataref'] = { - 'pop'() { - return Module['_BinaryenPop'](module, Module['dataref']); - } - }; - self['ref'] = { 'null'(type) { return Module['_BinaryenRefNull'](module, type); }, 'is_null'(value) { - return Module['_BinaryenRefIs'](module, Module['RefIsNull'], value); - }, - 'is_func'(value) { - return Module['_BinaryenRefIs'](module, Module['RefIsFunc'], value); - }, - 'is_data'(value) { - return Module['_BinaryenRefIs'](module, Module['RefIsData'], value); - }, - 'is_i31'(value) { - return Module['_BinaryenRefIs'](module, Module['RefIsI31'], value); - }, - 'as_non_null'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsNonNull'], value); - }, - 'as_func'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsFunc'], value); - }, - 'as_data'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsData'], value); - }, - 'as_i31'(value) { - return Module['_BinaryenRefAs'](module, Module['RefAsI31'], value); + return Module['_BinaryenRefIsNull'](module, value); }, 'func'(func, type) { return preserveStack(() => Module['_BinaryenRefFunc'](module, strToStack(func), type)); @@ -2322,15 +2135,17 @@ } }; - self['try'] = function(name, body, catchTags, catchBodies, delegateTarget) { - return preserveStack(() => - Module['_BinaryenTry'](module, name ? strToStack(name) : 0, body, i32sToStack(catchTags.map(strToStack)), catchTags.length, i32sToStack(catchBodies), catchBodies.length, delegateTarget ? strToStack(delegateTarget) : 0)); + self['try'] = function(body, catchBody) { + return Module['_BinaryenTry'](module, body, catchBody); }; - self['throw'] = function(tag, operands) { - return preserveStack(() => Module['_BinaryenThrow'](module, strToStack(tag), i32sToStack(operands), operands.length)); + self['throw'] = function(event_, operands) { + return preserveStack(() => Module['_BinaryenThrow'](module, strToStack(event_), i32sToStack(operands), operands.length)); }; - self['rethrow'] = function(target) { - return Module['_BinaryenRethrow'](module, strToStack(target)); + self['rethrow'] = function(exnref) { + return Module['_BinaryenRethrow'](module, exnref); + }; + self['br_on_exn'] = function(label, event_, exnref) { + return preserveStack(() => Module['_BinaryenBrOnExn'](module, strToStack(label), strToStack(event_), exnref)); }; self['tuple'] = { @@ -2372,63 +2187,17 @@ self['getGlobal'] = function(name) { return preserveStack(() => Module['_BinaryenGetGlobal'](module, strToStack(name))); }; - self['addTable'] = function(table, initial, maximum, type = Module['_BinaryenTypeFuncref']()) { - return preserveStack(() => Module['_BinaryenAddTable'](module, strToStack(table), initial, maximum, type)); - } - self['getTable'] = function(name) { - return preserveStack(() => Module['_BinaryenGetTable'](module, strToStack(name))); - }; - self['addActiveElementSegment'] = function(table, name, funcNames, offset = self['i32']['const'](0)) { - return preserveStack(() => Module['_BinaryenAddActiveElementSegment']( - module, - strToStack(table), - strToStack(name), - i32sToStack(funcNames.map(strToStack)), - funcNames.length, - offset - )); - }; - self['addPassiveElementSegment'] = function(name, funcNames) { - return preserveStack(() => Module['_BinaryenAddPassiveElementSegment']( - module, - strToStack(name), - i32sToStack(funcNames.map(strToStack)), - funcNames.length - )); - }; - self['getElementSegment'] = function(name) { - return preserveStack(() => Module['_BinaryenGetElementSegment'](module, strToStack(name))); - }; - self['getTableSegments'] = function(table) { - var numElementSegments = Module['_BinaryenGetNumElementSegments'](module); - var tableName = UTF8ToString(Module['_BinaryenTableGetName'](table)); - var ret = []; - for (var i = 0; i < numElementSegments; i++) { - var segment = Module['_BinaryenGetElementSegmentByIndex'](module, i); - var elemTableName = UTF8ToString(Module['_BinaryenElementSegmentGetTable'](segment)); - if (tableName === elemTableName) { - ret.push(segment); - } - } - return ret; - } self['removeGlobal'] = function(name) { return preserveStack(() => Module['_BinaryenRemoveGlobal'](module, strToStack(name))); } - self['removeTable'] = function(name) { - return preserveStack(() => Module['_BinaryenRemoveTable'](module, strToStack(name))); - }; - self['removeElementSegment'] = function(name) { - return preserveStack(() => Module['_BinaryenRemoveElementSegment'](module, strToStack(name))); - }; - self['addTag'] = function(name, params, results) { - return preserveStack(() => Module['_BinaryenAddTag'](module, strToStack(name), params, results)); + self['addEvent'] = function(name, attribute, params, results) { + return preserveStack(() => Module['_BinaryenAddEvent'](module, strToStack(name), attribute, params, results)); }; - self['getTag'] = function(name) { - return preserveStack(() => Module['_BinaryenGetTag'](module, strToStack(name))); + self['getEvent'] = function(name) { + return preserveStack(() => Module['_BinaryenGetEvent'](module, strToStack(name))); }; - self['removeTag'] = function(name) { - return preserveStack(() => Module['_BinaryenRemoveTag'](module, strToStack(name))); + self['removeEvent'] = function(name) { + return preserveStack(() => Module['_BinaryenRemoveEvent'](module, strToStack(name))); }; self['addFunctionImport'] = function(internalName, externalModuleName, externalBaseName, params, results) { return preserveStack(() => @@ -2450,9 +2219,9 @@ Module['_BinaryenAddGlobalImport'](module, strToStack(internalName), strToStack(externalModuleName), strToStack(externalBaseName), globalType, mutable) ); }; - self['addTagImport'] = function(internalName, externalModuleName, externalBaseName, params, results) { + self['addEventImport'] = function(internalName, externalModuleName, externalBaseName, attribute, params, results) { return preserveStack(() => - Module['_BinaryenAddTagImport'](module, strToStack(internalName), strToStack(externalModuleName), strToStack(externalBaseName), params, results) + Module['_BinaryenAddEventImport'](module, strToStack(internalName), strToStack(externalModuleName), strToStack(externalBaseName), attribute, params, results) ); }; self['addExport'] = // deprecated @@ -2468,12 +2237,43 @@ self['addGlobalExport'] = function(internalName, externalName) { return preserveStack(() => Module['_BinaryenAddGlobalExport'](module, strToStack(internalName), strToStack(externalName))); }; - self['addTagExport'] = function(internalName, externalName) { - return preserveStack(() => Module['_BinaryenAddTagExport'](module, strToStack(internalName), strToStack(externalName))); + self['addEventExport'] = function(internalName, externalName) { + return preserveStack(() => Module['_BinaryenAddEventExport'](module, strToStack(internalName), strToStack(externalName))); }; self['removeExport'] = function(externalName) { return preserveStack(() => Module['_BinaryenRemoveExport'](module, strToStack(externalName))); }; + self['setFunctionTable'] = function(initial, maximum, funcNames, offset = self['i32']['const'](0)) { + return preserveStack(() => { + return Module['_BinaryenSetFunctionTable'](module, initial, maximum, + i32sToStack(funcNames.map(strToStack)), + funcNames.length, + offset + ); + }); + }; + self['getFunctionTable'] = function() { + return { + 'imported': Boolean(Module['_BinaryenIsFunctionTableImported'](module)), + 'segments': (function() { + const numSegments = Module['_BinaryenGetNumFunctionTableSegments'](module) + const arr = new Array(numSegments); + for (let i = 0; i !== numSegments; ++i) { + const segmentLength = Module['_BinaryenGetFunctionTableSegmentLength'](module, i); + const names = new Array(segmentLength); + for (let j = 0; j !== segmentLength; ++j) { + const ptr = Module['_BinaryenGetFunctionTableSegmentData'](module, i, j); + names[j] = UTF8ToString(ptr); + } + arr[i] = { + 'offset': Module['_BinaryenGetFunctionTableSegmentOffset'](module, i), + 'names': names + }; + } + return arr; + })() + }; + }; self['setMemory'] = function(initial, maximum, exportName, segments = [], shared = false) { // segments are assumed to be { passive: bool, offset: expression ref, data: array of 8-bit data } return preserveStack(() => { @@ -2550,21 +2350,9 @@ self['getNumGlobals'] = function() { return Module['_BinaryenGetNumGlobals'](module); }; - self['getNumTables'] = function() { - return Module['_BinaryenGetNumTables'](module); - }; - self['getNumElementSegments'] = function() { - return Module['_BinaryenGetNumElementSegments'](module); - }; self['getGlobalByIndex'] = function(index) { return Module['_BinaryenGetGlobalByIndex'](module, index); }; - self['getTableByIndex'] = function(index) { - return Module['_BinaryenGetTableByIndex'](module, index); - }; - self['getElementSegmentByIndex'] = function(index) { - return Module['_BinaryenGetElementSegmentByIndex'](module, index); - }; self['emitText'] = function() { const old = out; let ret = ''; @@ -2703,23 +2491,6 @@ return ret; } -function setAllNested(ref, values, numFn, setFn, appendFn, removeFn) { - const num = values.length; - let prevNum = numFn(ref); - let index = 0; - while (index < num) { - if (index < prevNum) { - setFn(ref, index, values[index]); - } else { - appendFn(ref, values[index]); - } - ++index; - } - while (prevNum > index) { - removeFn(ref, --prevNum); - } -} - // Gets the specific id of an 'Expression' Module['getExpressionId'] = function(expr) { return Module['_BinaryenExpressionGetId'](expr); @@ -2789,7 +2560,6 @@ 'type': type, 'isReturn': Boolean(Module['_BinaryenCallIndirectIsReturn'](expr)), 'target': Module['_BinaryenCallIndirectGetTarget'](expr), - 'table': Module['_BinaryenCallIndirectGetTable'](expr), 'operands': getAllNested(expr, Module['_BinaryenCallIndirectGetNumOperands'], Module['_BinaryenCallIndirectGetOperandAt']) }; case Module['LocalGetId']: @@ -2819,35 +2589,6 @@ 'name': UTF8ToString(Module['_BinaryenGlobalSetGetName'](expr)), 'value': Module['_BinaryenGlobalSetGetValue'](expr) }; - case Module['TableGetId']: - return { - 'id': id, - 'type': type, - 'table': UTF8ToString(Module['_BinaryenTableGetGetTable'](expr)), - 'index': Module['_BinaryenTableGetGetIndex'](expr) - }; - case Module['TableSetId']: - return { - 'id': id, - 'type': type, - 'table': UTF8ToString(Module['_BinaryenTableSetGetTable'](expr)), - 'index': Module['_BinaryenTableSetGetIndex'](expr), - 'value': Module['_BinaryenTableSetGetValue'](expr) - }; - case Module['TableSizeId']: - return { - 'id': id, - 'type': type, - 'table': UTF8ToString(Module['_BinaryenTableSizeGetTable'](expr)), - }; - case Module['TableGrowId']: - return { - 'id': id, - 'type': type, - 'table': UTF8ToString(Module['_BinaryenTableGrowGetTable'](expr)), - 'value': Module['_BinaryenTableGrowGetValue'](expr), - 'delta': Module['_BinaryenTableGrowGetDelta'](expr), - }; case Module['LoadId']: return { 'id': id, @@ -3053,17 +2794,6 @@ 'align': Module['_BinaryenSIMDLoadGetAlign'](expr), 'ptr': Module['_BinaryenSIMDLoadGetPtr'](expr) }; - case Module['SIMDLoadStoreLaneId']: - return { - 'id': id, - 'type': type, - 'op': Module['_BinaryenSIMDLoadStoreLaneGetOp'](expr), - 'offset': Module['_BinaryenSIMDLoadStoreLaneGetOffset'](expr), - 'align': Module['_BinaryenSIMDLoadStoreLaneGetAlign'](expr), - 'index': Module['_BinaryenSIMDLoadStoreLaneGetIndex'](expr), - 'ptr': Module['_BinaryenSIMDLoadStoreLaneGetPtr'](expr), - 'vec': Module['_BinaryenSIMDLoadStoreLaneGetVec'](expr) - }; case Module['MemoryInitId']: return { 'id': id, @@ -3096,19 +2826,11 @@ 'id': id, 'type': type }; - case Module['RefIsId']: + case Module['RefIsNullId']: return { 'id': id, 'type': type, - 'op': Module['_BinaryenRefIsGetOp'](expr), - 'value': Module['_BinaryenRefIsGetValue'](expr) - }; - case Module['RefAsId']: - return { - 'id': id, - 'type': type, - 'op': Module['_BinaryenRefAsGetOp'](expr), - 'value': Module['_BinaryenRefAsGetValue'](expr) + 'value': Module['_BinaryenRefIsNullGetValue'](expr) }; case Module['RefFuncId']: return { @@ -3127,26 +2849,29 @@ return { 'id': id, 'type': type, - 'name': UTF8ToString(Module['_BinaryenTryGetName'](expr)), 'body': Module['_BinaryenTryGetBody'](expr), - 'catchTags': getAllNested(expr, Module['_BinaryenTryGetNumCatchTags'], Module['_BinaryenTryGetCatchTagAt']), - 'catchBodies': getAllNested(expr, Module['_BinaryenTryGetNumCatchBodies'], Module['_BinaryenTryGetCatchBodyAt']), - 'hasCatchAll': Module['_BinaryenTryHasCatchAll'](expr), - 'delegateTarget': UTF8ToString(Module['_BinaryenTryGetDelegateTarget'](expr)), - 'isDelegate': Module['_BinaryenTryIsDelegate'](expr) + 'catchBody': Module['_BinaryenTryGetCatchBody'](expr) }; case Module['ThrowId']: return { 'id': id, 'type': type, - 'tag': UTF8ToString(Module['_BinaryenThrowGetTag'](expr)), + 'event': UTF8ToString(Module['_BinaryenThrowGetEvent'](expr)), 'operands': getAllNested(expr, Module['_BinaryenThrowGetNumOperands'], Module['_BinaryenThrowGetOperandAt']) }; case Module['RethrowId']: return { 'id': id, 'type': type, - 'target': UTF8ToString(Module['_BinaryenRethrowGetTarget'](expr)) + 'exnref': Module['_BinaryenRethrowGetExnref'](expr) + }; + case Module['BrOnExnId']: + return { + 'id': id, + 'type': type, + 'name': UTF8ToString(Module['_BinaryenBrOnExnGetName'](expr)), + 'event': UTF8ToString(Module['_BinaryenBrOnExnGetEvent'](expr)), + 'exnref': Module['_BinaryenBrOnExnGetExnref'](expr) }; case Module['TupleMakeId']: return { @@ -3181,10 +2906,8 @@ }; // Gets the side effects of the specified expression -Module['getSideEffects'] = function(expr, module) { - assert(module); // guard against incorrect old API usage: a module must be - // provided here. - return Module['_BinaryenExpressionGetSideEffects'](expr, module['ptr']); +Module['getSideEffects'] = function(expr, features) { + return Module['_BinaryenExpressionGetSideEffects'](expr, features); }; Module['createType'] = function(types) { @@ -3229,47 +2952,15 @@ }; }; -// Obtains information about a 'Table' -Module['getTableInfo'] = function(table) { - var hasMax = Boolean(Module['_BinaryenTableHasMax'](table)); - var tableInfo = { - 'name': UTF8ToString(Module['_BinaryenTableGetName'](table)), - 'module': UTF8ToString(Module['_BinaryenTableImportGetModule'](table)), - 'base': UTF8ToString(Module['_BinaryenTableImportGetBase'](table)), - 'initial': Module['_BinaryenTableGetInitial'](table), - } - - if (hasMax) { - tableInfo.max = Module['_BinaryenTableGetMax'](table); - } - - return tableInfo; -}; - -Module['getElementSegmentInfo'] = function(segment) { - var segmentLength = Module['_BinaryenElementSegmentGetLength'](segment); - var names = new Array(segmentLength); - for (let j = 0; j !== segmentLength; ++j) { - var ptr = Module['_BinaryenElementSegmentGetData'](segment, j); - names[j] = UTF8ToString(ptr); - } - - return { - 'name': UTF8ToString(Module['_BinaryenElementSegmentGetName'](segment)), - 'table': UTF8ToString(Module['_BinaryenElementSegmentGetTable'](segment)), - 'offset': Module['_BinaryenElementSegmentGetOffset'](segment), - 'data': names - } -} - -// Obtains information about a 'Tag' -Module['getTagInfo'] = function(tag) { +// Obtains information about a 'Event' +Module['getEventInfo'] = function(event_) { return { - 'name': UTF8ToString(Module['_BinaryenTagGetName'](tag)), - 'module': UTF8ToString(Module['_BinaryenTagImportGetModule'](tag)), - 'base': UTF8ToString(Module['_BinaryenTagImportGetBase'](tag)), - 'params': Module['_BinaryenTagGetParams'](tag), - 'results': Module['_BinaryenTagGetResults'](tag) + 'name': UTF8ToString(Module['_BinaryenEventGetName'](event_)), + 'module': UTF8ToString(Module['_BinaryenEventImportGetModule'](event_)), + 'base': UTF8ToString(Module['_BinaryenEventImportGetBase'](event_)), + 'attribute': Module['_BinaryenEventGetAttribute'](event_), + 'params': Module['_BinaryenEventGetParams'](event_), + 'results': Module['_BinaryenEventGetResults'](event_) }; }; @@ -3359,16 +3050,6 @@ Module['_BinaryenSetLowMemoryUnused'](on); }; -// Gets whether that an imported memory will be zero-initialized speculation. -Module['getZeroFilledMemory'] = function() { - return Boolean(Module['_BinaryenGetZeroFilledMemory']()); -}; - -// Enables or disables whether that an imported memory will be -// zero-initialized speculation. -Module['setZeroFilledMemory'] = function(on) { - Module['_BinaryenSetZeroFilledMemory'](on); -}; // Gets whether fast math optimizations are enabled, ignoring for example // corner cases of floating-point math like NaN changes. Module['getFastMath'] = function() { @@ -3544,10 +3225,29 @@ return Module['_BinaryenBlockGetNumChildren'](expr); }, 'getChildren'(expr) { - return getAllNested(expr, Module['_BinaryenBlockGetNumChildren'], Module['_BinaryenBlockGetChildAt']); + const numChildren = Module['_BinaryenBlockGetNumChildren'](expr); + const children = new Array(numChildren); + let index = 0; + while (index < numChildren) { + children[index] = Module['_BinaryenBlockGetChildAt'](expr, index++); + } + return children; }, 'setChildren'(expr, children) { - setAllNested(expr, children, Module['_BinaryenBlockGetNumChildren'], Module['_BinaryenBlockSetChildAt'], Module['_BinaryenBlockAppendChild'], Module['_BinaryenBlockRemoveChildAt']); + const numChildren = children.length; + let prevNumChildren = Module['_BinaryenBlockGetNumChildren'](expr); + let index = 0; + while (index < numChildren) { + if (index < prevNumChildren) { + Module['_BinaryenBlockSetChildAt'](expr, index, children[index]); + } else { + Module['_BinaryenBlockAppendChild'](expr, children[index]); + } + ++index; + } + while (prevNumChildren > index) { + Module['_BinaryenBlockRemoveChildAt'](expr, --prevNumChildren); + } }, 'getChildAt'(expr, index) { return Module['_BinaryenBlockGetChildAt'](expr, index); @@ -3630,12 +3330,31 @@ return Module['_BinaryenSwitchGetNumNames'](expr); }, 'getNames'(expr) { - return getAllNested(expr, Module['_BinaryenSwitchGetNumNames'], Module['_BinaryenSwitchGetNameAt']).map(p => UTF8ToString(p)); + const numNames = Module['_BinaryenSwitchGetNumNames'](expr); + const names = new Array(numNames); + let index = 0; + while (index < numNames) { + names[index] = UTF8ToString(Module['_BinaryenSwitchGetNameAt'](expr, index++)); + } + return names; }, 'setNames'(expr, names) { - preserveStack(() => { - setAllNested(expr, names.map(strToStack), Module['_BinaryenSwitchGetNumNames'], Module['_BinaryenSwitchSetNameAt'], Module['_BinaryenSwitchAppendName'], Module['_BinaryenSwitchRemoveNameAt']); - }); + const numNames = names.length; + let prevNumNames = Module['_BinaryenSwitchGetNumNames'](expr); + let index = 0; + while (index < numNames) { + preserveStack(() => { + if (index < prevNumNames) { + Module['_BinaryenSwitchSetNameAt'](expr, index, strToStack(names[index])); + } else { + Module['_BinaryenSwitchAppendName'](expr, strToStack(names[index])); + } + }); + ++index; + } + while (prevNumNames > index) { + Module['_BinaryenSwitchRemoveNameAt'](expr, --prevNumNames); + } }, 'getDefaultName'(expr) { const name = Module['_BinaryenSwitchGetDefaultName'](expr); @@ -3684,10 +3403,29 @@ return Module['_BinaryenCallGetNumOperands'](expr); }, 'getOperands'(expr) { - return getAllNested(expr, Module['_BinaryenCallGetNumOperands'], Module['_BinaryenCallGetOperandAt']); + const numOperands = Module['_BinaryenCallGetNumOperands'](expr); + const operands = new Array(numOperands); + let index = 0; + while (index < numOperands) { + operands[index] = Module['_BinaryenCallGetOperandAt'](expr, index++); + } + return operands; }, 'setOperands'(expr, operands) { - setAllNested(expr, operands, Module['_BinaryenCallGetNumOperands'], Module['_BinaryenCallSetOperandAt'], Module['_BinaryenCallAppendOperand'], Module['_BinaryenCallRemoveOperandAt']); + const numOperands = operands.length; + let prevNumOperands = Module['_BinaryenCallGetNumOperands'](expr); + let index = 0; + while (index < numOperands) { + if (index < prevNumOperands) { + Module['_BinaryenCallSetOperandAt'](expr, index, operands[index]); + } else { + Module['_BinaryenCallAppendOperand'](expr, operands[index]); + } + ++index; + } + while (prevNumOperands > index) { + Module['_BinaryenCallRemoveOperandAt'](expr, --prevNumOperands); + } }, 'getOperandAt'(expr, index) { return Module['_BinaryenCallGetOperandAt'](expr, index); @@ -3719,20 +3457,33 @@ 'setTarget'(expr, targetExpr) { Module['_BinaryenCallIndirectSetTarget'](expr, targetExpr); }, - 'getTable'(expr) { - return UTF8ToString(Module['_BinaryenCallIndirectGetTable'](expr)); - }, - 'setTable'(expr, table) { - preserveStack(() => { Module['_BinaryenCallIndirectSetTable'](expr, strToStack(table)) }); - }, 'getNumOperands'(expr) { return Module['_BinaryenCallIndirectGetNumOperands'](expr); }, 'getOperands'(expr) { - return getAllNested(expr, Module['_BinaryenCallIndirectGetNumOperands'], Module['_BinaryenCallIndirectGetOperandAt']); + const numOperands = Module['_BinaryenCallIndirectGetNumOperands'](expr); + const operands = new Array(numOperands); + let index = 0; + while (index < numOperands) { + operands[index] = Module['_BinaryenCallIndirectGetOperandAt'](expr, index++); + } + return operands; }, 'setOperands'(expr, operands) { - setAllNested(expr, operands, Module['_BinaryenCallIndirectGetNumOperands'], Module['_BinaryenCallIndirectSetOperandAt'], Module['_BinaryenCallIndirectAppendOperand'], Module['_BinaryenCallIndirectRemoveOperandAt']); + const numOperands = operands.length; + let prevNumOperands = Module['_BinaryenCallIndirectGetNumOperands'](expr); + let index = 0; + while (index < numOperands) { + if (index < prevNumOperands) { + Module['_BinaryenCallIndirectSetOperandAt'](expr, index, operands[index]); + } else { + Module['_BinaryenCallIndirectAppendOperand'](expr, operands[index]); + } + ++index; + } + while (prevNumOperands > index) { + Module['_BinaryenCallIndirectRemoveOperandAt'](expr, --prevNumOperands); + } }, 'getOperandAt'(expr, index) { return Module['_BinaryenCallIndirectGetOperandAt'](expr, index); @@ -3820,72 +3571,6 @@ } }); -Module['TableGet'] = makeExpressionWrapper({ - 'getTable'(expr) { - return UTF8ToString(Module['_BinaryenTableGetGetTable'](expr)); - }, - 'setTable'(expr, name) { - preserveStack(() => { Module['_BinaryenTableGetSetTable'](expr, strToStack(name)) }); - }, - 'getIndex'(expr) { - return Module['_BinaryenTableGetGetIndex'](expr); - }, - 'setIndex'(expr, indexExpr) { - Module['_BinaryenTableGetSetIndex'](expr, indexExpr); - } -}); - -Module['TableSet'] = makeExpressionWrapper({ - 'getTable'(expr) { - return UTF8ToString(Module['_BinaryenTableSetGetTable'](expr)); - }, - 'setTable'(expr, name) { - preserveStack(() => { Module['_BinaryenTableSetSetTable'](expr, strToStack(name)) }); - }, - 'getIndex'(expr) { - return Module['_BinaryenTableSetGetIndex'](expr); - }, - 'setIndex'(expr, indexExpr) { - Module['_BinaryenTableSetSetIndex'](expr, indexExpr); - }, - 'getValue'(expr) { - return Module['_BinaryenTableSetGetValue'](expr); - }, - 'setValue'(expr, valueExpr) { - Module['_BinaryenTableSetSetValue'](expr, valueExpr); - } -}); - -Module['TableSize'] = makeExpressionWrapper({ - 'getTable'(expr) { - return UTF8ToString(Module['_BinaryenTableSizeGetTable'](expr)); - }, - 'setTable'(expr, name) { - preserveStack(() => { Module['_BinaryenTableSizeSetTable'](expr, strToStack(name)) }); - }, -}); - -Module['TableGrow'] = makeExpressionWrapper({ - 'getTable'(expr) { - return UTF8ToString(Module['_BinaryenTableGrowGetTable'](expr)); - }, - 'setTable'(expr, name) { - preserveStack(() => { Module['_BinaryenTableGrowSetTable'](expr, strToStack(name)) }); - }, - 'getValue'(expr) { - return Module['_BinaryenTableGrowGetValue'](expr); - }, - 'setValue'(expr, valueExpr) { - Module['_BinaryenTableGrowSetValue'](expr, valueExpr); - }, - 'getDelta'(expr) { - return Module['_BinaryenTableGrowGetDelta'](expr); - }, - 'setDelta'(expr, deltaExpr) { - Module['_BinaryenTableGrowSetDelta'](expr, deltaExpr); - } -}); - Module['MemorySize'] = makeExpressionWrapper({}); Module['MemoryGrow'] = makeExpressionWrapper({ @@ -4386,48 +4071,6 @@ } }); -Module['SIMDLoadStoreLane'] = makeExpressionWrapper({ - 'getOp'(expr) { - return Module['_BinaryenSIMDLoadStoreLaneGetOp'](expr); - }, - 'setOp'(expr, op) { - Module['_BinaryenSIMDLoadStoreLaneSetOp'](expr, op); - }, - 'getOffset'(expr) { - return Module['_BinaryenSIMDLoadStoreLaneGetOffset'](expr); - }, - 'setOffset'(expr, offset) { - Module['_BinaryenSIMDLoadStoreLaneSetOffset'](expr, offset); - }, - 'getAlign'(expr) { - return Module['_BinaryenSIMDLoadStoreLaneGetAlign'](expr); - }, - 'setAlign'(expr, align) { - Module['_BinaryenSIMDLoadStoreLaneSetAlign'](expr, align); - }, - 'getIndex'(expr) { - return Module['_BinaryenSIMDLoadStoreLaneGetIndex'](expr); - }, - 'setIndex'(expr, align) { - Module['_BinaryenSIMDLoadStoreLaneSetIndex'](expr, align); - }, - 'getPtr'(expr) { - return Module['_BinaryenSIMDLoadStoreLaneGetPtr'](expr); - }, - 'setPtr'(expr, ptrExpr) { - Module['_BinaryenSIMDLoadStoreLaneSetPtr'](expr, ptrExpr); - }, - 'getVec'(expr) { - return Module['_BinaryenSIMDLoadStoreLaneGetVec'](expr); - }, - 'setVec'(expr, ptrExpr) { - Module['_BinaryenSIMDLoadStoreLaneSetVec'](expr, ptrExpr); - }, - 'isStore'(expr) { - return Boolean(Module['_BinaryenSIMDLoadStoreLaneIsStore'](expr)); - } -}); - Module['MemoryInit'] = makeExpressionWrapper({ 'getSegment'(expr) { return Module['_BinaryenMemoryInitGetSegment'](expr); @@ -4506,33 +4149,12 @@ } }); -Module['RefIs'] = makeExpressionWrapper({ - 'getOp'(expr) { - return Module['_BinaryenRefIsGetOp'](expr); - }, - 'setOp'(expr, op) { - Module['_BinaryenRefIsSetOp'](expr, op); - }, +Module['RefIsNull'] = makeExpressionWrapper({ 'getValue'(expr) { - return Module['_BinaryenRefIsGetValue'](expr); + return Module['_BinaryenRefIsNullGetValue'](expr); }, 'setValue'(expr, valueExpr) { - Module['_BinaryenRefIsSetValue'](expr, valueExpr); - } -}); - -Module['RefAs'] = makeExpressionWrapper({ - 'getOp'(expr) { - return Module['_BinaryenRefAsGetOp'](expr); - }, - 'setOp'(expr, op) { - Module['_BinaryenRefAsSetOp'](expr, op); - }, - 'getValue'(expr) { - return Module['_BinaryenRefAsGetValue'](expr); - }, - 'setValue'(expr, valueExpr) { - Module['_BinaryenRefAsSetValue'](expr, valueExpr); + Module['_BinaryenRefIsNullSetValue'](expr, valueExpr); } }); @@ -4561,99 +4183,54 @@ }); Module['Try'] = makeExpressionWrapper({ - 'getName'(expr) { - const name = Module['_BinaryenTryGetName'](expr); - return name ? UTF8ToString(name) : null; - }, - 'setName'(expr, name) { - preserveStack(() => { Module['_BinaryenTrySetName'](expr, strToStack(name)) }); - }, 'getBody'(expr) { return Module['_BinaryenTryGetBody'](expr); }, 'setBody'(expr, bodyExpr) { Module['_BinaryenTrySetBody'](expr, bodyExpr); }, - 'getNumCatchTags'(expr) { - return Module['_BinaryenTryGetNumCatchTags'](expr); - }, - 'getCatchTags'(expr) { - return getAllNested(expr, Module['_BinaryenTryGetNumCatchTags'], Module['_BinaryenTryGetCatchTagAt']).map(p => UTF8ToString(p)); - }, - 'setCatchTags'(expr, catchTags) { - preserveStack(() => { - setAllNested(expr, catchTags.map(strToStack), Module['_BinaryenTryGetNumCatchTags'], Module['_BinaryenTrySetCatchTagAt'], Module['_BinaryenTryAppendCatchTag'], Module['_BinaryenTryRemoveCatchTagAt']); - }); - }, - 'getCatchTagAt'(expr, index) { - return UTF8ToString(Module['_BinaryenTryGetCatchTagAt'](expr, index)); - }, - 'setCatchTagAt'(expr, index, catchTag) { - preserveStack(() => { Module['_BinaryenTrySetCatchTagAt'](expr, index, strToStack(catchTag)) }); - }, - 'appendCatchTag'(expr, catchTag) { - preserveStack(() => Module['_BinaryenTryAppendCatchTag'](expr, strToStack(catchTag))); - }, - 'insertCatchTagAt'(expr, index, catchTag) { - preserveStack(() => { Module['_BinaryenTryInsertCatchTagAt'](expr, index, strToStack(catchTag)) }); - }, - 'removeCatchTagAt'(expr, index) { - return UTF8ToString(Module['_BinaryenTryRemoveCatchTagAt'](expr, index)); - }, - 'getNumCatchBodies'(expr) { - return Module['_BinaryenTryGetNumCatchBodies'](expr); - }, - 'getCatchBodies'(expr) { - return getAllNested(expr, Module['_BinaryenTryGetNumCatchBodies'], Module['_BinaryenTryGetCatchBodyAt']); - }, - 'setCatchBodies'(expr, catchBodies) { - setAllNested(expr, catchBodies, Module['_BinaryenTryGetNumCatchBodies'], Module['_BinaryenTrySetCatchBodyAt'], Module['_BinaryenTryAppendCatchBody'], Module['_BinaryenTryRemoveCatchBodyAt']); - }, - 'getCatchBodyAt'(expr, index) { - return Module['_BinaryenTryGetCatchBodyAt'](expr, index); - }, - 'setCatchBodyAt'(expr, index, catchExpr) { - Module['_BinaryenTrySetCatchBodyAt'](expr, index, catchExpr); - }, - 'appendCatchBody'(expr, catchExpr) { - return Module['_BinaryenTryAppendCatchBody'](expr, catchExpr); + 'getCatchBody'(expr) { + return Module['_BinaryenTryGetCatchBody'](expr); }, - 'insertCatchBodyAt'(expr, index, catchExpr) { - Module['_BinaryenTryInsertCatchBodyAt'](expr, index, catchExpr); - }, - 'removeCatchBodyAt'(expr, index) { - return Module['_BinaryenTryRemoveCatchBodyAt'](expr, index); - }, - 'hasCatchAll'(expr) { - return Boolean(Module['_BinaryenTryHasCatchAll'](expr)); - }, - 'getDelegateTarget'(expr) { - const name = Module['_BinaryenTryGetDelegateTarget'](expr); - return name ? UTF8ToString(name) : null; - }, - 'setDelegateTarget'(expr, name) { - preserveStack(() => { Module['_BinaryenTrySetDelegateTarget'](expr, strToStack(name)) }); - }, - 'isDelegate'(expr) { - return Boolean(Module['_BinaryenTryIsDelegate'](expr)); + 'setCatchBody'(expr, catchBodyExpr) { + Module['_BinaryenTrySetCatchBody'](expr, catchBodyExpr); } }); Module['Throw'] = makeExpressionWrapper({ - 'getTag'(expr) { - return UTF8ToString(Module['_BinaryenThrowGetTag'](expr)); + 'getEvent'(expr) { + return UTF8ToString(Module['_BinaryenThrowGetEvent'](expr)); }, - 'setTag'(expr, tagName) { - preserveStack(() => { Module['_BinaryenThrowSetTag'](expr, strToStack(tagName)) }); + 'setEvent'(expr, eventName) { + preserveStack(() => { Module['_BinaryenThrowSetEvent'](expr, strToStack(eventName)) }); }, 'getNumOperands'(expr) { return Module['_BinaryenThrowGetNumOperands'](expr); }, 'getOperands'(expr) { - return getAllNested(expr, Module['_BinaryenThrowGetNumOperands'], Module['_BinaryenThrowGetOperandAt']); + const numOperands = Module['_BinaryenThrowGetNumOperands'](expr); + const operands = new Array(numOperands); + let index = 0; + while (index < numOperands) { + operands[index] = Module['_BinaryenThrowGetOperandAt'](expr, index++); + } + return operands; }, 'setOperands'(expr, operands) { - setAllNested(expr, operands, Module['_BinaryenThrowGetNumOperands'], Module['_BinaryenThrowSetOperandAt'], Module['_BinaryenThrowAppendOperand'], Module['_BinaryenThrowRemoveOperandAt']); + const numOperands = operands.length; + let prevNumOperands = Module['_BinaryenThrowGetNumOperands'](expr); + let index = 0; + while (index < numOperands) { + if (index < prevNumOperands) { + Module['_BinaryenThrowSetOperandAt'](expr, index, operands[index]); + } else { + Module['_BinaryenThrowAppendOperand'](expr, operands[index]); + } + ++index; + } + while (prevNumOperands > index) { + Module['_BinaryenThrowRemoveOperandAt'](expr, --prevNumOperands); + } }, 'getOperandAt'(expr, index) { return Module['_BinaryenThrowGetOperandAt'](expr, index); @@ -4673,12 +4250,32 @@ }); Module['Rethrow'] = makeExpressionWrapper({ - 'getTarget'(expr) { - const target = Module['_BinaryenRethrowGetTarget'](expr); - return target ? UTF8ToString(target) : null; + 'getExnref'(expr) { + return Module['_BinaryenRethrowGetExnref'](expr); }, - 'setTarget'(expr, target) { - preserveStack(() => { Module['_BinaryenRethrowSetTarget'](expr, strToStack(target)) }); + 'setExnref'(expr, exnrefExpr) { + Module['_BinaryenRethrowSetExnref'](expr, exnrefExpr); + } +}); + +Module['BrOnExn'] = makeExpressionWrapper({ + 'getEvent'(expr) { + return UTF8ToString(Module['_BinaryenBrOnExnGetEvent'](expr)); + }, + 'setEvent'(expr, eventName) { + preserveStack(() => { Module['_BinaryenBrOnExnSetEvent'](expr, strToStack(eventName)) }); + }, + 'getName'(expr) { + return UTF8ToString(Module['_BinaryenBrOnExnGetName'](expr)); + }, + 'setName'(expr, name) { + preserveStack(() => { Module['_BinaryenBrOnExnSetName'](expr, strToStack(name)) }); + }, + 'getExnref'(expr) { + return Module['_BinaryenBrOnExnGetExnref'](expr); + }, + 'setExnref'(expr, exnrefExpr) { + Module['_BinaryenBrOnExnSetExnref'](expr, exnrefExpr); } }); @@ -4687,10 +4284,29 @@ return Module['_BinaryenTupleMakeGetNumOperands'](expr); }, 'getOperands'(expr) { - return getAllNested(expr, Module['_BinaryenTupleMakeGetNumOperands'], Module['_BinaryenTupleMakeGetOperandAt']); + const numOperands = Module['_BinaryenTupleMakeGetNumOperands'](expr); + const operands = new Array(numOperands); + let index = 0; + while (index < numOperands) { + operands[index] = Module['_BinaryenTupleMakeGetOperandAt'](expr, index++); + } + return operands; }, 'setOperands'(expr, operands) { - setAllNested(expr, operands, Module['_BinaryenTupleMakeGetNumOperands'], Module['_BinaryenTupleMakeSetOperandAt'], Module['_BinaryenTupleMakeAppendOperand'], Module['_BinaryenTupleMakeRemoveOperandAt']); + const numOperands = operands.length; + let prevNumOperands = Module['_BinaryenTupleMakeGetNumOperands'](expr); + let index = 0; + while (index < numOperands) { + if (index < prevNumOperands) { + Module['_BinaryenTupleMakeSetOperandAt'](expr, index, operands[index]); + } else { + Module['_BinaryenTupleMakeAppendOperand'](expr, operands[index]); + } + ++index; + } + while (prevNumOperands > index) { + Module['_BinaryenTupleMakeRemoveOperandAt'](expr, --prevNumOperands); + } }, 'getOperandAt'(expr, index) { return Module['_BinaryenTupleMakeGetOperandAt'](expr, index); @@ -4810,12 +4426,46 @@ if (status != 0) throw new Error('exiting due to error: ' + status); }; +// Indicates if Binaryen has been loaded and is ready +Module['isReady'] = runtimeInitialized; + +// Provide a mechanism to tell when the module is ready +// +// if (!binaryen.isReady) await binaryen.ready; +// ... +// +let pendingPromises = []; +let initializeError = null; + +Object.defineProperty(Module, 'ready', { + get() { + return new Promise((resolve, reject) => { + if (initializeError) { + reject(initializeError); + } else if (runtimeInitialized) { + resolve(Module); + } else { + pendingPromises.push({ resolve, reject }); + } + }); + } +}); + // Intercept the onRuntimeInitialized hook if necessary if (runtimeInitialized) { initializeConstants(); } else { Module['onRuntimeInitialized'] = (super_ => () => { - initializeConstants(); - if (super_) super_(); + try { + initializeConstants(); + if (super_) super_(); + Module['isReady'] = true; + pendingPromises.forEach(p => { p.resolve(Module) }); + } catch (e) { + initializeError = e; + pendingPromises.forEach(p => { p.reject(e) }); + } finally { + pendingPromises = []; + } })(Module['onRuntimeInitialized']); } diff -Nru binaryen-108/src/literal.h binaryen-99/src/literal.h --- binaryen-108/src/literal.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/literal.h 2021-01-07 20:01:06.000000000 +0000 @@ -19,7 +19,6 @@ #include #include -#include #include "compiler-support.h" #include "support/hash.h" @@ -31,8 +30,11 @@ namespace wasm { class Literals; +struct ExceptionPackage; struct GCData; -struct RttSupers; +// Subclass the vector type so that this is not easily confused with a vector of +// types (which could be confusing on the Literal constructor). +struct RttSupers : std::vector {}; class Literal { // store only integers, whose bits are deterministic. floats @@ -43,6 +45,8 @@ uint8_t v128[16]; // funcref function name. `isNull()` indicates a `null` value. Name func; + // exnref package. `nullptr` indicates a `null` value. + std::unique_ptr exn; // A reference to GC data, either a Struct or an Array. For both of those // we store the referred data as a Literals object (which is natural for an // Array, and for a Struct, is just the fields in order). The type is used @@ -60,11 +64,9 @@ // would do, but it is simple.) // The unique_ptr here is to avoid increasing the size of the union as well // as the Literal class itself. - // To support the experimental RttFreshSub instruction, we not only store - // the type, but also a reference to an allocation. std::unique_ptr rttSupers; - // TODO: Literals of type `anyref` can only be `null` currently but we - // will need to represent external values eventually, to + // TODO: Literals of type `externref` can only be `null` currently but we + // will need to represent extern values eventually, to // 1) run the spec tests and fuzzer with reference types enabled and // 2) avoid bailing out when seeing a reference typed value in precompute }; @@ -92,23 +94,25 @@ explicit Literal(const std::array&); explicit Literal(const std::array&); explicit Literal(Name func, Type type) : func(func), type(type) {} + explicit Literal(std::unique_ptr&& exn) + : exn(std::move(exn)), type(Type::exnref) {} explicit Literal(std::shared_ptr gcData, Type type); explicit Literal(std::unique_ptr&& rttSupers, Type type); Literal(const Literal& other); Literal& operator=(const Literal& other); ~Literal(); - bool isConcrete() const { return type.isConcrete(); } + bool isConcrete() const { return type != Type::none; } bool isNone() const { return type == Type::none; } - bool isFunction() const { return type.isFunction(); } - bool isData() const { return type.isData(); } - bool isNull() const { if (type.isNullable()) { if (type.isFunction()) { return func.isNull(); } - if (isData()) { + if (type.isException()) { + return !exn; + } + if (isGCData()) { return !gcData; } return true; @@ -175,6 +179,7 @@ WASM_UNREACHABLE("unexpected type"); } } + bool isGCData() const { return type.isStruct() || type.isArray(); } static Literals makeZeros(Type type); static Literals makeOnes(Type type); @@ -255,16 +260,15 @@ static Literal makeFunc(Name func, Type type = Type::funcref) { return Literal(func, type); } + static Literal makeExn(std::unique_ptr&& exn) { + return Literal(std::move(exn)); + } static Literal makeI31(int32_t value) { auto lit = Literal(Type::i31ref); lit.i32 = value & 0x7fffffff; return lit; } - // Get the canonical RTT value for a given HeapType. For nominal types, the - // canonical RTT reflects the static supertype chain. - static Literal makeCanonicalRtt(HeapType type); - Literal castToF32(); Literal castToF64(); Literal castToI32(); @@ -275,7 +279,7 @@ return i32; } int32_t geti31(bool signed_ = true) const { - assert(type.getHeapType() == HeapType::i31); + assert(type == Type::i31ref); return signed_ ? (i32 << 1) >> 1 : i32; } int64_t geti64() const { @@ -295,6 +299,7 @@ assert(type.isFunction() && !func.isNull()); return func; } + ExceptionPackage getExceptionPackage() const; std::shared_ptr getGCData() const; const RttSupers& getRttSupers() const; @@ -425,11 +430,6 @@ Literal pmax(const Literal& other) const; Literal copysign(const Literal& other) const; - // Fused multiply add and subtract. - // Computes this + (left * right) to infinite precision then round once. - Literal fma(const Literal& left, const Literal& right) const; - Literal fms(const Literal& left, const Literal& right) const; - std::array getLanesSI8x16() const; std::array getLanesUI8x16() const; std::array getLanesSI16x8() const; @@ -492,11 +492,6 @@ Literal geSI32x4(const Literal& other) const; Literal geUI32x4(const Literal& other) const; Literal eqI64x2(const Literal& other) const; - Literal neI64x2(const Literal& other) const; - Literal ltSI64x2(const Literal& other) const; - Literal gtSI64x2(const Literal& other) const; - Literal leSI64x2(const Literal& other) const; - Literal geSI64x2(const Literal& other) const; Literal eqF32x4(const Literal& other) const; Literal neF32x4(const Literal& other) const; Literal ltF32x4(const Literal& other) const; @@ -513,10 +508,10 @@ Literal andV128(const Literal& other) const; Literal orV128(const Literal& other) const; Literal xorV128(const Literal& other) const; - Literal anyTrueV128() const; Literal bitselectV128(const Literal& left, const Literal& right) const; Literal absI8x16() const; Literal negI8x16() const; + Literal anyTrueI8x16() const; Literal allTrueI8x16() const; Literal bitmaskI8x16() const; Literal shlI8x16(const Literal& other) const; @@ -528,6 +523,7 @@ Literal subI8x16(const Literal& other) const; Literal subSaturateSI8x16(const Literal& other) const; Literal subSaturateUI8x16(const Literal& other) const; + Literal mulI8x16(const Literal& other) const; Literal minSI8x16(const Literal& other) const; Literal minUI8x16(const Literal& other) const; Literal maxSI8x16(const Literal& other) const; @@ -536,6 +532,7 @@ Literal popcntI8x16() const; Literal absI16x8() const; Literal negI16x8() const; + Literal anyTrueI16x8() const; Literal allTrueI16x8() const; Literal bitmaskI16x8() const; Literal shlI16x8(const Literal& other) const; @@ -560,6 +557,7 @@ Literal extMulHighUI16x8(const Literal& other) const; Literal absI32x4() const; Literal negI32x4() const; + Literal anyTrueI32x4() const; Literal allTrueI32x4() const; Literal bitmaskI32x4() const; Literal shlI32x4(const Literal& other) const; @@ -572,17 +570,12 @@ Literal minUI32x4(const Literal& other) const; Literal maxSI32x4(const Literal& other) const; Literal maxUI32x4(const Literal& other) const; - Literal dotSI8x16toI16x8(const Literal& other) const; - Literal dotUI8x16toI16x8(const Literal& other) const; Literal dotSI16x8toI32x4(const Literal& other) const; Literal extMulLowSI32x4(const Literal& other) const; Literal extMulHighSI32x4(const Literal& other) const; Literal extMulLowUI32x4(const Literal& other) const; Literal extMulHighUI32x4(const Literal& other) const; - Literal absI64x2() const; Literal negI64x2() const; - Literal bitmaskI64x2() const; - Literal allTrueI64x2() const; Literal shlI64x2(const Literal& other) const; Literal shrSI64x2(const Literal& other) const; Literal shrUI64x2(const Literal& other) const; @@ -623,41 +616,27 @@ Literal floorF64x2() const; Literal truncF64x2() const; Literal nearestF64x2() const; - Literal extAddPairwiseToSI16x8() const; - Literal extAddPairwiseToUI16x8() const; - Literal extAddPairwiseToSI32x4() const; - Literal extAddPairwiseToUI32x4() const; Literal truncSatToSI32x4() const; Literal truncSatToUI32x4() const; + Literal truncSatToSI64x2() const; + Literal truncSatToUI64x2() const; Literal convertSToF32x4() const; Literal convertUToF32x4() const; - Literal narrowSToI8x16(const Literal& other) const; - Literal narrowUToI8x16(const Literal& other) const; - Literal narrowSToI16x8(const Literal& other) const; - Literal narrowUToI16x8(const Literal& other) const; - Literal extendLowSToI16x8() const; - Literal extendHighSToI16x8() const; - Literal extendLowUToI16x8() const; - Literal extendHighUToI16x8() const; - Literal extendLowSToI32x4() const; - Literal extendHighSToI32x4() const; - Literal extendLowUToI32x4() const; - Literal extendHighUToI32x4() const; - Literal extendLowSToI64x2() const; - Literal extendHighSToI64x2() const; - Literal extendLowUToI64x2() const; - Literal extendHighUToI64x2() const; - Literal convertLowSToF64x2() const; - Literal convertLowUToF64x2() const; - Literal truncSatZeroSToI32x4() const; - Literal truncSatZeroUToI32x4() const; - Literal demoteZeroToF32x4() const; - Literal promoteLowToF64x2() const; - Literal swizzleI8x16(const Literal& other) const; - Literal relaxedFmaF32x4(const Literal& left, const Literal& right) const; - Literal relaxedFmsF32x4(const Literal& left, const Literal& right) const; - Literal relaxedFmaF64x2(const Literal& left, const Literal& right) const; - Literal relaxedFmsF64x2(const Literal& left, const Literal& right) const; + Literal convertSToF64x2() const; + Literal convertUToF64x2() const; + Literal narrowSToVecI8x16(const Literal& other) const; + Literal narrowUToVecI8x16(const Literal& other) const; + Literal narrowSToVecI16x8(const Literal& other) const; + Literal narrowUToVecI16x8(const Literal& other) const; + Literal widenLowSToVecI16x8() const; + Literal widenHighSToVecI16x8() const; + Literal widenLowUToVecI16x8() const; + Literal widenHighUToVecI16x8() const; + Literal widenLowSToVecI32x4() const; + Literal widenHighSToVecI32x4() const; + Literal widenLowUToVecI32x4() const; + Literal widenHighUToVecI32x4() const; + Literal swizzleVec8x16(const Literal& other) const; // Checks if an RTT value is a sub-rtt of another, that is, whether GC data // with this object's RTT can be successfuly cast using the other RTT @@ -673,7 +652,6 @@ Literal subSatUI8(const Literal& other) const; Literal subSatSI16(const Literal& other) const; Literal subSatUI16(const Literal& other) const; - Literal q15MulrSatSI16(const Literal& other) const; Literal minInt(const Literal& other) const; Literal maxInt(const Literal& other) const; Literal minUInt(const Literal& other) const; @@ -695,12 +673,6 @@ Literals(size_t initialSize) : SmallVector(initialSize) {} Type getType() { - if (empty()) { - return Type::none; - } - if (size() == 1) { - return (*this)[0].type; - } std::vector types; for (auto& val : *this) { types.push_back(val.type); @@ -711,44 +683,31 @@ bool isConcrete() { return size() != 0; } }; +// A struct for a thrown exception, which includes a tag (event) and thrown +// values +struct ExceptionPackage { + Name event; + Literals values; + bool operator==(const ExceptionPackage& other) const { + return event == other.event && values == other.values; + } + bool operator!=(const ExceptionPackage& other) const { + return !(*this == other); + } +}; + std::ostream& operator<<(std::ostream& o, wasm::Literal literal); std::ostream& operator<<(std::ostream& o, wasm::Literals literals); +std::ostream& operator<<(std::ostream& o, const ExceptionPackage& exn); // A GC Struct or Array is a set of values with a run-time type saying what it -// is. In the case of static (rtt-free) typing, the rtt is not present and -// instead we have a static type. +// is. struct GCData { - // The runtime type info for this struct or array. Literal rtt; - - // The element or field values. Literals values; - GCData(Literal rtt, Literals values) : rtt(rtt), values(values) {} }; -struct RttSuper { - // The type of the super. - HeapType type; - // A shared allocation, used to implement rtt.fresh_sub. This is null for a - // normal sub, and for a fresh one we allocate a value here, which can then be - // used to differentiate rtts. (The allocation is shared so that when copying - // an rtt we remain equal.) - // TODO: Remove or optimize this when the spec stabilizes. - std::shared_ptr freshPtr; - - RttSuper(HeapType type) : type(type) {} - - void makeFresh() { freshPtr = std::make_shared(); } - - bool operator==(const RttSuper& other) const { - return type == other.type && freshPtr == other.freshPtr; - } - bool operator!=(const RttSuper& other) const { return !(*this == other); } -}; - -struct RttSupers : std::vector {}; - } // namespace wasm namespace std { @@ -764,8 +723,15 @@ wasm::rehash(digest, a.getFunc()); return digest; } + if (a.type.isException()) { + auto exn = a.getExceptionPackage(); + wasm::rehash(digest, exn.event); + wasm::rehash(digest, exn.values); + return digest; + } // other non-null reference type literals cannot represent concrete - // values, i.e. there is no concrete anyref or eqref other than null. + // values, i.e. there is no concrete externref, anyref or eqref other than + // null. WASM_UNREACHABLE("unexpected type"); }; if (a.type.isBasic()) { @@ -789,9 +755,10 @@ wasm::rehash(digest, chunks[1]); return digest; case wasm::Type::funcref: + case wasm::Type::externref: + case wasm::Type::exnref: case wasm::Type::anyref: case wasm::Type::eqref: - case wasm::Type::dataref: return hashRef(); case wasm::Type::i31ref: wasm::rehash(digest, a.geti31(true)); @@ -806,8 +773,7 @@ const auto& supers = a.getRttSupers(); wasm::rehash(digest, supers.size()); for (auto super : supers) { - wasm::rehash(digest, super.type.getID()); - wasm::rehash(digest, uintptr_t(super.freshPtr.get())); + wasm::rehash(digest, super.getID()); } return digest; } @@ -823,7 +789,39 @@ return digest; } }; - +template<> struct less { + bool operator()(const wasm::Literal& a, const wasm::Literal& b) const { + if (a.type < b.type) { + return true; + } + if (b.type < a.type) { + return false; + } + TODO_SINGLE_COMPOUND(a.type); + switch (a.type.getBasic()) { + case wasm::Type::i32: + return a.geti32() < b.geti32(); + case wasm::Type::f32: + return a.reinterpreti32() < b.reinterpreti32(); + case wasm::Type::i64: + return a.geti64() < b.geti64(); + case wasm::Type::f64: + return a.reinterpreti64() < b.reinterpreti64(); + case wasm::Type::v128: + return memcmp(a.getv128Ptr(), b.getv128Ptr(), 16) < 0; + case wasm::Type::funcref: + case wasm::Type::externref: + case wasm::Type::exnref: + case wasm::Type::anyref: + case wasm::Type::eqref: + case wasm::Type::i31ref: + case wasm::Type::none: + case wasm::Type::unreachable: + return false; + } + WASM_UNREACHABLE("unexpected type"); + } +}; } // namespace std #endif // wasm_literal_h diff -Nru binaryen-108/src/mixed_arena.h binaryen-99/src/mixed_arena.h --- binaryen-108/src/mixed_arena.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/mixed_arena.h 2021-01-07 20:01:06.000000000 +0000 @@ -104,7 +104,7 @@ if (!allocated) { allocated = new MixedArena(); // has our thread id } - if (curr->next.compare_exchange_strong(seen, allocated)) { + if (curr->next.compare_exchange_weak(seen, allocated)) { // we replaced it, so we are the next in the chain // we can forget about allocated, it is owned by the chain now allocated = nullptr; @@ -368,21 +368,21 @@ // C-API void insertAt(size_t index, T item) { - assert(index <= size()); // appending is ok - resize(size() + 1); - for (auto i = size() - 1; i > index; --i) { + assert(index <= usedElements); // appending is ok + resize(usedElements + 1); + for (auto i = usedElements; i > index; --i) { data[i] = data[i - 1]; } data[index] = item; } T removeAt(size_t index) { - assert(index < size()); + assert(index < usedElements); auto item = data[index]; - for (auto i = index; i < size() - 1; ++i) { + for (auto i = index; i < usedElements - 1; ++i) { data[i] = data[i + 1]; } - resize(size() - 1); + resize(usedElements - 1); return item; } }; diff -Nru binaryen-108/src/parsing.h binaryen-99/src/parsing.h --- binaryen-108/src/parsing.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/parsing.h 2021-01-07 20:01:06.000000000 +0000 @@ -40,7 +40,21 @@ ParseException(std::string text, size_t line, size_t col) : text(text), line(line), col(col) {} - void dump(std::ostream& o) const; + void dump(std::ostream& o) const { + Colors::magenta(o); + o << "["; + Colors::red(o); + o << "parse exception: "; + Colors::green(o); + o << text; + if (line != size_t(-1)) { + Colors::normal(o); + o << " (at " << line << ":" << col << ")"; + } + Colors::magenta(o); + o << "]"; + Colors::normal(o); + } }; struct MapParseException { @@ -49,9 +63,224 @@ MapParseException() : text("unknown parse error") {} MapParseException(std::string text) : text(text) {} - void dump(std::ostream& o) const; + void dump(std::ostream& o) const { + Colors::magenta(o); + o << "["; + Colors::red(o); + o << "map parse exception: "; + Colors::green(o); + o << text; + Colors::magenta(o); + o << "]"; + Colors::normal(o); + } }; +inline Expression* +parseConst(cashew::IString s, Type type, MixedArena& allocator) { + const char* str = s.str; + auto ret = allocator.alloc(); + ret->type = type; + if (type.isFloat()) { + if (s == _INFINITY) { + switch (type.getBasic()) { + case Type::f32: + ret->value = Literal(std::numeric_limits::infinity()); + break; + case Type::f64: + ret->value = Literal(std::numeric_limits::infinity()); + break; + default: + return nullptr; + } + // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; + return ret; + } + if (s == NEG_INFINITY) { + switch (type.getBasic()) { + case Type::f32: + ret->value = Literal(-std::numeric_limits::infinity()); + break; + case Type::f64: + ret->value = Literal(-std::numeric_limits::infinity()); + break; + default: + return nullptr; + } + // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; + return ret; + } + if (s == _NAN) { + switch (type.getBasic()) { + case Type::f32: + ret->value = Literal(float(std::nan(""))); + break; + case Type::f64: + ret->value = Literal(double(std::nan(""))); + break; + default: + return nullptr; + } + // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; + return ret; + } + bool negative = str[0] == '-'; + const char* positive = negative ? str + 1 : str; + if (!negative) { + if (positive[0] == '+') { + positive++; + } + } + if (positive[0] == 'n' && positive[1] == 'a' && positive[2] == 'n') { + const char* modifier = positive[3] == ':' ? positive + 4 : nullptr; + if (!(modifier ? positive[4] == '0' && positive[5] == 'x' : 1)) { + throw ParseException("bad nan input"); + } + switch (type.getBasic()) { + case Type::f32: { + uint32_t pattern; + if (modifier) { + std::istringstream istr(modifier); + istr >> std::hex >> pattern; + if (istr.fail()) { + throw ParseException("invalid f32 format"); + } + pattern |= 0x7f800000U; + } else { + pattern = 0x7fc00000U; + } + if (negative) { + pattern |= 0x80000000U; + } + if (!std::isnan(bit_cast(pattern))) { + pattern |= 1U; + } + ret->value = Literal(pattern).castToF32(); + break; + } + case Type::f64: { + uint64_t pattern; + if (modifier) { + std::istringstream istr(modifier); + istr >> std::hex >> pattern; + if (istr.fail()) { + throw ParseException("invalid f64 format"); + } + pattern |= 0x7ff0000000000000ULL; + } else { + pattern = 0x7ff8000000000000UL; + } + if (negative) { + pattern |= 0x8000000000000000ULL; + } + if (!std::isnan(bit_cast(pattern))) { + pattern |= 1ULL; + } + ret->value = Literal(pattern).castToF64(); + break; + } + default: + return nullptr; + } + // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; + return ret; + } + if (s == NEG_NAN) { + switch (type.getBasic()) { + case Type::f32: + ret->value = Literal(float(-std::nan(""))); + break; + case Type::f64: + ret->value = Literal(double(-std::nan(""))); + break; + default: + return nullptr; + } + // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; + return ret; + } + } + switch (type.getBasic()) { + case Type::i32: { + if ((str[0] == '0' && str[1] == 'x') || + (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { + bool negative = str[0] == '-'; + if (negative) { + str++; + } + std::istringstream istr(str); + uint32_t temp; + istr >> std::hex >> temp; + if (istr.fail()) { + throw ParseException("invalid i32 format"); + } + ret->value = Literal(negative ? -temp : temp); + } else { + std::istringstream istr(str[0] == '-' ? str + 1 : str); + uint32_t temp; + istr >> temp; + if (istr.fail()) { + throw ParseException("invalid i32 format"); + } + ret->value = Literal(str[0] == '-' ? -temp : temp); + } + break; + } + case Type::i64: { + if ((str[0] == '0' && str[1] == 'x') || + (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { + bool negative = str[0] == '-'; + if (negative) { + str++; + } + std::istringstream istr(str); + uint64_t temp; + istr >> std::hex >> temp; + if (istr.fail()) { + throw ParseException("invalid i64 format"); + } + ret->value = Literal(negative ? -temp : temp); + } else { + std::istringstream istr(str[0] == '-' ? str + 1 : str); + uint64_t temp; + istr >> temp; + if (istr.fail()) { + throw ParseException("invalid i64 format"); + } + ret->value = Literal(str[0] == '-' ? -temp : temp); + } + break; + } + case Type::f32: { + char* end; + ret->value = Literal(strtof(str, &end)); + break; + } + case Type::f64: { + char* end; + ret->value = Literal(strtod(str, &end)); + break; + } + case Type::v128: + case Type::funcref: + case Type::externref: + case Type::exnref: + case Type::anyref: + case Type::eqref: + case Type::i31ref: + WASM_UNREACHABLE("unexpected const type"); + case Type::none: + case Type::unreachable: { + return nullptr; + } + } + if (ret->value.type != type) { + throw ParseException("parsed type does not match expected type"); + } + // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; + return ret; +} + // Helper for parsers that may not have unique label names. This transforms // the names into unique ones, as required by Binaryen IR. struct UniqueNameMapper { @@ -62,21 +291,104 @@ Index otherIndex = 0; - Name getPrefixedName(Name prefix); + Name getPrefixedName(Name prefix) { + if (reverseLabelMapping.find(prefix) == reverseLabelMapping.end()) { + return prefix; + } + // make sure to return a unique name not already on the stack + while (1) { + Name ret = Name(prefix.str + std::to_string(otherIndex++)); + if (reverseLabelMapping.find(ret) == reverseLabelMapping.end()) { + return ret; + } + } + } // receives a source name. generates a unique name, pushes it, and returns it - Name pushLabelName(Name sName); - - void popLabelName(Name name); - - Name sourceToUnique(Name sName); - - Name uniqueToSource(Name name); - - void clear(); + Name pushLabelName(Name sName) { + Name name = getPrefixedName(sName); + labelStack.push_back(name); + labelMappings[sName].push_back(name); + reverseLabelMapping[name] = sName; + return name; + } + + void popLabelName(Name name) { + assert(labelStack.back() == name); + labelStack.pop_back(); + labelMappings[reverseLabelMapping[name]].pop_back(); + } + + Name sourceToUnique(Name sName) { + if (labelMappings.find(sName) == labelMappings.end()) { + throw ParseException("bad label in sourceToUnique"); + } + if (labelMappings[sName].empty()) { + throw ParseException("use of popped label in sourceToUnique"); + } + return labelMappings[sName].back(); + } + + Name uniqueToSource(Name name) { + if (reverseLabelMapping.find(name) == reverseLabelMapping.end()) { + throw ParseException("label mismatch in uniqueToSource"); + } + return reverseLabelMapping[name]; + } + + void clear() { + labelStack.clear(); + labelMappings.clear(); + reverseLabelMapping.clear(); + } // Given an expression, ensures all names are unique - static void uniquify(Expression* curr); + static void uniquify(Expression* curr) { + struct Walker : public ControlFlowWalker> { + UniqueNameMapper mapper; + + static void doPreVisitControlFlow(Walker* self, Expression** currp) { + auto* curr = *currp; + if (auto* block = curr->dynCast()) { + if (block->name.is()) { + block->name = self->mapper.pushLabelName(block->name); + } + } else if (auto* loop = curr->dynCast()) { + if (loop->name.is()) { + loop->name = self->mapper.pushLabelName(loop->name); + } + } + } + static void doPostVisitControlFlow(Walker* self, Expression** currp) { + auto* curr = *currp; + if (auto* block = curr->dynCast()) { + if (block->name.is()) { + self->mapper.popLabelName(block->name); + } + } else if (auto* loop = curr->dynCast()) { + if (loop->name.is()) { + self->mapper.popLabelName(loop->name); + } + } + } + + void visitBreak(Break* curr) { + curr->name = mapper.sourceToUnique(curr->name); + } + void visitBrOnExn(BrOnExn* curr) { + curr->name = mapper.sourceToUnique(curr->name); + } + void visitSwitch(Switch* curr) { + for (auto& target : curr->targets) { + target = mapper.sourceToUnique(target); + } + curr->default_ = mapper.sourceToUnique(curr->default_); + } + }; + + Walker walker; + walker.walk(curr); + } }; } // namespace wasm diff -Nru binaryen-108/src/passes/Asyncify.cpp binaryen-99/src/passes/Asyncify.cpp --- binaryen-108/src/passes/Asyncify.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Asyncify.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -296,11 +296,9 @@ // of their original range. // -#include "asmjs/shared-constants.h" #include "cfg/liveness-traversal.h" #include "ir/effects.h" #include "ir/find_all.h" -#include "ir/linear-execution.h" #include "ir/literal-utils.h" #include "ir/memory-utils.h" #include "ir/module-utils.h" @@ -382,8 +380,8 @@ } private: - std::unordered_map map; - std::unordered_map rev; + std::map map; + std::map rev; // Collect the types returned from all calls for which call support globals // may need to be generated. @@ -631,7 +629,9 @@ }); // Functions in the remove-list are assumed to not change the state. - for (auto& [func, info] : scanner.map) { + for (auto& pair : scanner.map) { + auto* func = pair.first; + auto& info = pair.second; if (removeList.match(func->name)) { info.inRemoveList = true; if (verbose && info.canChangeState) { @@ -644,8 +644,9 @@ // Remove the asyncify imports, if any, and any calls to them. std::vector funcsToDelete; - for (auto& [func, info] : scanner.map) { - auto& callsTo = info.callsTo; + for (auto& pair : scanner.map) { + auto* func = pair.first; + auto& callsTo = pair.second.callsTo; if (func->imported() && func->module == ASYNCIFY) { funcsToDelete.push_back(func->name); } @@ -860,7 +861,7 @@ State::Rewinding), // TODO: such checks can be !normal makeCallIndexPop()), process(func->body)}); - if (func->getResults() != Type::none) { + if (func->sig.results != Type::none) { // Rewriting control flow may alter things; make sure the function ends in // something valid (which the optimizer can remove later). block->list.push_back(builder->makeUnreachable()); @@ -882,6 +883,9 @@ Index callIndex = 0; Expression* process(Expression* curr) { + if (!analyzer->canChangeState(curr, func)) { + return makeMaybeSkip(curr); + } // The IR is in flat form, which makes this much simpler: there are no // unnecessarily nested side effects or control flow, so we can add // skips for rewinding in an easy manner, putting a single if around @@ -915,164 +919,85 @@ // Note that temp locals added in this way are just normal locals, and in // particular they are saved and loaded. That way if we resume from the // first if arm we will avoid the second. - - // To avoid recursion, we use stacks here. We process the work for each - // node in two phases as follows: - // - // 1. The "Scan" phase finds children we need to process (ones that may - // change the state), and adds Scan tasks for them to the work stack. - // 2. The "Finish" phase runs after all children have been Scanned and - // Finished. It pops the children's results from the results stack (if - // there were relevant children), and then it pushes its own result. - // - struct Work { - Expression* curr; - enum { Scan, Finish } phase; - }; - - std::vector work; - std::vector results; - std::unordered_set processed; - - work.push_back(Work{curr, Work::Scan}); - - while (!work.empty()) { - auto item = work.back(); - work.pop_back(); - processed.insert(item.curr); - auto* curr = item.curr; - auto phase = item.phase; - - if (phase == Work::Scan && !analyzer->canChangeState(curr, func)) { - results.push_back(makeMaybeSkip(curr)); - continue; - } - - if (auto* block = curr->dynCast()) { - auto& list = block->list; - - // Find the children we need to process. They will be Scanned and - // Finished before we reach our own Finish phase. - if (phase == Work::Scan) { - work.push_back(Work{curr, Work::Finish}); - // Add Scan tasks in reverse order, so that we process them in - // execution order. - for (size_t i = list.size(); i > 0; i--) { - auto* child = list[i - 1]; - if (analyzer->canChangeState(child, func)) { - work.push_back(Work{child, Work::Scan}); - } + if (auto* block = curr->dynCast()) { + // At least one of our children may change the state. Clump them as + // necessary. + Index i = 0; + auto& list = block->list; + while (i < list.size()) { + if (analyzer->canChangeState(list[i], func)) { + list[i] = process(list[i]); + i++; + } else { + Index end = i + 1; + while (end < list.size() && + !analyzer->canChangeState(list[end], func)) { + end++; } - continue; - } - Index i = list.size() - 1; - // At least one of our children may change the state. Clump them as - // necessary. - while (1) { - if (processed.count(list[i])) { - list[i] = results.back(); - results.pop_back(); + // We have a range of [i, end) in which the state cannot change, + // so all we need to do is skip it if rewinding. + if (end == i + 1) { + list[i] = makeMaybeSkip(list[i]); } else { - Index begin = i; - while (begin > 0 && !processed.count(list[begin - 1])) { - begin--; + auto* block = builder->makeBlock(); + for (auto j = i; j < end; j++) { + block->list.push_back(list[j]); } - // We have a range of [begin, i] in which the state cannot change, - // so all we need to do is skip it if rewinding. - if (begin == i) { - list[i] = makeMaybeSkip(list[i]); - } else { - auto* block = builder->makeBlock(); - for (auto j = begin; j <= i; j++) { - block->list.push_back(list[j]); - } - block->finalize(); - list[begin] = makeMaybeSkip(block); - for (auto j = begin + 1; j <= i; j++) { - list[j] = builder->makeNop(); - } + block->finalize(); + list[i] = makeMaybeSkip(block); + for (auto j = i + 1; j < end; j++) { + list[j] = builder->makeNop(); } - i = begin; } - if (i == 0) { - break; - } else { - i--; - } - } - results.push_back(block); - continue; - } else if (auto* iff = curr->dynCast()) { - // The state change cannot be in the condition due to flat form, so it - // must be in one of the children. - assert(!analyzer->canChangeState(iff->condition, func)); - if (item.phase == Work::Scan) { - work.push_back(Work{curr, Work::Finish}); - // Add ifTrue later so that we process it first. - if (iff->ifFalse) { - work.push_back(Work{iff->ifFalse, Work::Scan}); - } - work.push_back(Work{iff->ifTrue, Work::Scan}); - continue; + i = end; } - // We must linearize this, which means we pass through both arms if we - // are rewinding. - if (!iff->ifFalse) { - iff->condition = builder->makeBinary( - OrInt32, iff->condition, builder->makeStateCheck(State::Rewinding)); - iff->ifTrue = results.back(); - results.pop_back(); - iff->finalize(); - results.push_back(iff); - continue; - } - auto* newIfFalse = results.back(); - results.pop_back(); - auto* newIfTrue = results.back(); - results.pop_back(); - auto conditionTemp = builder->addVar(func, Type::i32); - // TODO: can avoid pre if the condition is a get or a const - auto* pre = - makeMaybeSkip(builder->makeLocalSet(conditionTemp, iff->condition)); - iff->condition = builder->makeLocalGet(conditionTemp, Type::i32); + } + return block; + } else if (auto* iff = curr->dynCast()) { + // The state change cannot be in the condition due to flat form, so it + // must be in one of the children. + assert(!analyzer->canChangeState(iff->condition, func)); + // We must linearize this, which means we pass through both arms if we + // are rewinding. + if (!iff->ifFalse) { iff->condition = builder->makeBinary( OrInt32, iff->condition, builder->makeStateCheck(State::Rewinding)); - iff->ifTrue = newIfTrue; - iff->ifFalse = nullptr; + iff->ifTrue = process(iff->ifTrue); iff->finalize(); - // Add support for the second arm as well. - auto* otherIf = builder->makeIf( - builder->makeBinary( - OrInt32, - builder->makeUnary(EqZInt32, - builder->makeLocalGet(conditionTemp, Type::i32)), - builder->makeStateCheck(State::Rewinding)), - newIfFalse); - otherIf->finalize(); - results.push_back(builder->makeBlock({pre, iff, otherIf})); - continue; - } else if (auto* loop = curr->dynCast()) { - if (item.phase == Work::Scan) { - work.push_back(Work{curr, Work::Finish}); - work.push_back(Work{loop->body, Work::Scan}); - continue; - } - loop->body = results.back(); - results.pop_back(); - results.push_back(loop); - continue; - } else if (doesCall(curr)) { - results.push_back(makeCallSupport(curr)); - continue; + return iff; } - // We must handle all control flow above, and all things that can change - // the state, so there should be nothing that can reach here - add it - // earlier as necessary. - // std::cout << *curr << '\n'; - WASM_UNREACHABLE("unexpected expression type"); - } - assert(results.size() == 1); - return results.back(); + auto conditionTemp = builder->addVar(func, Type::i32); + // TODO: can avoid pre if the condition is a get or a const + auto* pre = + makeMaybeSkip(builder->makeLocalSet(conditionTemp, iff->condition)); + iff->condition = builder->makeLocalGet(conditionTemp, Type::i32); + iff->condition = builder->makeBinary( + OrInt32, iff->condition, builder->makeStateCheck(State::Rewinding)); + iff->ifTrue = process(iff->ifTrue); + auto* otherArm = iff->ifFalse; + iff->ifFalse = nullptr; + iff->finalize(); + // Add support for the second arm as well. + auto* otherIf = builder->makeIf( + builder->makeBinary( + OrInt32, + builder->makeUnary(EqZInt32, + builder->makeLocalGet(conditionTemp, Type::i32)), + builder->makeStateCheck(State::Rewinding)), + process(otherArm)); + otherIf->finalize(); + return builder->makeBlock({pre, iff, otherIf}); + } else if (auto* loop = curr->dynCast()) { + loop->body = process(loop->body); + return loop; + } else if (doesCall(curr)) { + return makeCallSupport(curr); + } + // We must handle all control flow above, and all things that can change + // the state, so there should be nothing that can reach here - add it + // earlier as necessary. + // std::cout << *curr << '\n'; + WASM_UNREACHABLE("unexpected expression type"); } // Possibly skip some code, if rewinding. @@ -1278,7 +1203,7 @@ walk(func->body); // After the normal function body, emit a barrier before the postamble. Expression* barrier; - if (func->getResults() == Type::none) { + if (func->sig.results == Type::none) { // The function may have ended without a return; ensure one. barrier = builder->makeReturn(); } else { @@ -1296,12 +1221,12 @@ builder->makeSequence(func->body, barrier))), makeCallIndexPush(unwindIndex), makeLocalSaving()}); - if (func->getResults() != Type::none) { + if (func->sig.results != Type::none) { // If we unwind, we must still "return" a value, even if it will be // ignored on the outside. newBody->list.push_back( - LiteralUtils::makeZero(func->getResults(), *getModule())); - newBody->finalize(func->getResults()); + LiteralUtils::makeZero(func->sig.results, *getModule())); + newBody->finalize(func->sig.results); } func->body = newBody; // Making things like returns conditional may alter types. @@ -1312,7 +1237,7 @@ std::unique_ptr builder; Index rewindIndex; - std::unordered_map fakeCallLocals; + std::map fakeCallLocals; std::set relevantLiveLocals; void findRelevantLiveLocals(Function* func) { @@ -1343,7 +1268,6 @@ }; RelevantLiveLocalsWalker walker; - walker.setFunction(func); walker.walkFunctionInModule(func, getModule()); // The relevant live locals are ones that are alive at an unwind/rewind // location. TODO look more precisely inside basic blocks, as one might stop @@ -1368,7 +1292,7 @@ if (!relevantLiveLocals.count(i)) { continue; } - total += getByteSize(func->getLocalType(i)); + total += func->getLocalType(i).getByteSize(); } auto* block = builder->makeBlock(); block->list.push_back(builder->makeIncStackPos(-total)); @@ -1383,7 +1307,7 @@ auto localType = func->getLocalType(i); SmallVector loads; for (const auto& type : localType) { - auto size = getByteSize(type); + auto size = type.getByteSize(); assert(size % STACK_ALIGN == 0); // TODO: higher alignment? loads.push_back( @@ -1427,7 +1351,7 @@ auto localType = func->getLocalType(i); size_t j = 0; for (const auto& type : localType) { - auto size = getByteSize(type); + auto size = type.getByteSize(); Expression* localGet = builder->makeLocalGet(i, localType); if (localType.size() > 1) { localGet = builder->makeTupleExtract(localGet, j); @@ -1461,15 +1385,6 @@ Type::i32), builder->makeIncStackPos(4)); } - - unsigned getByteSize(Type type) { - if (!type.hasByteSize()) { - Fatal() << "Asyncify does not yet support non-number types, like " - "references (see " - "https://github.com/WebAssembly/binaryen/issues/3739)"; - } - return type.getByteSize(); - } }; } // anonymous namespace @@ -1523,8 +1438,6 @@ runner->options.getArgumentOrDefault("asyncify-asserts", "") != ""; auto verbose = runner->options.getArgumentOrDefault("asyncify-verbose", "") != ""; - auto relocatable = - runner->options.getArgumentOrDefault("asyncify-relocatable", "") != ""; removeList = handleBracketingOperators(removeList); addList = handleBracketingOperators(addList); @@ -1559,7 +1472,7 @@ verbose); // Add necessary globals before we emit code to use them. - addGlobals(module, relocatable); + addGlobals(module); // Instrument the flow of code, adding code instrumentation and // skips for when rewinding. We do this on flat IR so that it is @@ -1614,28 +1527,16 @@ } private: - void addGlobals(Module* module, bool imported) { + void addGlobals(Module* module) { Builder builder(*module); - - auto asyncifyState = builder.makeGlobal(ASYNCIFY_STATE, - Type::i32, - builder.makeConst(int32_t(0)), - Builder::Mutable); - if (imported) { - asyncifyState->module = ENV; - asyncifyState->base = ASYNCIFY_STATE; - } - module->addGlobal(std::move(asyncifyState)); - - auto asyncifyData = builder.makeGlobal(ASYNCIFY_DATA, - Type::i32, - builder.makeConst(int32_t(0)), - Builder::Mutable); - if (imported) { - asyncifyData->module = ENV; - asyncifyData->base = ASYNCIFY_DATA; - } - module->addGlobal(std::move(asyncifyData)); + module->addGlobal(builder.makeGlobal(ASYNCIFY_STATE, + Type::i32, + builder.makeConst(int32_t(0)), + Builder::Mutable)); + module->addGlobal(builder.makeGlobal(ASYNCIFY_DATA, + Type::i32, + builder.makeConst(int32_t(0)), + Builder::Mutable)); } void addFunctions(Module* module) { diff -Nru binaryen-108/src/passes/AvoidReinterprets.cpp binaryen-99/src/passes/AvoidReinterprets.cpp --- binaryen-108/src/passes/AvoidReinterprets.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/AvoidReinterprets.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -40,7 +40,7 @@ static Load* getSingleLoad(LocalGraph* localGraph, LocalGet* get, const PassOptions& passOptions, - Module& module) { + FeatureSet features) { std::set seen; seen.insert(get); while (1) { @@ -52,14 +52,15 @@ if (!set) { return nullptr; } - auto* value = Properties::getFallthrough(set->value, passOptions, module); + auto* value = Properties::getFallthrough(set->value, passOptions, features); if (auto* parentGet = value->dynCast()) { - if (seen.emplace(parentGet).second) { - get = parentGet; - continue; + if (seen.count(parentGet)) { + // We are in a cycle of gets, in unreachable code. + return nullptr; } - // We are in a cycle of gets, in unreachable code. - return nullptr; + get = parentGet; + seen.insert(get); + continue; } if (auto* load = value->dynCast()) { return load; @@ -101,11 +102,12 @@ void visitUnary(Unary* curr) { if (isReinterpret(curr)) { - if (auto* get = Properties::getFallthrough( - curr->value, getPassOptions(), *getModule()) - ->dynCast()) { + FeatureSet features = getModule()->features; + if (auto* get = + Properties::getFallthrough(curr->value, getPassOptions(), features) + ->dynCast()) { if (auto* load = - getSingleLoad(localGraph, get, getPassOptions(), *getModule())) { + getSingleLoad(localGraph, get, getPassOptions(), features)) { auto& info = infos[load]; info.reinterpreted = true; } @@ -116,7 +118,9 @@ void optimize(Function* func) { std::set unoptimizables; auto indexType = getModule()->memory.indexType; - for (auto& [load, info] : infos) { + for (auto& pair : infos) { + auto* load = pair.first; + auto& info = pair.second; if (info.reinterpreted && canReplaceWithReinterpret(load)) { // We should use another load here, to avoid reinterprets. info.ptrLocal = Builder::addVar(func, indexType); @@ -152,8 +156,8 @@ replaceCurrent(makeReinterpretedLoad(load, load->ptr)); } } else if (auto* get = value->dynCast()) { - if (auto* load = - getSingleLoad(localGraph, get, passOptions, *module)) { + if (auto* load = getSingleLoad( + localGraph, get, passOptions, module->features)) { auto iter = infos.find(load); if (iter != infos.end()) { auto& info = iter->second; diff -Nru binaryen-108/src/passes/CMakeLists.txt binaryen-99/src/passes/CMakeLists.txt --- binaryen-108/src/passes/CMakeLists.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/CMakeLists.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,28 +1,20 @@ -file(READ wasm-intrinsics.wat WASM_INTRINSICS_WAT HEX) +# Python 3.5 is the version shipped in Ubuntu Xenial +find_package(PythonInterp 3.5 REQUIRED) -string(REGEX MATCHALL "([A-Fa-f0-9][A-Fa-f0-9])" SEPARATED_HEX ${WASM_INTRINSICS_WAT}) - -set(WASM_INTRINSICS_SIZE 1) -foreach (hex IN LISTS SEPARATED_HEX) - string(APPEND WASM_INTRINSICS_EMBED "0x${hex},") - math(EXPR WASM_INTRINSICS_SIZE "${WASM_INTRINSICS_SIZE}+1") -endforeach () -string(APPEND WASM_INTRINSICS_EMBED "0x00") - -configure_file(WasmIntrinsics.cpp.in WasmIntrinsics.cpp @ONLY) +add_custom_command( + OUTPUT WasmIntrinsics.cpp + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/embedwat.py ${PROJECT_SOURCE_DIR}/src/passes/wasm-intrinsics.wat ${CMAKE_CURRENT_BINARY_DIR}/WasmIntrinsics.cpp + DEPENDS ${PROJECT_SOURCE_DIR}/scripts/embedwat.py wasm-intrinsics.wat) FILE(GLOB passes_HEADERS *.h) set(passes_SOURCES - param-utils.cpp pass.cpp - test_passes.cpp AlignmentLowering.cpp Asyncify.cpp AvoidReinterprets.cpp CoalesceLocals.cpp CodePushing.cpp CodeFolding.cpp - ConstantFieldPropagation.cpp ConstHoisting.cpp DataFlowOpts.cpp DeadArgumentElimination.cpp @@ -37,35 +29,27 @@ Flatten.cpp FuncCastEmulation.cpp GenerateDynCalls.cpp - GlobalRefining.cpp - GlobalTypeOptimization.cpp - Heap2Local.cpp I64ToI32Lowering.cpp Inlining.cpp InstrumentLocals.cpp InstrumentMemory.cpp - Intrinsics.cpp LegalizeJSInterface.cpp LimitSegments.cpp LocalCSE.cpp - LocalSubtyping.cpp LogExecution.cpp LoopInvariantCodeMotion.cpp Memory64Lowering.cpp MemoryPacking.cpp MergeBlocks.cpp - MergeSimilarFunctions.cpp MergeLocals.cpp Metrics.cpp MinifyImportsAndExports.cpp NameList.cpp - NameTypes.cpp - OnceReduction.cpp + NoExitRuntime.cpp OptimizeAddedConstants.cpp OptimizeInstructions.cpp - OptimizeForJS.cpp PickLoadSigns.cpp - Poppify.cpp + PostAssemblyScript.cpp PostEmscripten.cpp Precompute.cpp Print.cpp @@ -73,10 +57,7 @@ PrintFeatures.cpp PrintFunctionMap.cpp RoundTrip.cpp - SetGlobals.cpp StackIR.cpp - SignaturePruning.cpp - SignatureRefining.cpp Strip.cpp StripTargetFeatures.cpp RedundantSetElimination.cpp @@ -90,7 +71,6 @@ ReorderFunctions.cpp ReReloop.cpp TrapMode.cpp - TypeRefining.cpp SafeHeap.cpp SimplifyGlobals.cpp SimplifyLocals.cpp diff -Nru binaryen-108/src/passes/CoalesceLocals.cpp binaryen-99/src/passes/CoalesceLocals.cpp --- binaryen-108/src/passes/CoalesceLocals.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/CoalesceLocals.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -30,12 +30,11 @@ #include #include "cfg/liveness-traversal.h" -#include "ir/numbering.h" #include "ir/utils.h" #include "pass.h" #include "support/learning.h" #include "support/permutations.h" -#include "support/sparse_square_matrix.h" +#include "wasm-builder.h" #include "wasm.h" #ifdef CFG_PROFILE #include "support/timing.h" @@ -47,10 +46,6 @@ : public WalkerPass>> { bool isFunctionParallel() override { return true; } - // This pass merges locals, mapping the originals to new ones. - // FIXME DWARF updating does not handle local changes yet. - bool invalidatesDWARF() override { return true; } - Pass* create() override { return new CoalesceLocals; } // main entry point @@ -59,10 +54,10 @@ void increaseBackEdgePriorities(); - // Calculate interferences between locals. This will will fill - // the data structure |interferences|. void calculateInterferences(); + void calculateInterferences(const SetOfLocals& locals); + void pickIndicesFromOrder(std::vector& order, std::vector& indices); void pickIndicesFromOrder(std::vector& order, @@ -77,31 +72,34 @@ // interference state // canonicalized - accesses should check (low, high) - sparse_square_matrix interferences; + std::vector interferences; void interfere(Index i, Index j) { if (i == j) { return; } - interferences.set(std::min(i, j), std::max(i, j), true); + interferences[std::min(i, j) * numLocals + std::max(i, j)] = 1; } // optimized version where you know that low < high void interfereLowHigh(Index low, Index high) { assert(low < high); - interferences.set(low, high, true); + interferences[low * numLocals + high] = 1; } void unInterfere(Index i, Index j) { - interferences.set(std::min(i, j), std::max(i, j), false); + interferences[std::min(i, j) * numLocals + std::max(i, j)] = 0; } bool interferes(Index i, Index j) { - return interferences.get(std::min(i, j), std::max(i, j)); + return interferences[std::min(i, j) * numLocals + std::max(i, j)]; } }; void CoalesceLocals::doWalkFunction(Function* func) { + if (!canRun(func)) { + return; + } super::doWalkFunction(func); // prioritize back edges increaseBackEdgePriorities(); @@ -143,187 +141,49 @@ } void CoalesceLocals::calculateInterferences() { - interferences.recreate(numLocals); - - // We will track the values in each local, using a numbering where each index - // represents a unique different value. This array maps a local index to the - // value index it contains. - // - // To avoid reallocating this array all the time, allocate it once outside the - // loop. - std::vector values(numLocals); - - ValueNumbering valueNumbering; - - auto* func = getFunction(); - + interferences.resize(numLocals * numLocals); + std::fill(interferences.begin(), interferences.end(), false); for (auto& curr : basicBlocks) { if (liveBlocks.count(curr.get()) == 0) { continue; // ignore dead blocks } - - // First, find which gets end a live range. While doing so, also calculate - // the effectiveness of sets. - auto& actions = curr->contents.actions; - std::vector endsLiveRange(actions.size(), false); + // everything coming in might interfere, as it might come from a different + // block auto live = curr->contents.end; + calculateInterferences(live); + // scan through the block itself + auto& actions = curr->contents.actions; for (int i = int(actions.size()) - 1; i >= 0; i--) { auto& action = actions[i]; auto index = action.index; if (action.isGet()) { - if (!live.has(index)) { - // The local is not live after us, so its liveness ends here. - endsLiveRange[i] = true; - live.insert(index); + // new live local, interferes with all the rest + live.insert(index); + for (auto i : live) { + interfere(i, index); } } else { - // This is a set. Check if the local is alive after it; if it is then - // the set if effective as there is some get that can read the value. if (live.erase(index)) { action.effective = true; } } } - - // We have processed from the end of the block to the start, updating |live| - // as we go, and now it must be equal to the state at the start of the - // block. We will also use |live| in the next loop, and assume it begins - // in that state. - assert(live == curr->contents.start); - - // Now that we know live ranges, check if locals interfere in this block. - // Locals interfere if they might contain different values on areas where - // their live ranges overlap. To evaluate that, we do an analysis inside - // the block that gives each set a unique value number, and as those flow - // around through copies between sets we can see when sets are guaranteed to - // be equal. - - if (curr.get() == entry) { - // Each parameter is assumed to have a different value on entry. - for (Index i = 0; i < func->getNumParams(); i++) { - values[i] = valueNumbering.getUniqueValue(); - } - - for (Index i = func->getNumParams(); i < func->getNumLocals(); i++) { - auto type = func->getLocalType(i); - if (!LiteralUtils::canMakeZero(type)) { - // The default value for a type for which we can't make a zero cannot - // be used anyhow, but we must give it some value in this analysis. A - // unique one seems least likely to result in surprise during - // debugging. - values[i] = valueNumbering.getUniqueValue(); - } else { - values[i] = valueNumbering.getValue(Literal::makeZeros(type)); - } - } - } else { - // In any block but the entry, assume that each live local might have a - // different value at the start. - // TODO: Propagating value IDs across blocks could identify more copies, - // however, it would also be nonlinear. - for (auto index : curr->contents.start) { - values[index] = valueNumbering.getUniqueValue(); - } - } - - // Traverse through the block from start to finish. We keep track of both - // liveness (in |live|) and the value IDs in each local (in |values|) - // while doing so. - for (Index i = 0; i < actions.size(); i++) { - auto& action = actions[i]; - auto index = action.index; - if (action.isGet()) { - if (endsLiveRange[i]) { - bool erased = live.erase(action.index); - assert(erased); - WASM_UNUSED(erased); - } - continue; - } - - // This is a set. Find the value being assigned to the local. - auto* set = (*action.origin)->cast(); - Index newValue; - if (set->value->is() || set->value->is()) { - // This is a copy: Either it is a get or a tee, that occurs right - // before us. Set our new value to theirs. - assert(i > 0 && set->value == *actions[i - 1].origin); - newValue = values[actions[i - 1].index]; - } else { - // This is not a copy. - newValue = valueNumbering.getValue(set->value); - } - values[index] = newValue; - - // If this set has no gets that read from it, then it does not start a - // live range, and it cannot cause interference. - if (!action.effective) { - continue; - } - - // Update interferences: This will interfere with any other local that - // is currently live and contains a different value. - for (auto other : live) { - // This index cannot have been live before this set (as we would be - // trampling some other set before us, if so; and then that set would - // have been ineffective). We will mark this index as live right after - // this loop). - assert(other != index); - if (values[other] != newValue) { - interfere(other, index); - } - } - live.insert(action.index); - } - - // Note that we do not need to do anything for merges: while in general an - // interference can happen either in a block or when control flow merges, - // in wasm we have default values for all locals. As a result, if a local is - // live at the beginning of a block, it will be live at the ends of *all* - // the blocks reaching it: there is no possibility of an "unset local." That - // is, imagine we have this merge with a conflict: - // - // [a is set to some value] ->- - // | - // |->- [merge block where a and b are used] - // | - // [b is set to some value] ->- - // - // It is true that a conflict happens in the merge block, and if we had - // unset locals then the top block would have b unset, and the bottom block - // would have a unset, and so there would be no conflict there and the - // problem would only appear in the merge. But in wasm, that a and b are - // used in the merge block means that they are live at the end of both the - // top and bottom block, and that liveness will extend all the way back to - // *some* set of those values, possibly only the zero-initialization at the - // function start. Therefore a conflict will be noticed in both the top and - // bottom blocks, and that merge block does not need to reason about merging - // its inputs. In other words, a conflict will appear in the middle of a - // block, somewhere, and therefore we leave it to that block to identify, - // and so blocks only need to reason about their own contents and not what - // arrives to them. - // - // The one exception here is the entry to the function, see below. } - - // We must not try to coalesce parameters as they are fixed. Mark them as - // "interfering" so that we do not need to special-case them later. + // Params have a value on entry, so mark them as live, as variables + // live at the entry expect their zero-init value. + SetOfLocals start = entry->contents.start; auto numParams = getFunction()->getNumParams(); for (Index i = 0; i < numParams; i++) { - for (Index j = i + 1; j < numParams; j++) { - interfereLowHigh(i, j); - } + start.insert(i); } + calculateInterferences(start); +} - // We must handle interference between uses of the zero-init value and - // parameters manually. A zero initialization represents a set (to a default - // value), and that set would be what alerts us to a conflict, but there is no - // actual set in the IR since the zero-init value is applied implicitly. - for (auto i : entry->contents.start) { - if (i >= numParams) { - for (Index j = 0; j < numParams; j++) { - interfereLowHigh(j, i); - } +void CoalesceLocals::calculateInterferences(const SetOfLocals& locals) { + Index size = locals.size(); + for (Index i = 0; i < size; i++) { + for (Index j = i + 1; j < size; j++) { + interfereLowHigh(locals[i], locals[j]); } } } @@ -376,19 +236,17 @@ // registers, for gzip) std::vector types; // new index * numLocals => list of all interferences of locals merged to it - sparse_square_matrix newInterferences; - + std::vector newInterferences; // new index * numLocals => list of all copies of locals merged to it - sparse_square_matrix newCopies; - + std::vector newCopies; indices.resize(numLocals); types.resize(numLocals); - + newInterferences.resize(numLocals * numLocals); + std::fill(newInterferences.begin(), newInterferences.end(), false); auto numParams = getFunction()->getNumParams(); - - newInterferences.recreate(numLocals); - newCopies.recreate(numLocals); - + // start with enough room for the params + newCopies.resize(numParams * numLocals); + std::fill(newCopies.begin(), newCopies.end(), 0); Index nextFree = 0; removedCopies = 0; // we can't reorder parameters, they are fixed in order, and cannot coalesce @@ -398,8 +256,8 @@ indices[i] = i; types[i] = getFunction()->getLocalType(i); for (Index j = numParams; j < numLocals; j++) { - newInterferences.set(i, j, interferes(i, j)); - newCopies.set(i, j, getCopies(i, j)); + newInterferences[numLocals * i + j] = interferes(i, j); + newCopies[numLocals * i + j] = getCopies(i, j); } nextFree++; } @@ -408,13 +266,13 @@ Index found = -1; uint8_t foundCopies = -1; for (Index j = 0; j < nextFree; j++) { - if (!newInterferences.get(j, actual) && + if (!newInterferences[j * numLocals + actual] && getFunction()->getLocalType(actual) == types[j]) { // this does not interfere, so it might be what we want. but pick the // one eliminating the most copies (we could stop looking forward when // there are no more items that have copies anyhow, but it doesn't seem // to help) - auto currCopies = newCopies.get(j, actual); + auto currCopies = newCopies[j * numLocals + actual]; if (found == Index(-1) || currCopies > foundCopies) { indices[actual] = found = j; foundCopies = currCopies; @@ -426,6 +284,7 @@ types[found] = getFunction()->getLocalType(actual); nextFree++; removedCopies += getCopies(found, actual); + newCopies.resize(nextFree * numLocals); } else { removedCopies += foundCopies; } @@ -436,9 +295,9 @@ for (Index k = i + 1; k < numLocals; k++) { // go in the order, we only need to update for those we will see later auto j = order[k]; - newInterferences.set( - found, j, newInterferences.get(found, j) || interferes(actual, j)); - newCopies.set(found, j, newCopies.get(found, j) + getCopies(actual, j)); + newInterferences[found * numLocals + j] = + newInterferences[found * numLocals + j] | interferes(actual, j); + newCopies[found * numLocals + j] += getCopies(actual, j); } } } @@ -514,17 +373,11 @@ set->index = indices[set->index]; // in addition, we can optimize out redundant copies and ineffective // sets - if (auto* get = set->value->dynCast()) { - if (get->index == set->index) { - action.removeCopy(); - continue; - } - } - if (auto* subSet = set->value->dynCast()) { - if (subSet->index == set->index) { - set->value = subSet->value; - continue; - } + LocalGet* get; + if ((get = set->value->dynCast()) && + get->index == set->index) { + action.removeCopy(); + continue; } // remove ineffective actions if (!action.effective) { diff -Nru binaryen-108/src/passes/CodeFolding.cpp binaryen-99/src/passes/CodeFolding.cpp --- binaryen-108/src/passes/CodeFolding.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/CodeFolding.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -155,6 +155,8 @@ unoptimizables.insert(curr->default_); } + void visitBrOnExn(BrOnExn* curr) { unoptimizables.insert(curr->name); } + void visitUnreachable(Unreachable* curr) { // we can only optimize if we are at the end of the parent block if (!controlFlowStack.empty()) { @@ -303,11 +305,11 @@ return false; } if (getModule()->features.hasExceptionHandling()) { - EffectAnalyzer effects(getPassOptions(), *getModule(), item); - // Pop instructions are pseudoinstructions used only after 'catch' to - // simulate its behavior. We cannot move expressions containing pops if - // they are not enclosed in a 'catch' body, because a pop instruction - // should follow right after 'catch'. + EffectAnalyzer effects(getPassOptions(), getModule()->features, item); + // Currently pop instructions are only used for exnref.pop, which is a + // pseudo instruction following a catch. We cannot move expressions + // containing pops if they are not enclosed in a 'catch' body, because a + // pop instruction should follow right after 'catch'. if (effects.danglingPop) { return false; } @@ -319,7 +321,7 @@ // conservative approximation because there can be cases that 'try' is // within the expression that may throw so it is safe to take the // expression out. - if (effects.throws() && !FindAll(outOf).list.empty()) { + if (effects.throws && !FindAll(outOf).list.empty()) { return false; } } @@ -591,8 +593,9 @@ // TODO: this should not be a problem in // *non*-terminating tails, but // double-verify that - if (EffectAnalyzer( - getPassOptions(), *getModule(), newItem) + if (EffectAnalyzer(getPassOptions(), + getModule()->features, + newItem) .hasExternalBreakTargets()) { return true; } @@ -617,10 +620,10 @@ for (auto& tail : next) { auto* item = getItem(tail, num); auto digest = hashes[item]; - if (!seen.emplace(digest).second) { + if (seen.count(digest)) { continue; } - + seen.insert(digest); auto& items = hashed[digest]; if (items.size() == 1) { continue; @@ -741,7 +744,7 @@ mergeable.pop_back(); } // ensure the replacement has the same type, so the outside is not surprised - outer->finalize(getFunction()->getResults()); + outer->finalize(getFunction()->sig.results); getFunction()->body = outer; return true; } diff -Nru binaryen-108/src/passes/CodePushing.cpp binaryen-99/src/passes/CodePushing.cpp --- binaryen-108/src/passes/CodePushing.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/CodePushing.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -41,12 +41,12 @@ void analyze(Function* func) { auto num = func->getNumLocals(); - numSets.clear(); numSets.resize(num); - numGets.clear(); + std::fill(numSets.begin(), numSets.end(), 0); numGets.resize(num); - sfa.clear(); + std::fill(numGets.begin(), numGets.end(), 0); sfa.resize(num); + std::fill(sfa.begin(), sfa.begin() + func->getNumParams(), false); std::fill(sfa.begin() + func->getNumParams(), sfa.end(), true); walk(func->body); for (Index i = 0; i < num; i++) { @@ -82,16 +82,16 @@ LocalAnalyzer& analyzer; std::vector& numGetsSoFar; PassOptions& passOptions; - Module& module; + FeatureSet features; public: Pusher(Block* block, LocalAnalyzer& analyzer, std::vector& numGetsSoFar, PassOptions& passOptions, - Module& module) + FeatureSet features) : list(block->list), analyzer(analyzer), numGetsSoFar(numGetsSoFar), - passOptions(passOptions), module(module) { + passOptions(passOptions), features(features) { // Find an optimization segment: from the first pushable thing, to the first // point past which we want to push. We then push in that range before // continuing forward. @@ -128,7 +128,7 @@ // but also have no side effects, as it may not execute if pushed. if (analyzer.isSFA(index) && numGetsSoFar[index] == analyzer.getNumGets(index) && - !EffectAnalyzer(passOptions, module, set->value).hasSideEffects()) { + !EffectAnalyzer(passOptions, features, set->value).hasSideEffects()) { return set; } return nullptr; @@ -141,7 +141,7 @@ if (auto* drop = curr->dynCast()) { curr = drop->value; } - if (curr->is()) { + if (curr->is() || curr->is()) { return true; } if (auto* br = curr->dynCast()) { @@ -159,7 +159,7 @@ assert(firstPushable != Index(-1) && pushPoint != Index(-1) && firstPushable < pushPoint); // everything that matters if you want to be pushed past the pushPoint - EffectAnalyzer cumulativeEffects(passOptions, module); + EffectAnalyzer cumulativeEffects(passOptions, features); cumulativeEffects.walk(list[pushPoint]); // it is ok to ignore the branching here, that is the crucial point of this // opt @@ -177,7 +177,7 @@ pushableEffects .emplace(std::piecewise_construct, std::forward_as_tuple(pushable), - std::forward_as_tuple(passOptions, module, pushable)) + std::forward_as_tuple(passOptions, features, pushable)) .first; } auto& effects = iter->second; @@ -245,8 +245,8 @@ // pre-scan to find which vars are sfa, and also count their gets&sets analyzer.analyze(func); // prepare to walk - numGetsSoFar.clear(); numGetsSoFar.resize(func->getNumLocals()); + std::fill(numGetsSoFar.begin(), numGetsSoFar.end(), 0); // walk and optimize walk(func->body); } @@ -268,7 +268,8 @@ // don't hit a non-control-flow ordering invalidation issue, since if this // isn't a loop, it's fine (we're not used outside), and if it is, we hit // the assign before any use (as we can't push it past a use). - Pusher pusher(curr, analyzer, numGetsSoFar, getPassOptions(), *getModule()); + Pusher pusher( + curr, analyzer, numGetsSoFar, getPassOptions(), getModule()->features); } }; diff -Nru binaryen-108/src/passes/ConstantFieldPropagation.cpp binaryen-99/src/passes/ConstantFieldPropagation.cpp --- binaryen-108/src/passes/ConstantFieldPropagation.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/ConstantFieldPropagation.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,253 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Find struct fields that are always written to with a constant value, and -// replace gets of them with that value. -// -// For example, if we have a vtable of type T, and we always create it with one -// of the fields containing a ref.func of the same function F, and there is no -// write to that field of a different value (even using a subtype of T), then -// anywhere we see a get of that field we can place a ref.func of F. -// -// FIXME: This pass assumes a closed world. When we start to allow multi-module -// wasm GC programs we need to check for type escaping. -// - -#include "ir/module-utils.h" -#include "ir/possible-constant.h" -#include "ir/struct-utils.h" -#include "ir/utils.h" -#include "pass.h" -#include "support/unique_deferring_queue.h" -#include "wasm-builder.h" -#include "wasm-traversal.h" -#include "wasm.h" - -namespace wasm { - -namespace { - -using PCVStructValuesMap = StructUtils::StructValuesMap; -using PCVFunctionStructValuesMap = - StructUtils::FunctionStructValuesMap; - -// Optimize struct gets based on what we've learned about writes. -// -// TODO Aside from writes, we could use information like whether any struct of -// this type has even been created (to handle the case of struct.sets but -// no struct.news). -struct FunctionOptimizer : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - Pass* create() override { return new FunctionOptimizer(infos); } - - FunctionOptimizer(PCVStructValuesMap& infos) : infos(infos) {} - - void visitStructGet(StructGet* curr) { - auto type = curr->ref->type; - if (type == Type::unreachable) { - return; - } - - Builder builder(*getModule()); - - // Find the info for this field, and see if we can optimize. First, see if - // there is any information for this heap type at all. If there isn't, it is - // as if nothing was ever noted for that field. - PossibleConstantValues info; - assert(!info.hasNoted()); - auto iter = infos.find(type.getHeapType()); - if (iter != infos.end()) { - // There is information on this type, fetch it. - info = iter->second[curr->index]; - } - - if (!info.hasNoted()) { - // This field is never written at all. That means that we do not even - // construct any data of this type, and so it is a logic error to reach - // this location in the code. (Unless we are in an open-world - // situation, which we assume we are not in.) Replace this get with a - // trap. Note that we do not need to care about the nullability of the - // reference, as if it should have trapped, we are replacing it with - // another trap, which we allow to reorder (but we do need to care about - // side effects in the reference, so keep it around). - replaceCurrent(builder.makeSequence(builder.makeDrop(curr->ref), - builder.makeUnreachable())); - changed = true; - return; - } - - // If the value is not a constant, then it is unknown and we must give up. - if (!info.isConstant()) { - return; - } - - // We can do this! Replace the get with a trap on a null reference using a - // ref.as_non_null (we need to trap as the get would have done so), plus the - // constant value. (Leave it to further optimizations to get rid of the - // ref.) - Expression* value = info.makeExpression(*getModule()); - replaceCurrent(builder.makeSequence( - builder.makeDrop(builder.makeRefAs(RefAsNonNull, curr->ref)), value)); - changed = true; - } - - void doWalkFunction(Function* func) { - WalkerPass>::doWalkFunction(func); - - // If we changed anything, we need to update parent types as types may have - // changed. - if (changed) { - ReFinalize().walkFunctionInModule(func, getModule()); - } - } - -private: - PCVStructValuesMap& infos; - - bool changed = false; -}; - -struct PCVScanner - : public StructUtils::StructScanner { - Pass* create() override { - return new PCVScanner(functionNewInfos, functionSetGetInfos); - } - - PCVScanner(StructUtils::FunctionStructValuesMap& - functionNewInfos, - StructUtils::FunctionStructValuesMap& - functionSetInfos) - : StructUtils::StructScanner( - functionNewInfos, functionSetInfos) {} - - void noteExpression(Expression* expr, - HeapType type, - Index index, - PossibleConstantValues& info) { - info.note(expr, *getModule()); - } - - void noteDefault(Type fieldType, - HeapType type, - Index index, - PossibleConstantValues& info) { - info.note(Literal::makeZero(fieldType)); - } - - void noteCopy(HeapType type, Index index, PossibleConstantValues& info) { - // Ignore copies: when we set a value to a field from that same field, no - // new values are actually introduced. - // - // Note that this is only sound by virtue of the overall analysis in this - // pass: the object read from may be of a subclass, and so subclass values - // may be actually written here. But as our analysis considers subclass - // values too (as it must) then that is safe. That is, if a subclass of $A - // adds a value X that can be loaded from (struct.get $A $b), then consider - // a copy - // - // (struct.set $A $b (struct.get $A $b)) - // - // Our analysis will figure out that X can appear in that copy's get, and so - // the copy itself does not add any information about values. - // - // TODO: This may be extensible to a copy from a subtype by the above - // analysis (but this is already entering the realm of diminishing - // returns). - } - - void noteRead(HeapType type, Index index, PossibleConstantValues& info) { - // Reads do not interest us. - } -}; - -struct ConstantFieldPropagation : public Pass { - void run(PassRunner* runner, Module* module) override { - if (getTypeSystem() != TypeSystem::Nominal) { - Fatal() << "ConstantFieldPropagation requires nominal typing"; - } - - // Find and analyze all writes inside each function. - PCVFunctionStructValuesMap functionNewInfos(*module), - functionSetInfos(*module); - PCVScanner scanner(functionNewInfos, functionSetInfos); - scanner.run(runner, module); - scanner.runOnModuleCode(runner, module); - - // Combine the data from the functions. - PCVStructValuesMap combinedNewInfos, combinedSetInfos; - functionNewInfos.combineInto(combinedNewInfos); - functionSetInfos.combineInto(combinedSetInfos); - - // Handle subtyping. |combinedInfo| so far contains data that represents - // each struct.new and struct.set's operation on the struct type used in - // that instruction. That is, if we do a struct.set to type T, the value was - // noted for type T. But our actual goal is to answer questions about - // struct.gets. Specifically, when later we see: - // - // (struct.get $A x (REF-1)) - // - // Then we want to be aware of all the relevant struct.sets, that is, the - // sets that can write data that this get reads. Given a set - // - // (struct.set $B x (REF-2) (..value..)) - // - // then - // - // 1. If $B is a subtype of $A, it is relevant: the get might read from a - // struct of type $B (i.e., REF-1 and REF-2 might be identical, and both - // be a struct of type $B). - // 2. If $B is a supertype of $A that still has the field x then it may - // also be relevant: since $A is a subtype of $B, the set may write to a - // struct of type $A (and again, REF-1 and REF-2 may be identical). - // - // Thus, if either $A <: $B or $B <: $A then we must consider the get and - // set to be relevant to each other. To make our later lookups for gets - // efficient, we therefore propagate information about the possible values - // in each field to both subtypes and supertypes. - // - // struct.new on the other hand knows exactly what type is being written to, - // and so given a get of $A and a new of $B, the new is relevant for the get - // iff $A is a subtype of $B, so we only need to propagate in one direction - // there, to supertypes. - - StructUtils::TypeHierarchyPropagator propagator( - *module); - propagator.propagateToSuperTypes(combinedNewInfos); - propagator.propagateToSuperAndSubTypes(combinedSetInfos); - - // Combine both sources of information to the final information that gets - // care about. - PCVStructValuesMap combinedInfos = std::move(combinedNewInfos); - combinedSetInfos.combineInto(combinedInfos); - - // Optimize. - // TODO: Skip this if we cannot optimize anything - FunctionOptimizer(combinedInfos).run(runner, module); - - // TODO: Actually remove the field from the type, where possible? That might - // be best in another pass. - } -}; - -} // anonymous namespace - -Pass* createConstantFieldPropagationPass() { - return new ConstantFieldPropagation(); -} - -} // namespace wasm diff -Nru binaryen-108/src/passes/ConstHoisting.cpp binaryen-99/src/passes/ConstHoisting.cpp --- binaryen-108/src/passes/ConstHoisting.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/ConstHoisting.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -30,11 +30,12 @@ // <= 1 byte to declare the local and 2-3 to use it! // -#include "pass.h" -#include "support/insert_ordered.h" -#include "wasm-binary.h" -#include "wasm-builder.h" -#include "wasm.h" +#include + +#include +#include +#include +#include namespace wasm { @@ -46,7 +47,7 @@ Pass* create() override { return new ConstHoisting; } - InsertOrderedMap> uses; + std::map> uses; void visitConst(Const* curr) { uses[curr->value].push_back(getCurrentPointer()); @@ -54,7 +55,9 @@ void visitFunction(Function* curr) { std::vector prelude; - for (auto& [value, vec] : uses) { + for (auto& pair : uses) { + auto value = pair.first; + auto& vec = pair.second; auto num = vec.size(); if (worthHoisting(value, num)) { prelude.push_back(hoist(vec)); @@ -92,10 +95,11 @@ // not implemented yet case Type::v128: case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: - case Type::i31ref: - case Type::dataref: { + case Type::i31ref: { return false; } case Type::none: diff -Nru binaryen-108/src/passes/DeadArgumentElimination.cpp binaryen-99/src/passes/DeadArgumentElimination.cpp --- binaryen-108/src/passes/DeadArgumentElimination.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/DeadArgumentElimination.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -15,8 +15,10 @@ */ // -// Optimizes call arguments in a whole-program manner. In particular, this -// removes ones that are not used (dead), but it also does more things: +// Optimizes call arguments in a whole-program manner, removing ones +// that are not used (dead). +// +// Specifically, this does these things: // // * Find functions for whom an argument is always passed the same // constant. If so, we can just set that local to that constant @@ -26,8 +28,6 @@ // the previous point was true for an argument, then the second // must as well.) // * Find return values ("return arguments" ;) that are never used. -// * Refine the types of arguments, that is make the argument type more -// specific if all the passed values allow that. // // This pass does not depend on flattening, but it may be more effective, // as then call arguments never have side effects (which we need to @@ -37,14 +37,9 @@ #include #include +#include "cfg/cfg-traversal.h" #include "ir/effects.h" -#include "ir/element-utils.h" -#include "ir/find_all.h" -#include "ir/lubs.h" #include "ir/module-utils.h" -#include "ir/type-updating.h" -#include "ir/utils.h" -#include "param-utils.h" #include "pass.h" #include "passes/opt-utils.h" #include "support/sorted_vector.h" @@ -86,8 +81,19 @@ typedef std::unordered_map DAEFunctionInfoMap; +// Information in a basic block +struct DAEBlockInfo { + // A local may be read, written, or not accessed in this block. + // If it is both read and written, we just care about the first + // action (if it is read first, that's all the info we are + // looking for; if it is written first, it can't be read later). + enum LocalUse { Read, Written }; + std::unordered_map localUses; +}; + struct DAEScanner - : public WalkerPass>> { + : public WalkerPass< + CFGWalker, DAEBlockInfo>> { bool isFunctionParallel() override { return true; } Pass* create() override { return new DAEScanner(infoMap); } @@ -99,6 +105,28 @@ Index numParams; + // cfg traversal work + + void visitLocalGet(LocalGet* curr) { + if (currBasicBlock) { + auto& localUses = currBasicBlock->contents.localUses; + auto index = curr->index; + if (localUses.count(index) == 0) { + localUses[index] = DAEBlockInfo::Read; + } + } + } + + void visitLocalSet(LocalSet* curr) { + if (currBasicBlock) { + auto& localUses = currBasicBlock->contents.localUses; + auto index = curr->index; + if (localUses.count(index) == 0) { + localUses[index] = DAEBlockInfo::Written; + } + } + } + void visitCall(Call* curr) { if (!getModule()->getFunction(curr->target)->imported()) { info->calls[curr->target].push_back(curr); @@ -143,7 +171,8 @@ void doWalkFunction(Function* func) { numParams = func->getNumParams(); info = &((*infoMap)[func->name]); - PostWalker>::doWalkFunction(func); + CFGWalker, DAEBlockInfo>::doWalkFunction( + func); // If there are relevant params, check if they are used. If we can't // optimize the function anyhow, there's no point (note that our check here // is technically racy - another thread could update hasUnseenCalls to true @@ -155,21 +184,76 @@ // part of, say if we are exported, or if another parallel function finds a // RefFunc to us and updates it before we check it). if (numParams > 0 && !info->hasUnseenCalls) { - auto usedParams = ParamUtils::getUsedParams(func); - for (Index i = 0; i < numParams; i++) { - if (usedParams.count(i) == 0) { - info->unusedParams.insert(i); + findUnusedParams(); + } + } + + void findUnusedParams() { + // Flow the incoming parameter values, see if they reach a read. + // Once we've seen a parameter at a block, we need never consider it there + // again. + std::unordered_map seenBlockIndexes; + // Start with all the incoming parameters. + SortedVector initial; + for (Index i = 0; i < numParams; i++) { + initial.push_back(i); + } + // The used params, which we now compute. + std::unordered_set usedParams; + // An item of work is a block plus the values arriving there. + typedef std::pair Item; + std::vector work; + work.emplace_back(entry, initial); + while (!work.empty()) { + auto item = std::move(work.back()); + work.pop_back(); + auto* block = item.first; + auto& indexes = item.second; + // Ignore things we've already seen, or we've already seen to be used. + auto& seenIndexes = seenBlockIndexes[block]; + indexes.filter([&](const Index i) { + if (seenIndexes.has(i) || usedParams.count(i)) { + return false; + } else { + seenIndexes.insert(i); + return true; + } + }); + if (indexes.empty()) { + continue; // nothing more to flow + } + auto& localUses = block->contents.localUses; + SortedVector remainingIndexes; + for (auto i : indexes) { + auto iter = localUses.find(i); + if (iter != localUses.end()) { + auto use = iter->second; + if (use == DAEBlockInfo::Read) { + usedParams.insert(i); + } + // Whether it was a read or a write, we can stop looking at that local + // here. + } else { + remainingIndexes.insert(i); + } + } + // If there are remaining indexes, flow them forward. + if (!remainingIndexes.empty()) { + for (auto* next : block->out) { + work.emplace_back(next, remainingIndexes); } } } + // We can now compute the unused params. + for (Index i = 0; i < numParams; i++) { + if (usedParams.count(i) == 0) { + info->unusedParams.insert(i); + } + } } }; struct DAE : public Pass { - // This pass changes locals and parameters. - // FIXME DWARF updating does not handle local changes yet. - bool invalidatesDWARF() override { return true; } - bool optimize = false; void run(PassRunner* runner, Module* module) override { @@ -190,67 +274,88 @@ for (auto& func : module->functions) { infoMap[func->name]; } - DAEScanner scanner(&infoMap); - scanner.walkModuleCode(module); + // Check the influence of the table and exports. for (auto& curr : module->exports) { if (curr->kind == ExternalKind::Function) { infoMap[curr->value].hasUnseenCalls = true; } } + for (auto& segment : module->table.segments) { + for (auto name : segment.data) { + infoMap[name].hasUnseenCalls = true; + } + } // Scan all the functions. - scanner.run(runner, module); + DAEScanner(&infoMap).run(runner, module); // Combine all the info. - std::map> allCalls; + std::unordered_map> allCalls; std::unordered_set tailCallees; - for (auto& [_, info] : infoMap) { - for (auto& [name, calls] : info.calls) { + for (auto& pair : infoMap) { + auto& info = pair.second; + for (auto& pair : info.calls) { + auto name = pair.first; + auto& calls = pair.second; auto& allCallsToName = allCalls[name]; allCallsToName.insert(allCallsToName.end(), calls.begin(), calls.end()); } for (auto& callee : info.tailCallees) { tailCallees.insert(callee); } - for (auto& [name, calls] : info.droppedCalls) { - allDroppedCalls[name] = calls; + for (auto& pair : info.droppedCalls) { + allDroppedCalls[pair.first] = pair.second; } } - // If we refine return types then we will need to do more type updating - // at the end. - bool refinedReturnTypes = false; - // We now have a mapping of all call sites for each function, and can look - // for optimization opportunities. - for (auto& [name, calls] : allCalls) { - // We can only optimize if we see all the calls and can modify them. + // We now have a mapping of all call sites for each function. Check which + // are always passed the same constant for a particular argument. + for (auto& pair : allCalls) { + auto name = pair.first; + // We can only optimize if we see all the calls and can modify + // them. if (infoMap[name].hasUnseenCalls) { continue; } + auto& calls = pair.second; auto* func = module->getFunction(name); - // Refine argument types before doing anything else. This does not - // affect whether an argument is used or not, it just refines the type - // where possible. - refineArgumentTypes(func, calls, module, infoMap[name]); - // Refine return types as well. - if (refineReturnTypes(func, calls, module)) { - refinedReturnTypes = true; - } - auto optimizedIndexes = - ParamUtils::applyConstantValues({func}, calls, {}, module); - for (auto i : optimizedIndexes) { - // Mark it as unused, which we know it now is (no point to re-scan just - // for that). - infoMap[name].unusedParams.insert(i); - } - } - if (refinedReturnTypes) { - // Changing a call expression's return type can propagate out to its - // parents, and so we must refinalize. - // TODO: We could track in which functions we actually make changes. - ReFinalize().run(runner, module); + auto numParams = func->getNumParams(); + for (Index i = 0; i < numParams; i++) { + Literal value; + for (auto* call : calls) { + assert(call->target == name); + assert(call->operands.size() == numParams); + auto* operand = call->operands[i]; + if (auto* c = operand->dynCast()) { + if (value.type == Type::none) { + // This is the first value seen. + value = c->value; + } else if (value != c->value) { + // Not identical, give up + value = Literal(Type::none); + break; + } + } else { + // Not a constant, give up + value = Literal(Type::none); + break; + } + } + if (value.type != Type::none) { + // Success! We can just apply the constant in the function, which + // makes the parameter value unused, which lets us remove it later. + Builder builder(*module); + func->body = builder.makeSequence( + builder.makeLocalSet(i, builder.makeConst(value)), func->body); + // Mark it as unused, which we know it now is (no point to + // re-scan just for that). + infoMap[name].unusedParams.insert(i); + } + } } // Track which functions we changed, and optimize them later if necessary. std::unordered_set changed; // We now know which parameters are unused, and can potentially remove them. - for (auto& [name, calls] : allCalls) { + for (auto& pair : allCalls) { + auto name = pair.first; + auto& calls = pair.second; if (infoMap[name].hasUnseenCalls) { continue; } @@ -259,11 +364,30 @@ if (numParams == 0) { continue; } - auto removedIndexes = ParamUtils::removeParameters( - {func}, infoMap[name].unusedParams, calls, {}, module, runner); - if (!removedIndexes.empty()) { - // Success! - changed.insert(func); + // Iterate downwards, as we may remove more than one. + Index i = numParams - 1; + while (1) { + if (infoMap[name].unusedParams.has(i)) { + // Great, it's not used. Check if none of the calls has a param with + // side effects, as that would prevent us removing them (flattening + // should have been done earlier). + bool canRemove = + std::none_of(calls.begin(), calls.end(), [&](Call* call) { + auto* operand = call->operands[i]; + return EffectAnalyzer(runner->options, module->features, operand) + .hasSideEffects(); + }); + if (canRemove) { + // Wonderful, nothing stands in our way! Do it. + // TODO: parallelize this? + removeParameter(func, i, calls); + changed.insert(func); + } + } + if (i == 0) { + break; + } + i--; } } // We can also tell which calls have all their return values dropped. Note @@ -272,7 +396,7 @@ // once to remove a param, once to drop the return value). if (changed.empty()) { for (auto& func : module->functions) { - if (func->getResults() == Type::none) { + if (func->sig.results == Type::none) { continue; } auto name = func->name; @@ -282,7 +406,7 @@ if (infoMap[name].hasTailCalls) { continue; } - if (tailCallees.count(name)) { + if (tailCallees.find(name) != tailCallees.end()) { continue; } auto iter = allCalls.find(name); @@ -306,15 +430,50 @@ if (optimize && !changed.empty()) { OptUtils::optimizeAfterInlining(changed, module, runner); } - return !changed.empty() || refinedReturnTypes; + return !changed.empty(); } private: std::unordered_map allDroppedCalls; + void removeParameter(Function* func, Index i, std::vector& calls) { + // It's cumbersome to adjust local names - TODO don't clear them? + Builder::clearLocalNames(func); + // Remove the parameter from the function. We must add a new local + // for uses of the parameter, but cannot make it use the same index + // (in general). + std::vector params(func->sig.params.begin(), func->sig.params.end()); + auto type = params[i]; + params.erase(params.begin() + i); + func->sig.params = Type(params); + Index newIndex = Builder::addVar(func, type); + // Update local operations. + struct LocalUpdater : public PostWalker { + Index removedIndex; + Index newIndex; + LocalUpdater(Function* func, Index removedIndex, Index newIndex) + : removedIndex(removedIndex), newIndex(newIndex) { + walk(func->body); + } + void visitLocalGet(LocalGet* curr) { updateIndex(curr->index); } + void visitLocalSet(LocalSet* curr) { updateIndex(curr->index); } + void updateIndex(Index& index) { + if (index == removedIndex) { + index = newIndex; + } else if (index > removedIndex) { + index--; + } + } + } localUpdater(func, i, newIndex); + // Remove the arguments from the calls. + for (auto* call : calls) { + call->operands.erase(call->operands.begin() + i); + } + } + void removeReturnValue(Function* func, std::vector& calls, Module* module) { - func->setResults(Type::none); + func->sig.results = Type::none; Builder builder(*module); // Remove any return values. struct ReturnUpdater : public PostWalker { @@ -346,107 +505,6 @@ } } } - - // Given a function and all the calls to it, see if we can refine the type of - // its arguments. If we only pass in a subtype, we may as well refine the type - // to that. - // - // This assumes that the function has no calls aside from |calls|, that is, it - // is not exported or called from the table or by reference. - void refineArgumentTypes(Function* func, - const std::vector& calls, - Module* module, - const DAEFunctionInfo& info) { - if (!module->features.hasGC()) { - return; - } - auto numParams = func->getNumParams(); - std::vector newParamTypes; - newParamTypes.reserve(numParams); - std::vector lubs(numParams); - for (Index i = 0; i < numParams; i++) { - auto originalType = func->getLocalType(i); - // If the parameter type is not a reference, there is nothing to refine. - // And if it is unused, also do nothing, as we can leave it to the other - // parts of this pass to optimize it properly, which avoids having to - // think about corner cases involving refining the type of an unused - // param (in particular, unused params are turned into locals, which means - // we'd need to think about defaultability etc.). - if (!originalType.isRef() || info.unusedParams.has(i)) { - newParamTypes.push_back(originalType); - continue; - } - auto& lub = lubs[i]; - for (auto* call : calls) { - auto* operand = call->operands[i]; - lub.noteUpdatableExpression(operand); - if (lub.getBestPossible() == originalType) { - // We failed to refine this parameter to anything more specific. - break; - } - } - - // Nothing is sent here at all; leave such optimizations to DCE. - if (!lub.noted()) { - return; - } - newParamTypes.push_back(lub.getBestPossible()); - } - - // Check if we are able to optimize here before we do the work to scan the - // function body. - auto newParams = Type(newParamTypes); - if (newParams == func->getParams()) { - return; - } - - // We can do this! - TypeUpdating::updateParamTypes(func, newParamTypes, *module); - - // Update anything the lubs need to update. - for (auto& lub : lubs) { - lub.updateNulls(); - } - - // Also update the function's type. - func->setParams(newParams); - } - - // See if the types returned from a function allow us to define a more refined - // return type for it. If so, we can update it and all calls going to it. - // - // This assumes that the function has no calls aside from |calls|, that is, it - // is not exported or called from the table or by reference. Exports should be - // fine, as should indirect calls in principle, but VMs will need to support - // function subtyping in indirect calls. TODO: relax this when possible - // - // Returns whether we optimized. - // - // TODO: We may be missing a global optimum here, as e.g. if a function calls - // itself and returns that value, then we would not do any change here, - // as one of the return values is exactly what it already is. Similar - // unoptimality can happen with multiple functions, more local code in - // the middle, etc. - bool refineReturnTypes(Function* func, - const std::vector& calls, - Module* module) { - auto lub = LUB::getResultsLUB(func, *module); - if (!lub.noted()) { - return false; - } - auto newType = lub.getBestPossible(); - if (newType != func->getResults()) { - lub.updateNulls(); - func->setResults(newType); - for (auto* call : calls) { - if (call->type != Type::unreachable) { - call->type = newType; - } - } - return true; - } - return false; - } }; Pass* createDAEPass() { return new DAE(); } diff -Nru binaryen-108/src/passes/DeadCodeElimination.cpp binaryen-99/src/passes/DeadCodeElimination.cpp --- binaryen-108/src/passes/DeadCodeElimination.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/DeadCodeElimination.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -161,12 +161,9 @@ } else if (auto* tryy = curr->dynCast()) { // If both try body and catch body are unreachable, there is no need for a // concrete type, which may allow more reduction. - bool allCatchesUnreachable = true; - for (auto* catchBody : tryy->catchBodies) { - allCatchesUnreachable &= catchBody->type == Type::unreachable; - } if (tryy->type != Type::unreachable && - tryy->body->type == Type::unreachable && allCatchesUnreachable) { + tryy->body->type == Type::unreachable && + tryy->catchBody->type == Type::unreachable) { typeUpdater.changeType(tryy, Type::unreachable); } } else { diff -Nru binaryen-108/src/passes/DeNaN.cpp binaryen-99/src/passes/DeNaN.cpp --- binaryen-108/src/passes/DeNaN.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/DeNaN.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,6 @@ // differ on wasm's nondeterminism around NaNs. // -#include "ir/names.h" #include "ir/properties.h" #include "pass.h" #include "wasm-builder.h" @@ -32,9 +31,6 @@ struct DeNaN : public WalkerPass< ControlFlowWalker>> { - - Name deNan32, deNan64; - void visitExpression(Expression* expr) { // If the expression returns a floating-point value, ensure it is not a // NaN. If we can do this at compile time, do it now, which is useful for @@ -57,13 +53,13 @@ if (c && c->value.isNaN()) { replacement = builder.makeConst(float(0)); } else { - replacement = builder.makeCall(deNan32, {expr}, Type::f32); + replacement = builder.makeCall("deNan32", {expr}, Type::f32); } } else if (expr->type == Type::f64) { if (c && c->value.isNaN()) { replacement = builder.makeConst(double(0)); } else { - replacement = builder.makeCall(deNan64, {expr}, Type::f64); + replacement = builder.makeCall("deNan64", {expr}, Type::f64); } } if (replacement) { @@ -90,12 +86,12 @@ fixes.push_back(builder.makeLocalSet( i, builder.makeCall( - deNan32, {builder.makeLocalGet(i, Type::f32)}, Type::f32))); + "deNan32", {builder.makeLocalGet(i, Type::f32)}, Type::f32))); } else if (func->getLocalType(i) == Type::f64) { fixes.push_back(builder.makeLocalSet( i, builder.makeCall( - deNan64, {builder.makeLocalGet(i, Type::f64)}, Type::f64))); + "deNan64", {builder.makeLocalGet(i, Type::f64)}, Type::f64))); } } if (!fixes.empty()) { @@ -109,18 +105,13 @@ } } - void doWalkModule(Module* module) { - // Pick names for the helper functions. - deNan32 = Names::getValidFunctionName(*module, "deNan32"); - deNan64 = Names::getValidFunctionName(*module, "deNan64"); - - ControlFlowWalker>::doWalkModule( - module); - - // Add helper functions after the walk, so they are not instrumented. + void visitModule(Module* module) { + // Add helper functions. Builder builder(*module); auto add = [&](Name name, Type type, Literal literal, BinaryOp op) { - auto func = Builder::makeFunction(name, Signature(type, type), {}); + auto* func = new Function; + func->name = name; + func->sig = Signature(type, type); // Compare the value to itself to check if it is a NaN, and return 0 if // so: // @@ -137,10 +128,10 @@ op, builder.makeLocalGet(0, type), builder.makeLocalGet(0, type)), builder.makeLocalGet(0, type), builder.makeConst(literal)); - module->addFunction(std::move(func)); + module->addFunction(func); }; - add(deNan32, Type::f32, Literal(float(0)), EqFloat32); - add(deNan64, Type::f64, Literal(double(0)), EqFloat64); + add("deNan32", Type::f32, Literal(float(0)), EqFloat32); + add("deNan64", Type::f64, Literal(double(0)), EqFloat64); } }; diff -Nru binaryen-108/src/passes/Directize.cpp binaryen-99/src/passes/Directize.cpp --- binaryen-108/src/passes/Directize.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Directize.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -23,7 +23,6 @@ #include #include "ir/table-utils.h" -#include "ir/type-updating.h" #include "ir/utils.h" #include "pass.h" #include "wasm-builder.h" @@ -37,84 +36,47 @@ struct FunctionDirectizer : public WalkerPass> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new FunctionDirectizer(tables); } + Pass* create() override { return new FunctionDirectizer(flatTable); } - FunctionDirectizer( - const std::unordered_map& tables) - : tables(tables) {} + FunctionDirectizer(TableUtils::FlatTable* flatTable) : flatTable(flatTable) {} void visitCallIndirect(CallIndirect* curr) { - auto it = tables.find(curr->table); - if (it == tables.end()) { + if (!flatTable) { return; } - - auto& flatTable = it->second; - - // If the target is constant, we can emit a direct call. - if (curr->target->is()) { - std::vector operands(curr->operands.begin(), - curr->operands.end()); - replaceCurrent(makeDirectCall(operands, curr->target, flatTable, curr)); - return; + if (auto* c = curr->target->dynCast()) { + Index index = c->value.geti32(); + // If the index is invalid, or the type is wrong, we can + // emit an unreachable here, since in Binaryen it is ok to + // reorder/replace traps when optimizing (but never to + // remove them, at least not by default). + if (index >= flatTable->names.size()) { + replaceWithUnreachable(curr); + return; + } + auto name = flatTable->names[index]; + if (!name.is()) { + replaceWithUnreachable(curr); + return; + } + auto* func = getModule()->getFunction(name); + if (curr->sig != func->sig) { + replaceWithUnreachable(curr); + return; + } + // Everything looks good! + replaceCurrent( + Builder(*getModule()) + .makeCall(name, curr->operands, curr->type, curr->isReturn)); } + } - // If the target is a select of two different constants, we can emit two - // direct calls. - // TODO: handle 3+ - // TODO: handle the case where just one arm is a constant? - if (auto* select = curr->target->dynCast()) { + return optimizeSelect(select); + } + + if (auto* binary = curr->dynCast()) { + if (auto* ext = Properties::getAlmostSignExt(binary)) { + Index extraLeftShifts; + auto bits = Properties::getAlmostSignExtBits(binary, extraLeftShifts); + if (extraLeftShifts == 0) { + if (auto* load = + Properties::getFallthrough(ext, getPassOptions(), features) + ->dynCast()) { + // pattern match a load of 8 bits and a sign extend using a shl of + // 24 then shr_s of 24 as well, etc. + if (LoadUtils::canBeSigned(load) && + ((load->bytes == 1 && bits == 8) || + (load->bytes == 2 && bits == 16))) { + // if the value falls through, we can't alter the load, as it + // might be captured in a tee + if (load->signed_ == true || load == ext) { + load->signed_ = true; + return ext; + } } } } - } - // We can in some cases remove part of a sign extend, that is, - // (x << A) >> B => x << (A - B) - // If the sign-extend input cannot have a sign bit, we don't need it. - if (Bits::getMaxBits(ext, this) + extraLeftShifts < bits) { - return replaceCurrent(removeAlmostSignExt(curr)); - } - // We also don't need it if it already has an identical-sized sign - // extend applied to it. That is, if it is already a sign-extended - // value, then another sign extend will do nothing. We do need to be - // careful of the extra shifts, though. - if (isSignExted(ext, bits) && extraLeftShifts == 0) { - return replaceCurrent(removeAlmostSignExt(curr)); - } - } else if (curr->op == EqInt32 || curr->op == NeInt32) { - if (auto* c = curr->right->dynCast()) { - if (auto* ext = Properties::getSignExtValue(curr->left)) { - // We are comparing a sign extend to a constant, which means we can - // use a cheaper zero-extend in some cases. That is, - // (x << S) >> S ==/!= C => x & T ==/!= C - // where S and T are the matching values for sign/zero extend of the - // same size. For example, for an effective 8-bit value: - // (x << 24) >> 24 ==/!= C => x & 255 ==/!= C - // - // The key thing to track here are the upper bits plus the sign bit; - // call those the "relevant bits". This is crucial because x is - // sign-extended, that is, its effective sign bit is spread to all - // the upper bits, which means that the relevant bits on the left - // side are either all 0, or all 1. - auto bits = Properties::getSignExtBits(curr->left); - uint32_t right = c->value.geti32(); - uint32_t numRelevantBits = 32 - bits + 1; - uint32_t setRelevantBits = - Bits::popCount(right >> uint32_t(bits - 1)); - // If all the relevant bits on C are zero - // then we can mask off the high bits instead of sign-extending x. - // This is valid because if x is negative, then the comparison was - // false before (negative vs positive), and will still be false - // as the sign bit will remain to cause a difference. And if x is - // positive then the upper bits would be zero anyhow. - if (setRelevantBits == 0) { - curr->left = makeZeroExt(ext, bits); - return replaceCurrent(curr); - } else if (setRelevantBits == numRelevantBits) { - // If all those bits are one, then we can do something similar if - // we also zero-extend on the right as well. This is valid - // because, as in the previous case, the sign bit differentiates - // the two sides when they are different, and if the sign bit is - // identical, then the upper bits don't matter, so masking them - // off both sides is fine. - curr->left = makeZeroExt(ext, bits); - c->value = c->value.and_(Literal(Bits::lowBitMask(bits))); - return replaceCurrent(curr); - } else { - // Otherwise, C's relevant bits are mixed, and then the two sides - // can never be equal, as the left side's bits cannot be mixed. - Builder builder(*getModule()); - // The result is either always true, or always false. - c->value = Literal::makeFromInt32(curr->op == NeInt32, c->type); - return replaceCurrent( - builder.makeSequence(builder.makeDrop(ext), c)); - } - } - } else if (auto* left = Properties::getSignExtValue(curr->left)) { - if (auto* right = Properties::getSignExtValue(curr->right)) { - auto bits = Properties::getSignExtBits(curr->left); - if (Properties::getSignExtBits(curr->right) == bits) { - // we are comparing two sign-exts with the same bits, so we may as - // well replace both with cheaper zexts - curr->left = makeZeroExt(left, bits); - curr->right = makeZeroExt(right, bits); - return replaceCurrent(curr); - } - } else if (auto* load = curr->right->dynCast()) { - // we are comparing a load to a sign-ext, we may be able to switch - // to zext - auto leftBits = Properties::getSignExtBits(curr->left); - if (load->signed_ && leftBits == load->bytes * 8) { - load->signed_ = false; - curr->left = makeZeroExt(left, leftBits); - return replaceCurrent(curr); - } - } - } else if (auto* load = curr->left->dynCast()) { - if (auto* right = Properties::getSignExtValue(curr->right)) { - // we are comparing a load to a sign-ext, we may be able to switch - // to zext - auto rightBits = Properties::getSignExtBits(curr->right); - if (load->signed_ && rightBits == load->bytes * 8) { - load->signed_ = false; - curr->right = makeZeroExt(right, rightBits); - return replaceCurrent(curr); - } + // We can in some cases remove part of a sign extend, that is, + // (x << A) >> B => x << (A - B) + // If the sign-extend input cannot have a sign bit, we don't need it. + if (Bits::getMaxBits(ext, this) + extraLeftShifts < bits) { + return removeAlmostSignExt(binary); + } + // We also don't need it if it already has an identical-sized sign + // extend applied to it. That is, if it is already a sign-extended + // value, then another sign extend will do nothing. We do need to be + // careful of the extra shifts, though. + if (isSignExted(ext, bits) && extraLeftShifts == 0) { + return removeAlmostSignExt(binary); } - } - // note that both left and right may be consts, but then we let - // precompute compute the constant result - } else if (curr->op == AddInt32 || curr->op == AddInt64 || - curr->op == SubInt32 || curr->op == SubInt64) { - if (auto* ret = optimizeAddedConstants(curr)) { - return replaceCurrent(ret); - } - } else if (curr->op == MulFloat32 || curr->op == MulFloat64 || - curr->op == DivFloat32 || curr->op == DivFloat64) { - if (curr->left->type == curr->right->type) { - if (auto* leftUnary = curr->left->dynCast()) { - if (leftUnary->op == Abstract::getUnary(curr->type, Abstract::Abs)) { - if (auto* rightUnary = curr->right->dynCast()) { - if (leftUnary->op == rightUnary->op) { // both are abs ops - // abs(x) * abs(y) ==> abs(x * y) - // abs(x) / abs(y) ==> abs(x / y) - curr->left = leftUnary->value; - curr->right = rightUnary->value; - leftUnary->value = curr; - return replaceCurrent(leftUnary); - } + } else if (binary->op == EqInt32 || binary->op == NeInt32) { + if (auto* c = binary->right->dynCast()) { + if (auto* ext = Properties::getSignExtValue(binary->left)) { + // We are comparing a sign extend to a constant, which means we can + // use a cheaper zero-extend in some cases. That is, + // (x << S) >> S ==/!= C => x & T ==/!= C + // where S and T are the matching values for sign/zero extend of the + // same size. For example, for an effective 8-bit value: + // (x << 24) >> 24 ==/!= C => x & 255 ==/!= C + // + // The key thing to track here are the upper bits plus the sign bit; + // call those the "relevant bits". This is crucial because x is + // sign-extended, that is, its effective sign bit is spread to all + // the upper bits, which means that the relevant bits on the left + // side are either all 0, or all 1. + auto bits = Properties::getSignExtBits(binary->left); + uint32_t right = c->value.geti32(); + uint32_t numRelevantBits = 32 - bits + 1; + uint32_t setRelevantBits = + Bits::popCount(right >> uint32_t(bits - 1)); + // If all the relevant bits on C are zero + // then we can mask off the high bits instead of sign-extending x. + // This is valid because if x is negative, then the comparison was + // false before (negative vs positive), and will still be false + // as the sign bit will remain to cause a difference. And if x is + // positive then the upper bits would be zero anyhow. + if (setRelevantBits == 0) { + binary->left = makeZeroExt(ext, bits); + return binary; + } else if (setRelevantBits == numRelevantBits) { + // If all those bits are one, then we can do something similar if + // we also zero-extend on the right as well. This is valid + // because, as in the previous case, the sign bit differentiates + // the two sides when they are different, and if the sign bit is + // identical, then the upper bits don't matter, so masking them + // off both sides is fine. + binary->left = makeZeroExt(ext, bits); + c->value = c->value.and_(Literal(Bits::lowBitMask(bits))); + return binary; + } else { + // Otherwise, C's relevant bits are mixed, and then the two sides + // can never be equal, as the left side's bits cannot be mixed. + Builder builder(*getModule()); + // The result is either always true, or always false. + c->value = Literal::makeFromInt32(binary->op == NeInt32, c->type); + return builder.makeSequence(builder.makeDrop(ext), c); + } + } + } else if (auto* left = Properties::getSignExtValue(binary->left)) { + if (auto* right = Properties::getSignExtValue(binary->right)) { + auto bits = Properties::getSignExtBits(binary->left); + if (Properties::getSignExtBits(binary->right) == bits) { + // we are comparing two sign-exts with the same bits, so we may as + // well replace both with cheaper zexts + binary->left = makeZeroExt(left, bits); + binary->right = makeZeroExt(right, bits); + return binary; + } + } else if (auto* load = binary->right->dynCast()) { + // we are comparing a load to a sign-ext, we may be able to switch + // to zext + auto leftBits = Properties::getSignExtBits(binary->left); + if (load->signed_ && leftBits == load->bytes * 8) { + load->signed_ = false; + binary->left = makeZeroExt(left, leftBits); + return binary; } } - } - } - } - // a bunch of operations on a constant right side can be simplified - if (auto* right = curr->right->dynCast()) { - if (curr->op == AndInt32) { - auto mask = right->value.geti32(); - // and with -1 does nothing (common in asm.js output) - if (mask == -1) { - return replaceCurrent(curr->left); - } - // small loads do not need to be masked, the load itself masks - if (auto* load = curr->left->dynCast()) { - if ((load->bytes == 1 && mask == 0xff) || - (load->bytes == 2 && mask == 0xffff)) { - load->signed_ = false; - return replaceCurrent(curr->left); - } - } else if (auto maskedBits = Bits::getMaskedBits(mask)) { - if (Bits::getMaxBits(curr->left, this) <= maskedBits) { - // a mask of lower bits is not needed if we are already smaller - return replaceCurrent(curr->left); + } else if (auto* load = binary->left->dynCast()) { + if (auto* right = Properties::getSignExtValue(binary->right)) { + // we are comparing a load to a sign-ext, we may be able to switch + // to zext + auto rightBits = Properties::getSignExtBits(binary->right); + if (load->signed_ && rightBits == load->bytes * 8) { + load->signed_ = false; + binary->right = makeZeroExt(right, rightBits); + return binary; + } } } - } - // some math operations have trivial results - if (auto* ret = optimizeWithConstantOnRight(curr)) { - return replaceCurrent(ret); - } - // the square of some operations can be merged - if (auto* left = curr->left->dynCast()) { - if (left->op == curr->op) { - if (auto* leftRight = left->right->dynCast()) { - if (left->op == AndInt32 || left->op == AndInt64) { - leftRight->value = leftRight->value.and_(right->value); - return replaceCurrent(left); - } else if (left->op == OrInt32 || left->op == OrInt64) { - leftRight->value = leftRight->value.or_(right->value); - return replaceCurrent(left); - } else if (left->op == XorInt32 || left->op == XorInt64) { - leftRight->value = leftRight->value.xor_(right->value); - return replaceCurrent(left); - } else if (left->op == MulInt32 || left->op == MulInt64) { - leftRight->value = leftRight->value.mul(right->value); - return replaceCurrent(left); - - // TODO: - // handle signed / unsigned divisions. They are more complex - } else if (left->op == ShlInt32 || left->op == ShrUInt32 || - left->op == ShrSInt32 || left->op == ShlInt64 || - left->op == ShrUInt64 || left->op == ShrSInt64) { - // shifts only use an effective amount from the constant, so - // adding must be done carefully - auto total = Bits::getEffectiveShifts(leftRight) + - Bits::getEffectiveShifts(right); - if (total == Bits::getEffectiveShifts(total, right->type)) { - // no overflow, we can do this - leftRight->value = Literal::makeFromInt32(total, right->type); - return replaceCurrent(left); - } // TODO: handle overflows + // note that both left and right may be consts, but then we let + // precompute compute the constant result + } else if (binary->op == AddInt32 || binary->op == AddInt64 || + binary->op == SubInt32 || binary->op == SubInt64) { + if (auto* ret = optimizeAddedConstants(binary)) { + return ret; + } + } else if (binary->op == MulFloat32 || binary->op == MulFloat64 || + binary->op == DivFloat32 || binary->op == DivFloat64) { + if (binary->left->type == binary->right->type) { + if (auto* leftUnary = binary->left->dynCast()) { + if (leftUnary->op == + Abstract::getUnary(binary->type, Abstract::Abs)) { + if (auto* rightUnary = binary->right->dynCast()) { + if (leftUnary->op == rightUnary->op) { // both are abs ops + // abs(x) * abs(y) ==> abs(x * y) + // abs(x) / abs(y) ==> abs(x / y) + binary->left = leftUnary->value; + binary->right = rightUnary->value; + leftUnary->value = binary; + return leftUnary; + } + } } } } } - if (right->type == Type::i32) { - BinaryOp op; - int32_t c = right->value.geti32(); - // First, try to lower signed operations to unsigned if that is - // possible. Some unsigned operations like div_u or rem_u are usually - // faster on VMs. Also this opens more possibilities for further - // simplifications afterwards. - if (c >= 0 && (op = makeUnsignedBinaryOp(curr->op)) != InvalidBinary && - Bits::getMaxBits(curr->left, this) <= 31) { - curr->op = op; - } - if (c < 0 && c > std::numeric_limits::min() && - curr->op == DivUInt32) { - // u32(x) / C ==> u32(x) >= C iff C > 2^31 - // We avoid applying this for C == 2^31 due to conflict - // with other rule which transform to more prefereble - // right shift operation. - curr->op = c == -1 ? EqInt32 : GeUInt32; - return replaceCurrent(curr); - } - if (Bits::isPowerOf2((uint32_t)c)) { - switch (curr->op) { - case MulInt32: - return replaceCurrent(optimizePowerOf2Mul(curr, (uint32_t)c)); - case RemUInt32: - return replaceCurrent(optimizePowerOf2URem(curr, (uint32_t)c)); - case DivUInt32: - return replaceCurrent(optimizePowerOf2UDiv(curr, (uint32_t)c)); - default: - break; + // a bunch of operations on a constant right side can be simplified + if (auto* right = binary->right->dynCast()) { + if (binary->op == AndInt32) { + auto mask = right->value.geti32(); + // and with -1 does nothing (common in asm.js output) + if (mask == -1) { + return binary->left; } - } - } - if (right->type == Type::i64) { - BinaryOp op; - int64_t c = right->value.geti64(); - // See description above for Type::i32 - if (c >= 0 && (op = makeUnsignedBinaryOp(curr->op)) != InvalidBinary && - Bits::getMaxBits(curr->left, this) <= 63) { - curr->op = op; - } - if (getPassOptions().shrinkLevel == 0 && c < 0 && - c > std::numeric_limits::min() && curr->op == DivUInt64) { - // u64(x) / C ==> u64(u64(x) >= C) iff C > 2^63 - // We avoid applying this for C == 2^31 due to conflict - // with other rule which transform to more prefereble - // right shift operation. - // And apply this only for shrinkLevel == 0 due to it - // increasing size by one byte. - curr->op = c == -1LL ? EqInt64 : GeUInt64; - curr->type = Type::i32; - return replaceCurrent( - Builder(*getModule()).makeUnary(ExtendUInt32, curr)); - } - if (Bits::isPowerOf2((uint64_t)c)) { - switch (curr->op) { - case MulInt64: - return replaceCurrent(optimizePowerOf2Mul(curr, (uint64_t)c)); - case RemUInt64: - return replaceCurrent(optimizePowerOf2URem(curr, (uint64_t)c)); - case DivUInt64: - return replaceCurrent(optimizePowerOf2UDiv(curr, (uint64_t)c)); - default: - break; + // small loads do not need to be masked, the load itself masks + if (auto* load = binary->left->dynCast()) { + if ((load->bytes == 1 && mask == 0xff) || + (load->bytes == 2 && mask == 0xffff)) { + load->signed_ = false; + return binary->left; + } + } else if (auto maskedBits = Bits::getMaskedBits(mask)) { + if (Bits::getMaxBits(binary->left, this) <= maskedBits) { + // a mask of lower bits is not needed if we are already smaller + return binary->left; + } } } - } - if (curr->op == DivFloat32) { - float c = right->value.getf32(); - if (Bits::isPowerOf2InvertibleFloat(c)) { - return replaceCurrent(optimizePowerOf2FDiv(curr, c)); - } - } - if (curr->op == DivFloat64) { - double c = right->value.getf64(); - if (Bits::isPowerOf2InvertibleFloat(c)) { - return replaceCurrent(optimizePowerOf2FDiv(curr, c)); - } - } - } - // a bunch of operations on a constant left side can be simplified - if (curr->left->is()) { - if (auto* ret = optimizeWithConstantOnLeft(curr)) { - return replaceCurrent(ret); - } - } - if (curr->op == AndInt32 || curr->op == OrInt32) { - if (curr->op == AndInt32) { - if (auto* ret = combineAnd(curr)) { - return replaceCurrent(ret); - } - } - // for or, we can potentially combine - if (curr->op == OrInt32) { - if (auto* ret = combineOr(curr)) { - return replaceCurrent(ret); - } - } - // bitwise operations - // for and and or, we can potentially conditionalize - if (auto* ret = conditionalizeExpensiveOnBitwise(curr)) { - return replaceCurrent(ret); - } - } - // relation/comparisons allow for math optimizations - if (curr->isRelational()) { - if (auto* ret = optimizeRelational(curr)) { - return replaceCurrent(ret); - } - } - // finally, try more expensive operations on the curr in - // the case that they have no side effects - if (!effects(curr->left).hasSideEffects()) { - if (ExpressionAnalyzer::equal(curr->left, curr->right)) { - if (auto* ret = optimizeBinaryWithEqualEffectlessChildren(curr)) { - return replaceCurrent(ret); - } - } - } - - if (auto* ret = deduplicateBinary(curr)) { - return replaceCurrent(ret); - } - } - - void visitUnary(Unary* curr) { - if (curr->type == Type::unreachable) { - return; - } + // some math operations have trivial results + if (auto* ret = optimizeWithConstantOnRight(binary)) { + return ret; + } + // the square of some operations can be merged + if (auto* left = binary->left->dynCast()) { + if (left->op == binary->op) { + if (auto* leftRight = left->right->dynCast()) { + if (left->op == AndInt32 || left->op == AndInt64) { + leftRight->value = leftRight->value.and_(right->value); + return left; + } else if (left->op == OrInt32 || left->op == OrInt64) { + leftRight->value = leftRight->value.or_(right->value); + return left; + } else if (left->op == XorInt32 || left->op == XorInt64) { + leftRight->value = leftRight->value.xor_(right->value); + return left; + } else if (left->op == MulInt32 || left->op == MulInt64) { + leftRight->value = leftRight->value.mul(right->value); + return left; - { - using namespace Match; - using namespace Abstract; - Builder builder(*getModule()); - { - // eqz(x - y) => x == y - Binary* inner; - if (matches(curr, unary(EqZ, binary(&inner, Sub, any(), any())))) { - inner->op = Abstract::getBinary(inner->left->type, Eq); - inner->type = Type::i32; - return replaceCurrent(inner); - } - } - { - // eqz(x + C) => x == -C - Const* c; - Binary* inner; - if (matches(curr, unary(EqZ, binary(&inner, Add, any(), ival(&c))))) { - c->value = c->value.neg(); - inner->op = Abstract::getBinary(c->type, Eq); - inner->type = Type::i32; - return replaceCurrent(inner); - } - } - { - // eqz((signed)x % C_pot) => eqz(x & (abs(C_pot) - 1)) - Const* c; - Binary* inner; - if (matches(curr, unary(EqZ, binary(&inner, RemS, any(), ival(&c)))) && - (c->value.isSignedMin() || - Bits::isPowerOf2(c->value.abs().getInteger()))) { - inner->op = Abstract::getBinary(c->type, And); - if (c->value.isSignedMin()) { - c->value = Literal::makeSignedMax(c->type); - } else { - c->value = c->value.abs().sub(Literal::makeOne(c->type)); + // TODO: + // handle signed / unsigned divisions. They are more complex + } else if (left->op == ShlInt32 || left->op == ShrUInt32 || + left->op == ShrSInt32 || left->op == ShlInt64 || + left->op == ShrUInt64 || left->op == ShrSInt64) { + // shifts only use an effective amount from the constant, so + // adding must be done carefully + auto total = Bits::getEffectiveShifts(leftRight) + + Bits::getEffectiveShifts(right); + if (total == Bits::getEffectiveShifts(total, right->type)) { + // no overflow, we can do this + leftRight->value = Literal::makeFromInt32(total, right->type); + return left; + } // TODO: handle overflows + } + } } - return replaceCurrent(curr); } - } - { - // i32.wrap_i64(i64.extend_i32_s(x)) => x - // i32.wrap_i64(i64.extend_i32_u(x)) => x - Unary* inner; - Expression* x; - if (matches(curr, - unary(WrapInt64, unary(&inner, ExtendSInt32, any(&x)))) || - matches(curr, - unary(WrapInt64, unary(&inner, ExtendUInt32, any(&x))))) { - return replaceCurrent(x); - } - } - { - // i32.eqz(i32.wrap_i64(x)) => i64.eqz(x) - // where maxBits(x) <= 32 - Unary* inner; - Expression* x; - if (matches(curr, unary(EqZInt32, unary(&inner, WrapInt64, any(&x)))) && - Bits::getMaxBits(x, this) <= 32) { - inner->op = EqZInt64; - inner->value = x; - return replaceCurrent(inner); - } - } - { - // i64.extend_i32_s(i32.wrap_i64(x)) => x - // where maxBits(x) <= 31 - // - // i64.extend_i32_u(i32.wrap_i64(x)) => x - // where maxBits(x) <= 32 - Expression* x; - UnaryOp unaryOp; - if (matches(curr, unary(&unaryOp, unary(WrapInt64, any(&x))))) { - if (unaryOp == ExtendSInt32 || unaryOp == ExtendUInt32) { - auto maxBits = Bits::getMaxBits(x, this); - if ((unaryOp == ExtendSInt32 && maxBits <= 31) || - (unaryOp == ExtendUInt32 && maxBits <= 32)) { - return replaceCurrent(x); + if (right->type == Type::i32) { + BinaryOp op; + int32_t c = right->value.geti32(); + // First, try to lower signed operations to unsigned if that is + // possible. Some unsigned operations like div_u or rem_u are usually + // faster on VMs. Also this opens more possibilities for further + // simplifications afterwards. + if (c >= 0 && + (op = makeUnsignedBinaryOp(binary->op)) != InvalidBinary && + Bits::getMaxBits(binary->left, this) <= 31) { + binary->op = op; + } + if (c < 0 && c > std::numeric_limits::min() && + binary->op == DivUInt32) { + // u32(x) / C ==> u32(x) >= C iff C > 2^31 + // We avoid applying this for C == 2^31 due to conflict + // with other rule which transform to more prefereble + // right shift operation. + binary->op = c == -1 ? EqInt32 : GeUInt32; + return binary; + } + if (Bits::isPowerOf2((uint32_t)c)) { + switch (binary->op) { + case MulInt32: + return optimizePowerOf2Mul(binary, (uint32_t)c); + case RemUInt32: + return optimizePowerOf2URem(binary, (uint32_t)c); + case DivUInt32: + return optimizePowerOf2UDiv(binary, (uint32_t)c); + default: + break; } } } - } - if (getModule()->features.hasSignExt()) { - // i64.extend_i32_s(i32.wrap_i64(x)) => i64.extend32_s(x) - Unary* inner; - Expression* x; - if (matches(curr, - unary(ExtendSInt32, unary(&inner, WrapInt64, any(&x))))) { - inner->op = ExtendS32Int64; - inner->type = Type::i64; - inner->value = x; - return replaceCurrent(inner); - } - } - } - - if (curr->op == ExtendUInt32 || curr->op == ExtendSInt32) { - if (auto* load = curr->value->dynCast()) { - // i64.extend_i32_s(i32.load(_8|_16)(_u|_s)(x)) => - // i64.load(_8|_16|_32)(_u|_s)(x) - // - // i64.extend_i32_u(i32.load(_8|_16)(_u|_s)(x)) => - // i64.load(_8|_16|_32)(_u|_s)(x) - // - // but we can't do this in following cases: - // - // i64.extend_i32_u(i32.load8_s(x)) - // i64.extend_i32_u(i32.load16_s(x)) - // - // this mixed sign/zero extensions can't represent in single - // signed or unsigned 64-bit load operation. For example if `load8_s(x)` - // return i8(-1) (0xFF) than sign extended result will be - // i32(-1) (0xFFFFFFFF) and with zero extension to i64 we got - // finally 0x00000000FFFFFFFF. However with `i64.load8_s` in this - // situation we got `i64(-1)` (all ones) and with `i64.load8_u` it - // will be 0x00000000000000FF. - // - // Another limitation is atomics which only have unsigned loads. - // So we also avoid this only case: - // - // i64.extend_i32_s(i32.atomic.load(x)) - - // Special case for i32.load. In this case signedness depends on - // extend operation. - bool willBeSigned = curr->op == ExtendSInt32 && load->bytes == 4; - if (!(curr->op == ExtendUInt32 && load->bytes <= 2 && load->signed_) && - !(willBeSigned && load->isAtomic)) { - if (willBeSigned) { - load->signed_ = true; - } - load->type = Type::i64; - return replaceCurrent(load); - } - } - } - - if (Abstract::hasAnyReinterpret(curr->op)) { - // i32.reinterpret_f32(f32.reinterpret_i32(x)) => x - // i64.reinterpret_f64(f64.reinterpret_i64(x)) => x - // f32.reinterpret_i32(i32.reinterpret_f32(x)) => x - // f64.reinterpret_i64(i64.reinterpret_f64(x)) => x - if (auto* inner = curr->value->dynCast()) { - if (Abstract::hasAnyReinterpret(inner->op)) { - if (inner->value->type == curr->type) { - return replaceCurrent(inner->value); - } - } - } - // f32.reinterpret_i32(i32.load(x)) => f32.load(x) - // f64.reinterpret_i64(i64.load(x)) => f64.load(x) - // i32.reinterpret_f32(f32.load(x)) => i32.load(x) - // i64.reinterpret_f64(f64.load(x)) => i64.load(x) - if (auto* load = curr->value->dynCast()) { - if (!load->isAtomic && load->bytes == curr->type.getByteSize()) { - load->type = curr->type; - return replaceCurrent(load); - } - } - } - - if (curr->op == EqZInt32) { - if (auto* inner = curr->value->dynCast()) { - // Try to invert a relational operation using De Morgan's law - auto op = invertBinaryOp(inner->op); - if (op != InvalidBinary) { - inner->op = op; - return replaceCurrent(inner); - } - } - // eqz of a sign extension can be of zero-extension - if (auto* ext = Properties::getSignExtValue(curr->value)) { - // we are comparing a sign extend to a constant, which means we can - // use a cheaper zext - auto bits = Properties::getSignExtBits(curr->value); - curr->value = makeZeroExt(ext, bits); - return replaceCurrent(curr); - } - } else if (curr->op == AbsFloat32 || curr->op == AbsFloat64) { - // abs(-x) ==> abs(x) - if (auto* unaryInner = curr->value->dynCast()) { - if (unaryInner->op == - Abstract::getUnary(unaryInner->type, Abstract::Neg)) { - curr->value = unaryInner->value; - return replaceCurrent(curr); - } - } - // abs(x * x) ==> x * x - // abs(x / x) ==> x / x - if (auto* binary = curr->value->dynCast()) { - if ((binary->op == Abstract::getBinary(binary->type, Abstract::Mul) || - binary->op == Abstract::getBinary(binary->type, Abstract::DivS)) && - ExpressionAnalyzer::equal(binary->left, binary->right)) { - return replaceCurrent(binary); - } - // abs(0 - x) ==> abs(x), - // only for fast math - if (fastMath && - binary->op == Abstract::getBinary(binary->type, Abstract::Sub)) { - if (auto* c = binary->left->dynCast()) { - if (c->value.isZero()) { - curr->value = binary->right; - return replaceCurrent(curr); + if (right->type == Type::i64) { + BinaryOp op; + int64_t c = right->value.geti64(); + // See description above for Type::i32 + if (c >= 0 && + (op = makeUnsignedBinaryOp(binary->op)) != InvalidBinary && + Bits::getMaxBits(binary->left, this) <= 63) { + binary->op = op; + } + if (getPassOptions().shrinkLevel == 0 && c < 0 && + c > std::numeric_limits::min() && + binary->op == DivUInt64) { + // u64(x) / C ==> u64(u64(x) >= C) iff C > 2^63 + // We avoid applying this for C == 2^31 due to conflict + // with other rule which transform to more prefereble + // right shift operation. + // And apply this only for shrinkLevel == 0 due to it + // increasing size by one byte. + binary->op = c == -1LL ? EqInt64 : GeUInt64; + binary->type = Type::i32; + return Builder(*getModule()).makeUnary(ExtendUInt32, binary); + } + if (Bits::isPowerOf2((uint64_t)c)) { + switch (binary->op) { + case MulInt64: + return optimizePowerOf2Mul(binary, (uint64_t)c); + case RemUInt64: + return optimizePowerOf2URem(binary, (uint64_t)c); + case DivUInt64: + return optimizePowerOf2UDiv(binary, (uint64_t)c); + default: + break; } } } - } - } - - if (auto* ret = deduplicateUnary(curr)) { - return replaceCurrent(ret); - } - } - - void visitSelect(Select* curr) { - if (curr->type == Type::unreachable) { - return; - } - if (auto* ret = optimizeSelect(curr)) { - return replaceCurrent(ret); - } - optimizeTernary(curr); - } - - void visitGlobalSet(GlobalSet* curr) { - if (curr->type == Type::unreachable) { - return; - } - // optimize out a set of a get - auto* get = curr->value->dynCast(); - if (get && get->name == curr->name) { - ExpressionManipulator::nop(curr); - return replaceCurrent(curr); - } - } - - void visitBlock(Block* curr) { - if (getModule()->features.hasGC()) { - optimizeHeapStores(curr->list); - } - } - - void visitIf(If* curr) { - curr->condition = optimizeBoolean(curr->condition); - if (curr->ifFalse) { - if (auto* unary = curr->condition->dynCast()) { - if (unary->op == EqZInt32) { - // flip if-else arms to get rid of an eqz - curr->condition = unary->value; - std::swap(curr->ifTrue, curr->ifFalse); - } - } - if (curr->condition->type != Type::unreachable && - ExpressionAnalyzer::equal(curr->ifTrue, curr->ifFalse)) { - // The sides are identical, so fold. If we can replace the If with one - // arm and there are no side effects in the condition, replace it. But - // make sure not to change a concrete expression to an unreachable - // expression because we want to avoid having to refinalize. - bool needCondition = effects(curr->condition).hasSideEffects(); - bool wouldBecomeUnreachable = - curr->type.isConcrete() && curr->ifTrue->type == Type::unreachable; - Builder builder(*getModule()); - if (!wouldBecomeUnreachable && !needCondition) { - return replaceCurrent(curr->ifTrue); - } else if (!wouldBecomeUnreachable) { - return replaceCurrent(builder.makeSequence( - builder.makeDrop(curr->condition), curr->ifTrue)); - } else { - // Emit a block with the original concrete type. - auto* ret = builder.makeBlock(); - if (needCondition) { - ret->list.push_back(builder.makeDrop(curr->condition)); + if (binary->op == DivFloat32) { + float c = right->value.getf32(); + if (Bits::isPowerOf2InvertibleFloat(c)) { + return optimizePowerOf2FDiv(binary, c); } - ret->list.push_back(curr->ifTrue); - ret->finalize(curr->type); - return replaceCurrent(ret); - } - } - optimizeTernary(curr); - } - } - - void visitLocalSet(LocalSet* curr) { - // Interactions between local.set/tee and ref.as_non_null can be optimized - // in some cases, by removing or moving the ref.as_non_null operation. In - // all cases, we only do this when we do *not* allow non-nullable locals. If - // we do allow such locals, then (1) this local might be non-nullable, so we - // can't remove or move a ref.as_non_null flowing into a local.set/tee, and - // (2) even if the local were nullable, if we change things we might prevent - // the LocalSubtyping pass from turning it into a non-nullable local later. - // Note that we must also check if this local is nullable regardless, as a - // parameter might be non-nullable even if nullable locals are disallowed - // (as that just affects vars, and not params). - if (auto* as = curr->value->dynCast()) { - if (as->op == RefAsNonNull && !getModule()->features.hasGCNNLocals() && - getFunction()->getLocalType(curr->index).isNullable()) { - // (local.tee (ref.as_non_null ..)) - // => - // (ref.as_non_null (local.tee ..)) - // - // The reordering allows the ref.as to be potentially optimized further - // based on where the value flows to. - if (curr->isTee()) { - curr->value = as->value; - curr->finalize(); - as->value = curr; - as->finalize(); - replaceCurrent(as); - return; } - - // Otherwise, if this is not a tee, then no value falls through. The - // ref.as_non_null acts as a null check here, basically. If we are - // ignoring such traps, we can remove it. - auto& passOptions = getPassOptions(); - if (passOptions.ignoreImplicitTraps || passOptions.trapsNeverHappen) { - curr->value = as->value; - } - } - } - } - - void visitBreak(Break* curr) { - if (curr->condition) { - curr->condition = optimizeBoolean(curr->condition); - } - } - - void visitLoad(Load* curr) { - if (curr->type == Type::unreachable) { - return; - } - optimizeMemoryAccess(curr->ptr, curr->offset); - } - - void visitStore(Store* curr) { - if (curr->type == Type::unreachable) { - return; - } - optimizeMemoryAccess(curr->ptr, curr->offset); - optimizeStoredValue(curr->value, curr->bytes); - if (auto* unary = curr->value->dynCast()) { - if (unary->op == WrapInt64) { - // instead of wrapping to 32, just store some of the bits in the i64 - curr->valueType = Type::i64; - curr->value = unary->value; - } else if (!curr->isAtomic && Abstract::hasAnyReinterpret(unary->op) && - curr->bytes == curr->valueType.getByteSize()) { - // f32.store(y, f32.reinterpret_i32(x)) => i32.store(y, x) - // f64.store(y, f64.reinterpret_i64(x)) => i64.store(y, x) - // i32.store(y, i32.reinterpret_f32(x)) => f32.store(y, x) - // i64.store(y, i64.reinterpret_f64(x)) => f64.store(y, x) - curr->valueType = unary->value->type; - curr->value = unary->value; - } - } - } - - void optimizeStoredValue(Expression*& value, Index bytes) { - if (!value->type.isInteger()) { - return; - } - // truncates constant values during stores - // (i32|i64).store(8|16|32)(p, C) ==> - // (i32|i64).store(8|16|32)(p, C & mask) - if (auto* c = value->dynCast()) { - if (value->type == Type::i64 && bytes == 4) { - c->value = c->value.and_(Literal(uint64_t(0xffffffff))); - } else { - c->value = c->value.and_( - Literal::makeFromInt32(Bits::lowBitMask(bytes * 8), value->type)); - } - } - // stores of fewer bits truncates anyhow - if (auto* binary = value->dynCast()) { - if (binary->op == AndInt32) { - if (auto* right = binary->right->dynCast()) { - if (right->type == Type::i32) { - auto mask = right->value.geti32(); - if ((bytes == 1 && mask == 0xff) || - (bytes == 2 && mask == 0xffff)) { - value = binary->left; - } + if (binary->op == DivFloat64) { + double c = right->value.getf64(); + if (Bits::isPowerOf2InvertibleFloat(c)) { + return optimizePowerOf2FDiv(binary, c); } } - } else if (auto* ext = Properties::getSignExtValue(binary)) { - // if sign extending the exact bit size we store, we can skip the - // extension if extending something bigger, then we just alter bits we - // don't save anyhow - if (Properties::getSignExtBits(binary) >= Index(bytes) * 8) { - value = ext; - } - } - } - } - - void visitMemoryCopy(MemoryCopy* curr) { - if (curr->type == Type::unreachable) { - return; - } - assert(getModule()->features.hasBulkMemory()); - if (auto* ret = optimizeMemoryCopy(curr)) { - return replaceCurrent(ret); - } - } - - void visitMemoryFill(MemoryFill* curr) { - if (curr->type == Type::unreachable) { - return; - } - assert(getModule()->features.hasBulkMemory()); - if (auto* ret = optimizeMemoryFill(curr)) { - return replaceCurrent(ret); - } - } - - void visitCallRef(CallRef* curr) { - if (curr->target->type == Type::unreachable) { - // The call_ref is not reached; leave this for DCE. - return; - } - - if (auto* ref = curr->target->dynCast()) { - // We know the target! - replaceCurrent( - Builder(*getModule()) - .makeCall(ref->func, curr->operands, curr->type, curr->isReturn)); - return; - } - - if (auto* get = curr->target->dynCast()) { - // (call_ref ..args.. (table.get $table (index)) - // => - // (call_indirect $table ..args.. (index)) - replaceCurrent(Builder(*getModule()) - .makeCallIndirect(get->table, - get->index, - curr->operands, - get->type.getHeapType(), - curr->isReturn)); - return; - } - - auto features = getModule()->features; - - // It is possible the target is not a function reference, but we can infer - // the fallthrough value there. It takes more work to optimize this case, - // but it is pretty important to allow a call_ref to become a fast direct - // call, so make the effort. - if (auto* ref = Properties::getFallthrough( - curr->target, getPassOptions(), *getModule()) - ->dynCast()) { - // Check if the fallthrough make sense. We may have cast it to a different - // type, which would be a problem - we'd be replacing a call_ref to one - // type with a direct call to a function of another type. That would trap - // at runtime; be careful not to emit invalid IR here. - if (curr->target->type.getHeapType() != ref->type.getHeapType()) { - return; - } - Builder builder(*getModule()); - if (curr->operands.empty()) { - // No operands, so this is simple and there is nothing to reorder: just - // emit: - // - // (block - // (drop curr->target) - // (call ref.func-from-curr->target) - // ) - replaceCurrent(builder.makeSequence( - builder.makeDrop(curr->target), - builder.makeCall(ref->func, {}, curr->type, curr->isReturn))); - return; - } - - // In the presence of operands, we must execute the code in curr->target - // after the last operand and before the call happens. Interpose at the - // last operand: - // - // (call ref.func-from-curr->target) - // (operand1) - // (..) - // (operandN-1) - // (block - // (local.set $temp (operandN)) - // (drop curr->target) - // (local.get $temp) - // ) - // ) - auto* lastOperand = curr->operands.back(); - auto lastOperandType = lastOperand->type; - if (lastOperandType == Type::unreachable) { - // The call_ref is not reached; leave this for DCE. - return; - } - if (!TypeUpdating::canHandleAsLocal(lastOperandType)) { - // We cannot create a local, so we must give up. - return; - } - Index tempLocal = builder.addVar( - getFunction(), - TypeUpdating::getValidLocalType(lastOperandType, features)); - auto* set = builder.makeLocalSet(tempLocal, lastOperand); - auto* drop = builder.makeDrop(curr->target); - auto* get = TypeUpdating::fixLocalGet( - builder.makeLocalGet(tempLocal, lastOperandType), *getModule()); - curr->operands.back() = builder.makeBlock({set, drop, get}); - replaceCurrent(builder.makeCall( - ref->func, curr->operands, curr->type, curr->isReturn)); - } - } - - void visitRefEq(RefEq* curr) { - // Identical references compare equal. - if (areConsecutiveInputsEqualAndRemovable(curr->left, curr->right)) { - replaceCurrent( - Builder(*getModule()).makeConst(Literal::makeOne(Type::i32))); - return; - } - - // Canonicalize to the pattern of a null on the right-hand side, if there is - // one. This makes pattern matching simpler. - if (curr->left->is()) { - std::swap(curr->left, curr->right); - } - - // RefEq of a value to Null can be replaced with RefIsNull. - if (curr->right->is()) { - replaceCurrent(Builder(*getModule()).makeRefIs(RefIsNull, curr->left)); - } - } - - // If an instruction traps on a null input, there is no need for a - // ref.as_non_null on that input: we will trap either way (and the binaryen - // optimizer does not differentiate traps). - void skipNonNullCast(Expression*& input) { - while (1) { - if (auto* as = input->dynCast()) { - if (as->op == RefAsNonNull) { - input = as->value; - continue; - } - } - break; - } - } - - void visitStructGet(StructGet* curr) { skipNonNullCast(curr->ref); } - - void visitStructSet(StructSet* curr) { - skipNonNullCast(curr->ref); - - if (curr->ref->type != Type::unreachable && curr->value->type.isInteger()) { - const auto& fields = curr->ref->type.getHeapType().getStruct().fields; - optimizeStoredValue(curr->value, fields[curr->index].getByteSize()); - } - - // If our reference is a tee of a struct.new, we may be able to fold the - // stored value into the new itself: - // - // (struct.set (local.tee $x (struct.new X Y Z)) X') - // => - // (local.set $x (struct.new X' Y Z)) - // - if (auto* tee = curr->ref->dynCast()) { - if (auto* new_ = tee->value->dynCast()) { - if (optimizeSubsequentStructSet(new_, curr, tee->index)) { - // Success, so we do not need the struct.set any more, and the tee - // can just be a set instead of us. - tee->makeSet(); - replaceCurrent(tee); - } - } - } - } - - // Similar to the above with struct.set whose reference is a tee of a new, we - // can do the same for subsequent sets in a list: - // - // (local.set $x (struct.new X Y Z)) - // (struct.set (local.get $x) X') - // => - // (local.set $x (struct.new X' Y Z)) - // - // We also handle other struct.sets immediately after this one, but we only - // handle the case where they are all in sequence and right after the - // local.set (anything in the middle of this pattern will stop us from - // optimizing later struct.sets, which might be improved later but would - // require an analysis of effects TODO). - void optimizeHeapStores(ExpressionList& list) { - for (Index i = 0; i < list.size(); i++) { - auto* localSet = list[i]->dynCast(); - if (!localSet) { - continue; } - auto* new_ = localSet->value->dynCast(); - if (!new_) { - continue; - } - - // This local.set of a struct.new looks good. Find struct.sets after it - // to optimize. - for (Index j = i + 1; j < list.size(); j++) { - auto* structSet = list[j]->dynCast(); - if (!structSet) { - // Any time the pattern no longer matches, stop optimizing possible - // struct.sets for this struct.new. - break; - } - auto* localGet = structSet->ref->dynCast(); - if (!localGet || localGet->index != localSet->index) { - break; + // a bunch of operations on a constant left side can be simplified + if (binary->left->is()) { + if (auto* ret = optimizeWithConstantOnLeft(binary)) { + return ret; } - if (!optimizeSubsequentStructSet(new_, structSet, localGet->index)) { - break; - } else { - // Success. Replace the set with a nop, and continue to - // perhaps optimize more. - ExpressionManipulator::nop(structSet); - } - } - } - } - - // Given a struct.new and a struct.set that occurs right after it, and that - // applies to the same data, try to apply the set during the new. This can be - // either with a nested tee: - // - // (struct.set - // (local.tee $x (struct.new X Y Z)) - // X' - // ) - // => - // (local.set $x (struct.new X' Y Z)) - // - // or without: - // - // (local.set $x (struct.new X Y Z)) - // (struct.set (local.get $x) X') - // => - // (local.set $x (struct.new X' Y Z)) - // - // Returns true if we succeeded. - bool optimizeSubsequentStructSet(StructNew* new_, - StructSet* set, - Index refLocalIndex) { - // Leave unreachable code for DCE, to avoid updating types here. - if (new_->type == Type::unreachable || set->type == Type::unreachable) { - return false; - } - - if (new_->isWithDefault()) { - // Ignore a new_default for now. If the fields are defaultable then we - // could add them, in principle, but that might increase code size. - return false; - } - - auto index = set->index; - auto& operands = new_->operands; - - // Check for effects that prevent us moving the struct.set's value (X' in - // the function comment) into its new position in the struct.new. First, it - // must be ok to move it past the local.set (otherwise, it might read from - // memory using that local, and depend on the struct.new having already - // occurred; or, if it writes to that local, then it would cross another - // write). - auto setValueEffects = effects(set->value); - if (setValueEffects.localsRead.count(refLocalIndex) || - setValueEffects.localsWritten.count(refLocalIndex)) { - return false; - } - - // We must move the set's value past indexes greater than it (Y and Z in - // the example in the comment on this function). - // TODO When this function is called repeatedly in a sequence this can - // become quadratic - perhaps we should memoize (though, struct sizes - // tend to not be ridiculously large). - for (Index i = index + 1; i < operands.size(); i++) { - auto operandEffects = effects(operands[i]); - if (operandEffects.invalidates(setValueEffects)) { - // TODO: we could use locals to reorder everything - return false; - } - } - - Builder builder(*getModule()); - - // See if we need to keep the old value. - if (effects(operands[index]).hasUnremovableSideEffects()) { - operands[index] = - builder.makeSequence(builder.makeDrop(operands[index]), set->value); - } else { - operands[index] = set->value; - } - - return true; - } - - void visitArrayGet(ArrayGet* curr) { skipNonNullCast(curr->ref); } - - void visitArraySet(ArraySet* curr) { - skipNonNullCast(curr->ref); - - if (curr->ref->type != Type::unreachable && curr->value->type.isInteger()) { - auto element = curr->ref->type.getHeapType().getArray().element; - optimizeStoredValue(curr->value, element.getByteSize()); - } - } - - void visitArrayLen(ArrayLen* curr) { skipNonNullCast(curr->ref); } - - void visitArrayCopy(ArrayCopy* curr) { - skipNonNullCast(curr->destRef); - skipNonNullCast(curr->srcRef); - } - - bool canBeCastTo(HeapType a, HeapType b) { - return HeapType::isSubType(a, b) || HeapType::isSubType(b, a); - } - - void visitRefCast(RefCast* curr) { - if (curr->type == Type::unreachable) { - return; - } - - Builder builder(*getModule()); - auto& passOptions = getPassOptions(); - - auto fallthrough = - Properties::getFallthrough(curr->ref, getPassOptions(), *getModule()); - - auto intendedType = curr->getIntendedType(); - - // If the value is a null, it will just flow through, and we do not need - // the cast. However, if that would change the type, then things are less - // simple: if the original type was non-nullable, replacing it with a null - // would change the type, which can happen in e.g. - // (ref.cast (ref.as_non_null (.. (ref.null) - if (fallthrough->is()) { - // Replace the expression with drops of the inputs, and a null. Note - // that we provide a null of the previous type, so that we do not alter - // the type received by our parent. - std::vector items; - items.push_back(builder.makeDrop(curr->ref)); - if (curr->rtt) { - items.push_back(builder.makeDrop(curr->rtt)); - } - items.push_back(builder.makeRefNull(intendedType)); - Expression* rep = builder.makeBlock(items); - if (curr->ref->type.isNonNullable()) { - // Avoid a type change by forcing to be non-nullable. In practice, - // this would have trapped before we get here, so this is just for - // validation. - rep = builder.makeRefAs(RefAsNonNull, rep); } - replaceCurrent(rep); - return; - // TODO: The optimal ordering of this and the other ref.as_non_null - // stuff later down in this functions is unclear and may be worth - // looking into. - } - - // For the cast to be able to succeed, the value being cast must be a - // subtype of the desired type, as RTT subtyping is a subset of static - // subtyping. For example, trying to cast an array to a struct would be - // incompatible. - if (!canBeCastTo(curr->ref->type.getHeapType(), intendedType)) { - // This cast cannot succeed. If the input is not a null, it will - // definitely trap. - if (fallthrough->type.isNonNullable()) { - // Make sure to emit a block with the same type as us; leave updating - // types for other passes. - std::vector items; - items.push_back(builder.makeDrop(curr->ref)); - if (curr->rtt) { - items.push_back(builder.makeDrop(curr->rtt)); - } - items.push_back(builder.makeUnreachable()); - replaceCurrent(builder.makeBlock(items, curr->type)); - return; - } - // Otherwise, we are not sure what it is, and need to wait for runtime - // to see if it is a null or not. (We've already handled the case where - // we can see the value is definitely a null at compile time, earlier.) - } - - if (passOptions.ignoreImplicitTraps || passOptions.trapsNeverHappen || - !curr->rtt) { - // Aside from the issue of type incompatibility as mentioned above, the - // cast can trap if the types *are* compatible but it happens to be the - // case at runtime that the value is not of the desired subtype. If we - // do not consider such traps possible, we can ignore that. (Note, - // though, that we cannot do this if we cannot replace the current type - // with the reference's type.) We can also do this if this is a static - // cast: in that case, all we need to know about are the types. - if (HeapType::isSubType(curr->ref->type.getHeapType(), intendedType)) { - if (curr->rtt) { - replaceCurrent(getResultOfFirst(curr->ref, - builder.makeDrop(curr->rtt), - getFunction(), - getModule(), - passOptions)); - } else { - replaceCurrent(curr->ref); - - // We must refinalize here, as we may be returning a more specific - // type, which can alter the parent. For example: - // - // (struct.get $parent 0 - // (ref.cast_static $parent - // (local.get $child) - // ) - // ) - // - // Try to cast a $child to its parent, $parent. That always works, - // so the cast can be removed. - // Then once the cast is removed, the outer struct.get - // will have a reference with a different type, making it a - // (struct.get $child ..) instead of $parent. - // But if $parent and $child have different types on field 0 (the - // child may have a more refined one) then the struct.get must be - // refinalized so the IR node has the expected type. - refinalize = true; - } - return; + // bitwise operations + // for and and or, we can potentially conditionalize + if (binary->op == AndInt32 || binary->op == OrInt32) { + if (auto* ret = conditionalizeExpensiveOnBitwise(binary)) { + return ret; + } } - } - - // Repeated identical ref.cast operations are unnecessary. First, find the - // immediate child cast, if there is one. - // TODO: Look even further through incompatible casts? - auto* ref = curr->ref; - while (!ref->is()) { - auto* last = ref; - // RefCast falls through the value, so instead of calling - // getFallthrough() to look through all fallthroughs, we must iterate - // manually. Keep going until we reach either the end of things - // falling-through, or a cast. - ref = Properties::getImmediateFallthrough(ref, passOptions, *getModule()); - if (ref == last) { - break; - } - } - if (auto* child = ref->dynCast()) { - if (curr->rtt && child->rtt) { - // Check if the casts are identical. - if (ExpressionAnalyzer::equal(curr->rtt, child->rtt) && - !EffectAnalyzer(passOptions, *getModule(), curr->rtt) - .hasSideEffects()) { - replaceCurrent(curr->ref); - return; + // for or, we can potentially combine + if (binary->op == OrInt32) { + if (auto* ret = combineOr(binary)) { + return ret; } - } else if (!curr->rtt && !child->rtt) { - // Repeated static casts can be removed, leaving just the most demanding - // of them. - auto childIntendedType = child->getIntendedType(); - if (HeapType::isSubType(intendedType, childIntendedType)) { - // Skip the child. - if (curr->ref == child) { - curr->ref = child->ref; - return; - } else { - // The child is not the direct child of the parent, but it is a - // fallthrough value, for example, - // - // (ref.cast parent - // (block - // .. other code .. - // (ref.cast child))) - // - // In this case it isn't obvious that we can remove the child, as - // doing so might require updating the types of the things in the - // middle - and in fact the sole purpose of the child may be to get - // a proper type for validation to work. Do nothing in this case, - // and hope that other opts will help here (for example, - // trapsNeverHappen will help if the code validates without the - // child). - } - } else if (!canBeCastTo(intendedType, childIntendedType)) { - // The types are not compatible, so if the input is not null, this - // will trap. - if (!curr->type.isNullable()) { - // Make sure to emit a block with the same type as us; leave - // updating types for other passes. - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->ref), builder.makeUnreachable()}, - curr->type)); - return; + } + // relation/comparisons allow for math optimizations + if (binary->isRelational()) { + if (auto* ret = optimizeRelational(binary)) { + return ret; + } + } + // finally, try more expensive operations on the binary in + // the case that they have no side effects + if (!effects(binary->left).hasSideEffects()) { + if (ExpressionAnalyzer::equal(binary->left, binary->right)) { + if (auto* ret = optimizeBinaryWithEqualEffectlessChildren(binary)) { + return ret; } } } - } - // ref.cast can be reordered with ref.as_non_null, - // - // (ref.cast (ref.as_non_null ..)) - // => - // (ref.as_non_null (ref.cast ..)) - // - // This is valid because both pass through the value if they do not trap, - // and so reordering does not change whether a trap happens (and reordering - // traps is allowed), and does not change the value flowing out at the end. - // It is better to have the ref.as_non_null on the outside since it allows - // outer instructions to potentially optimize it away (should we find - // optimizations that can fold away a ref.cast on an outer instruction, that - // might motivate changing this). - // - // Note that other ref.as* methods, like ref.as_func, are not obviously - // worth reordering with ref.cast. For example, the type of ref.as_data is - // (ref data), which is less specific than what ref.cast would have. - // TODO optimize ref.cast of ref.as_[func|data|i31] in other ways. - if (auto* as = curr->ref->dynCast()) { - if (as->op == RefAsNonNull) { - curr->ref = as->value; - curr->finalize(); - as->value = curr; - as->finalize(); - replaceCurrent(as); - return; + if (auto* ret = deduplicateBinary(binary)) { + return ret; + } + } else if (auto* unary = curr->dynCast()) { + if (unary->op == EqZInt32) { + if (auto* inner = unary->value->dynCast()) { + // Try to invert a relational operation using De Morgan's law + auto op = invertBinaryOp(inner->op); + if (op != InvalidBinary) { + inner->op = op; + return inner; + } + } + // eqz of a sign extension can be of zero-extension + if (auto* ext = Properties::getSignExtValue(unary->value)) { + // we are comparing a sign extend to a constant, which means we can + // use a cheaper zext + auto bits = Properties::getSignExtBits(unary->value); + unary->value = makeZeroExt(ext, bits); + return unary; + } + } else if (unary->op == AbsFloat32 || unary->op == AbsFloat64) { + // abs(-x) ==> abs(x) + if (auto* unaryInner = unary->value->dynCast()) { + if (unaryInner->op == + Abstract::getUnary(unaryInner->type, Abstract::Neg)) { + unary->value = unaryInner->value; + return unary; + } + } + // abs(x * x) ==> x * x + // abs(x / x) ==> x / x + if (auto* binary = unary->value->dynCast()) { + if ((binary->op == Abstract::getBinary(binary->type, Abstract::Mul) || + binary->op == + Abstract::getBinary(binary->type, Abstract::DivS)) && + ExpressionAnalyzer::equal(binary->left, binary->right)) { + return binary; + } + // abs(0 - x) ==> abs(x), + // only for fast math + if (fastMath && + binary->op == Abstract::getBinary(binary->type, Abstract::Sub)) { + if (auto* c = binary->left->dynCast()) { + if (c->value.isZero()) { + unary->value = binary->right; + return unary; + } + } + } + } } - } - } - - void visitRefTest(RefTest* curr) { - if (curr->type == Type::unreachable) { - return; - } - - Builder builder(*getModule()); - auto refType = curr->ref->type.getHeapType(); - auto intendedType = curr->getIntendedType(); - - // See above in RefCast. - if (!canBeCastTo(refType, intendedType)) { - // This test cannot succeed, and will definitely return 0. - std::vector items; - items.push_back(builder.makeDrop(curr->ref)); - if (curr->rtt) { - items.push_back(builder.makeDrop(curr->rtt)); + if (auto* ret = deduplicateUnary(unary)) { + return ret; } - items.push_back(builder.makeConst(int32_t(0))); - replaceCurrent(builder.makeBlock(items)); - return; - } - - if (!curr->rtt && curr->ref->type.isNonNullable() && - HeapType::isSubType(refType, intendedType)) { - // This static test will definitely succeed. - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->ref), builder.makeConst(int32_t(1))})); - return; - } - } - - void visitRefIs(RefIs* curr) { - if (curr->type == Type::unreachable) { - return; - } - - // Optimizating RefIs is not that obvious, since even if we know the result - // evaluates to 0 or 1 then the replacement may not actually save code size, - // since RefIsNull is a single byte (the others are 2), while adding a Const - // of 0 would be two bytes. Other factors are that we can remove the input - // and the added drop on it if it has no side effects, and that replacing - // with a constant may allow further optimizations later. For now, replace - // with a constant, but this warrants more investigation. TODO - - Builder builder(*getModule()); - - auto nonNull = !curr->value->type.isNullable(); - - if (curr->op == RefIsNull) { - if (nonNull) { - replaceCurrent(builder.makeSequence( - builder.makeDrop(curr->value), - builder.makeConst(Literal::makeZero(Type::i32)))); + } else if (auto* set = curr->dynCast()) { + // optimize out a set of a get + auto* get = set->value->dynCast(); + if (get && get->name == set->name) { + ExpressionManipulator::nop(curr); + } + } else if (auto* iff = curr->dynCast()) { + iff->condition = optimizeBoolean(iff->condition); + if (iff->ifFalse) { + if (auto* unary = iff->condition->dynCast()) { + if (unary->op == EqZInt32) { + // flip if-else arms to get rid of an eqz + iff->condition = unary->value; + std::swap(iff->ifTrue, iff->ifFalse); + } + } + if (iff->condition->type != Type::unreachable && + ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) { + // sides are identical, fold + // if we can replace the if with one arm, and no side effects in the + // condition, do that + auto needCondition = effects(iff->condition).hasSideEffects(); + auto isSubType = Type::isSubType(iff->ifTrue->type, iff->type); + if (isSubType && !needCondition) { + return iff->ifTrue; + } else { + Builder builder(*getModule()); + if (isSubType) { + return builder.makeSequence(builder.makeDrop(iff->condition), + iff->ifTrue); + } else { + // the types diff. as the condition is reachable, that means the + // if must be concrete while the arm is not + assert(iff->type.isConcrete() && + iff->ifTrue->type == Type::unreachable); + // emit a block with a forced type + auto* ret = builder.makeBlock(); + if (needCondition) { + ret->list.push_back(builder.makeDrop(iff->condition)); + } + ret->list.push_back(iff->ifTrue); + ret->finalize(iff->type); + return ret; + } + } + } } - return; - } - - // Check if the type is the kind we are checking for. - auto result = GCTypeUtils::evaluateKindCheck(curr); - - if (result != GCTypeUtils::Unknown) { - // We know the kind. Now we must also take into account nullability. - if (nonNull) { - // We know the entire result. - replaceCurrent( - builder.makeSequence(builder.makeDrop(curr->value), - builder.makeConst(Literal::makeFromInt32( - result == GCTypeUtils::Success, Type::i32)))); - } else { - // The value may be null. Leave only a check for that. - curr->op = RefIsNull; - if (result == GCTypeUtils::Success) { - // The input is of the right kind. If it is not null then the result - // is 1, and otherwise it is 0, so we need to flip the result of - // RefIsNull. - // Note that even after adding an eqz here we do not regress code size - // as RefIsNull is a single byte while the others are two. So we keep - // code size identical. However, in theory this may be more work, if - // a VM considers ref.is_X to be as fast as ref.is_null, and if eqz is - // not free, so this is worth more investigation. TODO - replaceCurrent(builder.makeUnary(EqZInt32, curr)); - } else { - // The input is of the wrong kind. In this case if it is null we - // return zero because of that, and if it is not then we return zero - // because of the kind, so the result is always the same. - assert(result == GCTypeUtils::Failure); - replaceCurrent(builder.makeSequence( - builder.makeDrop(curr->value), - builder.makeConst(Literal::makeZero(Type::i32)))); + } else if (auto* br = curr->dynCast()) { + if (br->condition) { + br->condition = optimizeBoolean(br->condition); + } + } else if (auto* load = curr->dynCast()) { + optimizeMemoryAccess(load->ptr, load->offset); + } else if (auto* store = curr->dynCast()) { + optimizeMemoryAccess(store->ptr, store->offset); + if (store->valueType.isInteger()) { + // truncates constant values during stores + // (i32|i64).store(8|16|32)(p, C) ==> + // (i32|i64).store(8|16|32)(p, C & mask) + if (auto* c = store->value->dynCast()) { + if (store->valueType == Type::i64 && store->bytes == 4) { + c->value = c->value.and_(Literal(uint64_t(0xffffffff))); + } else { + c->value = c->value.and_(Literal::makeFromInt32( + Bits::lowBitMask(store->bytes * 8), store->valueType)); + } } } + // stores of fewer bits truncates anyhow + if (auto* binary = store->value->dynCast()) { + if (binary->op == AndInt32) { + if (auto* right = binary->right->dynCast()) { + if (right->type == Type::i32) { + auto mask = right->value.geti32(); + if ((store->bytes == 1 && mask == 0xff) || + (store->bytes == 2 && mask == 0xffff)) { + store->value = binary->left; + } + } + } + } else if (auto* ext = Properties::getSignExtValue(binary)) { + // if sign extending the exact bit size we store, we can skip the + // extension if extending something bigger, then we just alter bits we + // don't save anyhow + if (Properties::getSignExtBits(binary) >= Index(store->bytes) * 8) { + store->value = ext; + } + } + } else if (auto* unary = store->value->dynCast()) { + if (unary->op == WrapInt64) { + // instead of wrapping to 32, just store some of the bits in the i64 + store->valueType = Type::i64; + store->value = unary->value; + } + } + } else if (auto* memCopy = curr->dynCast()) { + assert(features.hasBulkMemory()); + if (auto* ret = optimizeMemoryCopy(memCopy)) { + return ret; + } } - } - - void visitRefAs(RefAs* curr) { - if (curr->type == Type::unreachable) { - return; - } - - skipNonNullCast(curr->value); - - // Check if the type is the kind we are checking for. - auto result = GCTypeUtils::evaluateKindCheck(curr); - - if (result == GCTypeUtils::Success) { - // We know the kind is correct, so all that is left is a check for - // non-nullability, which we do lower down. - curr->op = RefAsNonNull; - } else if (result == GCTypeUtils::Failure) { - // This is the wrong kind, so it will trap. The binaryen optimizer does - // not differentiate traps, so we can perform a replacement here. We - // replace 2 bytes of ref.as_* with one byte of unreachable and one of a - // drop, which is no worse, and the value and the drop can be optimized - // out later if the value has no side effects. - Builder builder(*getModule()); - // Make sure to emit a block with the same type as us; leave updating - // types for other passes. - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->value), builder.makeUnreachable()}, - curr->type)); - return; - } - - if (curr->op == RefAsNonNull && !curr->value->type.isNullable()) { - replaceCurrent(curr->value); - } + return nullptr; } Index getMaxBitsForLocal(LocalGet* get) { @@ -1886,60 +955,6 @@ // Information about our locals std::vector localInfo; - // Check if two consecutive inputs to an instruction are equal. As they are - // consecutive, no code can execeute in between them, which simplies the - // problem here (and which is the case we care about in this pass, which does - // simple peephole optimizations - all we care about is a single instruction - // at a time, and its inputs). - // - // This also checks that the inputs are removable. - bool areConsecutiveInputsEqualAndRemovable(Expression* left, - Expression* right) { - // First, check for side effects. If there are any, then we can't even - // assume things like local.get's of the same index being identical. (It is - // also ok to have side effects here, if we can remove them, as we are also - // checking if we can remove the two inputs anyhow.) - auto& passOptions = getPassOptions(); - if (EffectAnalyzer(passOptions, *getModule(), left) - .hasUnremovableSideEffects() || - EffectAnalyzer(passOptions, *getModule(), right) - .hasUnremovableSideEffects()) { - return false; - } - - // Ignore extraneous things and compare them structurally. - left = Properties::getFallthrough(left, passOptions, *getModule()); - right = Properties::getFallthrough(right, passOptions, *getModule()); - if (!ExpressionAnalyzer::equal(left, right)) { - return false; - } - // To be equal, they must also be known to return the same result - // deterministically. - if (Properties::isGenerative(left, getModule()->features)) { - return false; - } - return true; - } - - // Check if two consecutive inputs to an instruction are equal and can be - // folded into the first of the two. This identifies reads from the same local - // variable when one of them is a "tee" operation. - // The inputs here must be consecutive, but it is also ok to have code with no - // side effects at all in the middle. For example, a Const in between is ok. - bool areConsecutiveInputsEqualAndFoldable(Expression* left, - Expression* right) { - if (auto* set = left->dynCast()) { - if (auto* get = right->dynCast()) { - if (set->isTee() && get->index == set->index) { - return true; - } - } - } - // stronger property than we need - we can not only fold - // them but remove them entirely. - return areConsecutiveInputsEqualAndRemovable(left, right); - } - // Canonicalizing the order of a symmetric binary helps us // write more concise pattern matching code elsewhere. void canonicalize(Binary* binary) { @@ -1958,58 +973,14 @@ }; // Prefer a const on the right. if (binary->left->is() && !binary->right->is()) { - swap(); + return swap(); } if (auto* c = binary->right->dynCast()) { - // x - C ==> x + (-C) + // x - C ==> x + (-C) // Prefer use addition if there is a constant on the right. if (binary->op == Abstract::getBinary(c->type, Abstract::Sub)) { c->value = c->value.neg(); binary->op = Abstract::getBinary(c->type, Abstract::Add); - return; - } - // Prefer to compare to 0 instead of to -1 or 1. - // (signed)x > -1 ==> x >= 0 - if (binary->op == Abstract::getBinary(c->type, Abstract::GtS) && - c->value.getInteger() == -1LL) { - binary->op = Abstract::getBinary(c->type, Abstract::GeS); - c->value = Literal::makeZero(c->type); - return; - } - // (signed)x <= -1 ==> x < 0 - if (binary->op == Abstract::getBinary(c->type, Abstract::LeS) && - c->value.getInteger() == -1LL) { - binary->op = Abstract::getBinary(c->type, Abstract::LtS); - c->value = Literal::makeZero(c->type); - return; - } - // (signed)x < 1 ==> x <= 0 - if (binary->op == Abstract::getBinary(c->type, Abstract::LtS) && - c->value.getInteger() == 1LL) { - binary->op = Abstract::getBinary(c->type, Abstract::LeS); - c->value = Literal::makeZero(c->type); - return; - } - // (signed)x >= 1 ==> x > 0 - if (binary->op == Abstract::getBinary(c->type, Abstract::GeS) && - c->value.getInteger() == 1LL) { - binary->op = Abstract::getBinary(c->type, Abstract::GtS); - c->value = Literal::makeZero(c->type); - return; - } - // (unsigned)x < 1 ==> x == 0 - if (binary->op == Abstract::getBinary(c->type, Abstract::LtU) && - c->value.getInteger() == 1LL) { - binary->op = Abstract::getBinary(c->type, Abstract::Eq); - c->value = Literal::makeZero(c->type); - return; - } - // (unsigned)x >= 1 ==> x != 0 - if (binary->op == Abstract::getBinary(c->type, Abstract::GeU) && - c->value.getInteger() == 1LL) { - binary->op = Abstract::getBinary(c->type, Abstract::Ne); - c->value = Literal::makeZero(c->type); - return; } return; } @@ -2128,9 +1099,7 @@ } else if (auto* tryy = boolean->dynCast()) { if (tryy->type == Type::i32) { tryy->body = optimizeBoolean(tryy->body); - for (Index i = 0; i < tryy->catchBodies.size(); i++) { - tryy->catchBodies[i] = optimizeBoolean(tryy->catchBodies[i]); - } + tryy->catchBody = optimizeBoolean(tryy->catchBody); } } // TODO: recurse into br values? @@ -2139,7 +1108,6 @@ Expression* optimizeSelect(Select* curr) { using namespace Match; - using namespace Abstract; Builder builder(*getModule()); curr->condition = optimizeBoolean(curr->condition); { @@ -2174,44 +1142,6 @@ s->ifTrue = ifFalse; s->ifFalse = ifTrue; s->condition = c; - return s; - } - } - { - // TODO: Remove this after landing SCCP pass. See: #4161 - - // i32(x) ? i32(x) : 0 ==> x - Expression *x, *y; - if (matches(curr, select(any(&x), i32(0), any(&y))) && - areConsecutiveInputsEqualAndFoldable(x, y)) { - return curr->ifTrue; - } - // i32(x) ? 0 : i32(x) ==> { x, 0 } - if (matches(curr, select(i32(0), any(&x), any(&y))) && - areConsecutiveInputsEqualAndFoldable(x, y)) { - return builder.makeSequence(builder.makeDrop(x), curr->ifTrue); - } - - // i64(x) == 0 ? 0 : i64(x) ==> x - // i64(x) != 0 ? i64(x) : 0 ==> x - if ((matches(curr, select(i64(0), any(&x), unary(EqZInt64, any(&y)))) || - matches( - curr, - select(any(&x), i64(0), binary(NeInt64, any(&y), i64(0))))) && - areConsecutiveInputsEqualAndFoldable(x, y)) { - return curr->condition->is() ? curr->ifFalse : curr->ifTrue; - } - - // i64(x) == 0 ? i64(x) : 0 ==> { x, 0 } - // i64(x) != 0 ? 0 : i64(x) ==> { x, 0 } - if ((matches(curr, select(any(&x), i64(0), unary(EqZInt64, any(&y)))) || - matches( - curr, - select(i64(0), any(&x), binary(NeInt64, any(&y), i64(0))))) && - areConsecutiveInputsEqualAndFoldable(x, y)) { - return builder.makeSequence( - builder.makeDrop(x), - curr->condition->is() ? curr->ifFalse : curr->ifTrue); } } { @@ -2230,48 +1160,6 @@ } } { - // Simplify x < 0 ? -1 : 1 or x >= 0 ? 1 : -1 to - // i32(x) >> 31 | 1 - // i64(x) >> 63 | 1 - Binary* bin; - if (matches( - curr, - select(ival(-1), ival(1), binary(&bin, LtS, any(), ival(0)))) || - matches( - curr, - select(ival(1), ival(-1), binary(&bin, GeS, any(), ival(0))))) { - auto c = bin->right->cast(); - auto type = curr->ifTrue->type; - if (type == c->type) { - bin->type = type; - bin->op = Abstract::getBinary(type, ShrS); - c->value = Literal::makeFromInt32(type.getByteSize() * 8 - 1, type); - curr->ifTrue->cast()->value = Literal::makeOne(type); - return builder.makeBinary( - Abstract::getBinary(type, Or), bin, curr->ifTrue); - } - } - } - if (curr->type == Type::i32 && - Bits::getMaxBits(curr->condition, this) <= 1 && - Bits::getMaxBits(curr->ifTrue, this) <= 1 && - Bits::getMaxBits(curr->ifFalse, this) <= 1) { - // The condition and both arms are i32 booleans, which allows us to do - // boolean optimizations. - Expression* x; - Expression* y; - - // x ? y : 0 ==> x & y - if (matches(curr, select(any(&y), ival(0), any(&x)))) { - return builder.makeBinary(AndInt32, y, x); - } - - // x ? 1 : y ==> x | y - if (matches(curr, select(ival(1), any(&y), any(&x)))) { - return builder.makeBinary(OrInt32, y, x); - } - } - { // Sides are identical, fold Expression *ifTrue, *ifFalse, *c; if (matches(curr, select(any(&ifTrue), any(&ifFalse), any(&c))) && @@ -2391,6 +1279,7 @@ if (!curr->type.isInteger()) { return; } + FeatureSet features = getModule()->features; auto type = curr->type; auto* left = curr->left->dynCast(); auto* right = curr->right->dynCast(); @@ -2412,7 +1301,7 @@ // shift has side effects if (((left && left->value.isZero()) || (right && Bits::getEffectiveShifts(right) == 0)) && - !EffectAnalyzer(passOptions, *getModule(), curr->right) + !EffectAnalyzer(passOptions, features, curr->right) .hasSideEffects()) { replaceCurrent(curr->left); return; @@ -2421,13 +1310,13 @@ // multiplying by zero is a zero, unless the other side has side // effects if (left && left->value.isZero() && - !EffectAnalyzer(passOptions, *getModule(), curr->right) + !EffectAnalyzer(passOptions, features, curr->right) .hasSideEffects()) { replaceCurrent(left); return; } if (right && right->value.isZero() && - !EffectAnalyzer(passOptions, *getModule(), curr->left) + !EffectAnalyzer(passOptions, features, curr->left) .hasSideEffects()) { replaceCurrent(right); return; @@ -2521,90 +1410,12 @@ } } - // We can combine `and` operations, e.g. - // (x == 0) & (y == 0) ==> (x | y) == 0 - Expression* combineAnd(Binary* curr) { - assert(curr->op == AndInt32); - - using namespace Abstract; - using namespace Match; - - { - // (i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0 - // (i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0 - Expression *x, *y; - if (matches(curr->left, unary(EqZ, any(&x))) && - matches(curr->right, unary(EqZ, any(&y))) && x->type == y->type) { - auto* inner = curr->left->cast(); - inner->value = - Builder(*getModule()).makeBinary(getBinary(x->type, Or), x, y); - return inner; - } - } - { - // Binary operations that inverse a bitwise AND can be - // reordered. If F(x) = binary(x, c), and F(x) preserves AND, - // that is, - // - // F(x) & F(y) == F(x | y) - // - // Then also - // - // binary(x, c) & binary(y, c) => binary(x | y, c) - Binary *bx, *by; - Expression *x, *y; - Const *cx, *cy; - if (matches(curr->left, binary(&bx, any(&x), ival(&cx))) && - matches(curr->right, binary(&by, any(&y), ival(&cy))) && - bx->op == by->op && x->type == y->type && cx->value == cy->value && - inversesAnd(bx)) { - by->op = getBinary(x->type, Or); - by->type = x->type; - by->left = x; - by->right = y; - bx->left = by; - return bx; - } - } - { - // Binary operations that preserve a bitwise AND can be - // reordered. If F(x) = binary(x, c), and F(x) preserves AND, - // that is, - // - // F(x) & F(y) == F(x & y) - // - // Then also - // - // binary(x, c) & binary(y, c) => binary(x & y, c) - Binary *bx, *by; - Expression *x, *y; - Const *cx, *cy; - if (matches(curr->left, binary(&bx, any(&x), ival(&cx))) && - matches(curr->right, binary(&by, any(&y), ival(&cy))) && - bx->op == by->op && x->type == y->type && cx->value == cy->value && - preserveAnd(bx)) { - by->op = getBinary(x->type, And); - by->type = x->type; - by->left = x; - by->right = y; - bx->left = by; - return bx; - } - } - return nullptr; - } - // We can combine `or` operations, e.g. - // (x > y) | (x == y) ==> x >= y - // (x != 0) | (y != 0) ==> (x | y) != 0 - Expression* combineOr(Binary* curr) { - assert(curr->op == OrInt32); - - using namespace Abstract; - using namespace Match; - - if (auto* left = curr->left->dynCast()) { - if (auto* right = curr->right->dynCast()) { + // (x > y) | (x == y) ==> x >= y + Expression* combineOr(Binary* binary) { + assert(binary->op == OrInt32); + if (auto* left = binary->left->dynCast()) { + if (auto* right = binary->right->dynCast()) { if (left->op != right->op && ExpressionAnalyzer::equal(left->left, right->left) && ExpressionAnalyzer::equal(left->right, right->right) && @@ -2625,162 +1436,9 @@ } } } - { - // Binary operations that inverses a bitwise OR to AND. - // If F(x) = binary(x, c), and F(x) inverses OR, - // that is, - // - // F(x) | F(y) == F(x & y) - // - // Then also - // - // binary(x, c) | binary(y, c) => binary(x & y, c) - Binary *bx, *by; - Expression *x, *y; - Const *cx, *cy; - if (matches(curr->left, binary(&bx, any(&x), ival(&cx))) && - matches(curr->right, binary(&by, any(&y), ival(&cy))) && - bx->op == by->op && x->type == y->type && cx->value == cy->value && - inversesOr(bx)) { - by->op = getBinary(x->type, And); - by->type = x->type; - by->left = x; - by->right = y; - bx->left = by; - return bx; - } - } - { - // Binary operations that preserve a bitwise OR can be - // reordered. If F(x) = binary(x, c), and F(x) preserves OR, - // that is, - // - // F(x) | F(y) == F(x | y) - // - // Then also - // - // binary(x, c) | binary(y, c) => binary(x | y, c) - Binary *bx, *by; - Expression *x, *y; - Const *cx, *cy; - if (matches(curr->left, binary(&bx, any(&x), ival(&cx))) && - matches(curr->right, binary(&by, any(&y), ival(&cy))) && - bx->op == by->op && x->type == y->type && cx->value == cy->value && - preserveOr(bx)) { - by->op = getBinary(x->type, Or); - by->type = x->type; - by->left = x; - by->right = y; - bx->left = by; - return bx; - } - } return nullptr; } - // Check whether an operation preserves the Or operation through it, that is, - // - // F(x | y) = F(x) | F(y) - // - // Mathematically that means F is homomorphic with respect to the | operation. - // - // F(x) is seen as taking a single parameter of its first child. That is, the - // first child is |x|, and the rest is constant. For example, if we are given - // a binary with operation != and the right child is a constant 0, then - // F(x) = (x != 0). - bool preserveOr(Binary* curr) { - using namespace Abstract; - using namespace Match; - - // (x != 0) | (y != 0) ==> (x | y) != 0 - // This effectively checks if any bits are set in x or y. - if (matches(curr, binary(Ne, any(), ival(0)))) { - return true; - } - // (x < 0) | (y < 0) ==> (x | y) < 0 - // This effectively checks if x or y have the sign bit set. - if (matches(curr, binary(LtS, any(), ival(0)))) { - return true; - } - return false; - } - - // Check whether an operation inverses the Or operation to And, that is, - // - // F(x | y) = F(x) & F(y) - // - // Mathematically that means F is homomorphic with respect to the | operation. - // - // F(x) is seen as taking a single parameter of its first child. That is, the - // first child is |x|, and the rest is constant. For example, if we are given - // a binary with operation != and the right child is a constant 0, then - // F(x) = (x != 0). - bool inversesOr(Binary* curr) { - using namespace Abstract; - using namespace Match; - - // (x >= 0) | (y >= 0) ==> (x & y) >= 0 - if (matches(curr, binary(GeS, any(), ival(0)))) { - return true; - } - - // (x !=-1) | (y !=-1) ==> (x & y) !=-1 - if (matches(curr, binary(Ne, any(), ival(-1)))) { - return true; - } - - return false; - } - - // Check whether an operation preserves the And operation through it, that is, - // - // F(x & y) = F(x) & F(y) - // - // Mathematically that means F is homomorphic with respect to the & operation. - // - // F(x) is seen as taking a single parameter of its first child. That is, the - // first child is |x|, and the rest is constant. For example, if we are given - // a binary with operation != and the right child is a constant 0, then - // F(x) = (x != 0). - bool preserveAnd(Binary* curr) { - using namespace Abstract; - using namespace Match; - - // (x < 0) & (y < 0) ==> (x & y) < 0 - if (matches(curr, binary(LtS, any(), ival(0)))) { - return true; - } - - // (x == -1) & (y == -1) ==> (x & y) == -1 - if (matches(curr, binary(Eq, any(), ival(-1)))) { - return true; - } - - return false; - } - - // Check whether an operation inverses the And operation to Or, that is, - // - // F(x & y) = F(x) | F(y) - // - // Mathematically that means F is homomorphic with respect to the & operation. - // - // F(x) is seen as taking a single parameter of its first child. That is, the - // first child is |x|, and the rest is constant. For example, if we are given - // a binary with operation != and the right child is a constant 0, then - // F(x) = (x != 0). - bool inversesAnd(Binary* curr) { - using namespace Abstract; - using namespace Match; - - // (x >= 0) & (y >= 0) ==> (x | y) >= 0 - if (matches(curr, binary(GeS, any(), ival(0)))) { - return true; - } - - return false; - } - // fold constant factors into the offset void optimizeMemoryAccess(Expression*& ptr, Address& offset) { // ptr may be a const, but it isn't worth folding that in (we still have a @@ -2930,24 +1588,6 @@ matches(curr, binary(And, pure(&left), ival(0)))) { return right; } - // -x * C ==> x * -C, if shrinkLevel != 0 or C != C_pot - // -x * C ==> -(x * C), otherwise - // where x, C are integers - Binary* inner; - if (matches( - curr, - binary(Mul, binary(&inner, Sub, ival(0), any(&left)), ival()))) { - if (getPassOptions().shrinkLevel != 0 || - !Bits::isPowerOf2(right->value.getInteger())) { - right->value = right->value.neg(); - curr->left = left; - return curr; - } else { - curr->left = left; - Const* zero = inner->left->cast(); - return builder.makeBinary(inner->op, zero, curr); - } - } // x == 0 ==> eqz x if (matches(curr, binary(Eq, any(&left), ival(0)))) { return builder.makeUnary(Abstract::getUnary(type, EqZ), left); @@ -2997,20 +1637,6 @@ Bits::getMaxBits(left, this) == 1) { return builder.makeUnary(Abstract::getUnary(type, EqZ), left); } - // bool(x) ^ 1 ==> !bool(x) - if (matches(curr, binary(Xor, any(&left), ival(1))) && - Bits::getMaxBits(left, this) == 1) { - auto* result = builder.makeUnary(Abstract::getUnary(type, EqZ), left); - if (left->type == Type::i64) { - // Xor's result is also an i64 in this case, but EqZ returns i32, so we - // must expand it so that we keep returning the same value as before. - // This means we replace a xor and a const with a xor and an extend, - // which is still smaller (the const is 2 bytes, the extend just 1), and - // also the extend may be removed by further work. - result = builder.makeUnary(ExtendUInt32, result); - } - return result; - } // bool(x) | 1 ==> 1 if (matches(curr, binary(Or, pure(&left), ival(1))) && Bits::getMaxBits(left, this) == 1) { @@ -3410,7 +2036,8 @@ if (type.isInteger()) { if (auto* inner = outer->right->dynCast()) { if (outer->op == inner->op) { - if (!EffectAnalyzer(getPassOptions(), *getModule(), outer->left) + if (!EffectAnalyzer( + getPassOptions(), getModule()->features, outer->left) .hasSideEffects()) { if (ExpressionAnalyzer::equal(inner->left, outer->left)) { // x - (x - y) ==> y @@ -3452,7 +2079,8 @@ } if (auto* inner = outer->left->dynCast()) { if (outer->op == inner->op) { - if (!EffectAnalyzer(getPassOptions(), *getModule(), outer->right) + if (!EffectAnalyzer( + getPassOptions(), getModule()->features, outer->right) .hasSideEffects()) { if (ExpressionAnalyzer::equal(inner->right, outer->right)) { // (x ^ y) ^ y ==> x @@ -3513,9 +2141,9 @@ } Expression* optimizeMemoryCopy(MemoryCopy* memCopy) { - auto& options = getPassOptions(); + PassOptions options = getPassOptions(); - if (options.ignoreImplicitTraps || options.trapsNeverHappen) { + if (options.ignoreImplicitTraps) { if (ExpressionAnalyzer::equal(memCopy->dest, memCopy->source)) { // memory.copy(x, x, sz) ==> {drop(x), drop(x), drop(sz)} Builder builder(*getModule()); @@ -3527,12 +2155,12 @@ // memory.copy(dst, src, C) ==> store(dst, load(src)) if (auto* csize = memCopy->size->dynCast()) { - auto bytes = csize->value.getInteger(); + auto bytes = csize->value.geti32(); Builder builder(*getModule()); switch (bytes) { case 0: { - if (options.ignoreImplicitTraps || options.trapsNeverHappen) { + if (options.ignoreImplicitTraps) { // memory.copy(dst, src, 0) ==> {drop(dst), drop(src)} return builder.makeBlock({builder.makeDrop(memCopy->dest), builder.makeDrop(memCopy->source)}); @@ -3574,133 +2202,11 @@ Type::v128); } } - break; - } - default: { - } - } - } - return nullptr; - } - - Expression* optimizeMemoryFill(MemoryFill* memFill) { - if (memFill->type == Type::unreachable) { - return nullptr; - } - - if (!memFill->size->is()) { - return nullptr; - } - - auto& options = getPassOptions(); - Builder builder(*getModule()); - - auto* csize = memFill->size->cast(); - auto bytes = csize->value.getInteger(); - - if (bytes == 0LL && - (options.ignoreImplicitTraps || options.trapsNeverHappen)) { - // memory.fill(d, v, 0) ==> { drop(d), drop(v) } - return builder.makeBlock( - {builder.makeDrop(memFill->dest), builder.makeDrop(memFill->value)}); - } - - const uint32_t offset = 0, align = 1; - - if (auto* cvalue = memFill->value->dynCast()) { - uint32_t value = cvalue->value.geti32() & 0xFF; - // memory.fill(d, C1, C2) ==> - // store(d, (C1 & 0xFF) * (-1U / max(bytes))) - switch (bytes) { - case 1: { - return builder.makeStore(1, // bytes - offset, - align, - memFill->dest, - builder.makeConst(value), - Type::i32); - } - case 2: { - return builder.makeStore(2, - offset, - align, - memFill->dest, - builder.makeConst(value * 0x0101U), - Type::i32); - } - case 4: { - // transform only when "value" or shrinkLevel equal to zero due to - // it could increase size by several bytes - if (value == 0 || options.shrinkLevel == 0) { - return builder.makeStore( - 4, - offset, - align, - memFill->dest, - builder.makeConst(value * 0x01010101U), - Type::i32); - } - break; - } - case 8: { - // transform only when "value" or shrinkLevel equal to zero due to - // it could increase size by several bytes - if (value == 0 || options.shrinkLevel == 0) { - return builder.makeStore( - 8, - offset, - align, - memFill->dest, - builder.makeConst(value * 0x0101010101010101ULL), - Type::i64); - } - break; - } - case 16: { - if (options.shrinkLevel == 0) { - if (getModule()->features.hasSIMD()) { - uint8_t values[16]; - std::fill_n(values, 16, (uint8_t)value); - return builder.makeStore(16, - offset, - align, - memFill->dest, - builder.makeConst(values), - Type::v128); - } else { - // { i64.store(d, C', 0), i64.store(d, C', 8) } - auto destType = memFill->dest->type; - Index tempLocal = builder.addVar(getFunction(), destType); - return builder.makeBlock({ - builder.makeStore( - 8, - offset, - align, - builder.makeLocalTee(tempLocal, memFill->dest, destType), - builder.makeConst(value * 0x0101010101010101ULL), - Type::i64), - builder.makeStore( - 8, - offset + 8, - align, - builder.makeLocalGet(tempLocal, destType), - builder.makeConst(value * 0x0101010101010101ULL), - Type::i64), - }); - } - } - break; } default: { } } } - // memory.fill(d, v, 1) ==> store8(d, v) - if (bytes == 1LL) { - return builder.makeStore( - 1, offset, align, memFill->dest, memFill->value, Type::i32); - } - return nullptr; } @@ -3944,201 +2450,6 @@ return false; } } - - // Optimize an if-else or a select, something with a condition and two - // arms with outputs. - template void optimizeTernary(T* curr) { - using namespace Abstract; - using namespace Match; - Builder builder(*getModule()); - - // If one arm is an operation and the other is an appropriate constant, we - // can move the operation outside (where it may be further optimized), e.g. - // - // (select - // (i32.eqz (X)) - // (i32.const 0|1) - // (Y) - // ) - // => - // (i32.eqz - // (select - // (X) - // (i32.const 1|0) - // (Y) - // ) - // ) - // - // Ignore unreachable code here; leave that for DCE. - if (curr->type != Type::unreachable && - curr->ifTrue->type != Type::unreachable && - curr->ifFalse->type != Type::unreachable) { - Unary* un; - Const* c; - auto check = [&](Expression* a, Expression* b) { - return matches(b, bval(&c)) && matches(a, unary(&un, EqZ, any())); - }; - if (check(curr->ifTrue, curr->ifFalse) || - check(curr->ifFalse, curr->ifTrue)) { - // The new type of curr will be that of the value of the unary, as after - // we move the unary out, its value is curr's direct child. - auto newType = un->value->type; - auto updateArm = [&](Expression* arm) -> Expression* { - if (arm == un) { - // This is the arm that had the eqz, which we need to remove. - return un->value; - } else { - // This is the arm with the constant, which we need to flip. - // Note that we also need to set the type to match the other arm. - c->value = - Literal::makeFromInt32(1 - c->value.getInteger(), newType); - c->type = newType; - return c; - } - }; - curr->ifTrue = updateArm(curr->ifTrue); - curr->ifFalse = updateArm(curr->ifFalse); - un->value = curr; - curr->finalize(newType); - return replaceCurrent(un); - } - } - - { - // Identical code on both arms can be folded out, e.g. - // - // (select - // (i32.eqz (X)) - // (i32.eqz (Y)) - // (Z) - // ) - // => - // (i32.eqz - // (select - // (X) - // (Y) - // (Z) - // ) - // ) - // - // Continue doing this while we can, noting the chain of moved expressions - // as we go, then do a single replaceCurrent() at the end. - SmallVector chain; - while (1) { - // Ignore control flow structures (which are handled in MergeBlocks). - if (!Properties::isControlFlowStructure(curr->ifTrue) && - ExpressionAnalyzer::shallowEqual(curr->ifTrue, curr->ifFalse)) { - // TODO: consider the case with more than one child. - ChildIterator ifTrueChildren(curr->ifTrue); - if (ifTrueChildren.children.size() == 1) { - // ifTrue and ifFalse's children will become the direct children of - // curr, and so they must be compatible to allow for a proper new - // type after the transformation. - // - // At minimum an LUB is required, as shown here: - // - // (if - // (condition) - // (drop (i32.const 1)) - // (drop (f64.const 2.0)) - // ) - // - // However, that may not be enough, as with nominal types we can - // have things like this: - // - // (if - // (condition) - // (struct.get $A 1 (..)) - // (struct.get $B 1 (..)) - // ) - // - // It is possible that the LUB of $A and $B does not contain field - // "1". With structural types this specific problem is not possible, - // and it appears to be the case that with the GC MVP there is no - // instruction that poses a problem, but in principle it can happen - // there as well, if we add an instruction that returns the number - // of fields in a type, for example. For that reason, and to avoid - // a difference between structural and nominal typing here, disallow - // subtyping in both. (Note: In that example, the problem only - // happens because the type is not part of the struct.get - we infer - // it from the reference. That is why after hoisting the struct.get - // out, and computing a new type for the if that is now the child of - // the single struct.get, we get a struct.get of a supertype. So in - // principle we could fix this by modifying the IR as well, but the - // problem is more general, so avoid that.) - ChildIterator ifFalseChildren(curr->ifFalse); - auto* ifTrueChild = *ifTrueChildren.begin(); - auto* ifFalseChild = *ifFalseChildren.begin(); - bool validTypes = ifTrueChild->type == ifFalseChild->type; - - // In addition, after we move code outside of curr then we need to - // not change unreachability - if we did, we'd need to propagate - // that further, and we leave such work to DCE and Vacuum anyhow. - // This can happen in something like this for example, where the - // outer type changes from i32 to unreachable if we move the - // returns outside: - // - // (if (result i32) - // (local.get $x) - // (return - // (local.get $y) - // ) - // (return - // (local.get $z) - // ) - // ) - assert(curr->ifTrue->type == curr->ifFalse->type); - auto newOuterType = curr->ifTrue->type; - if ((newOuterType == Type::unreachable) != - (curr->type == Type::unreachable)) { - validTypes = false; - } - - // If the expression we are about to move outside has side effects, - // then we cannot do so in general with a select: we'd be reducing - // the amount of the effects as well as moving them. For an if, - // the side effects execute once, so there is no problem. - // TODO: handle certain side effects when possible in select - bool validEffects = std::is_same::value || - !ShallowEffectAnalyzer( - getPassOptions(), *getModule(), curr->ifTrue) - .hasSideEffects(); - - // In addition, check for specific limitations of select. - bool validChildren = - !std::is_same::value || - Properties::canEmitSelectWithArms(ifTrueChild, ifFalseChild); - - if (validTypes && validEffects && validChildren) { - // Replace ifTrue with its child. - curr->ifTrue = ifTrueChild; - // Relace ifFalse with its child, and reuse that node outside. - auto* reuse = curr->ifFalse; - curr->ifFalse = ifFalseChild; - // curr's type may have changed, if the instructions we moved out - // had different input types than output types. - curr->finalize(); - // Point to curr from the code that is now outside of it. - *ChildIterator(reuse).begin() = curr; - if (!chain.empty()) { - // We've already moved things out, so chain them to there. That - // is, the end of the chain should now point to reuse (which - // in turn already points to curr). - *ChildIterator(chain.back()).begin() = reuse; - } - chain.push_back(reuse); - continue; - } - } - } - break; - } - if (!chain.empty()) { - // The beginning of the chain is the new top parent. - return replaceCurrent(chain[0]); - } - } - } }; Pass* createOptimizeInstructionsPass() { return new OptimizeInstructions; } diff -Nru binaryen-108/src/passes/opt-utils.h binaryen-99/src/passes/opt-utils.h --- binaryen-108/src/passes/opt-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/opt-utils.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,8 +20,6 @@ #include #include -#include -#include #include #include @@ -31,7 +29,7 @@ // Run useful optimizations after inlining new code into a set // of functions. -inline void optimizeAfterInlining(const std::unordered_set& funcs, +inline void optimizeAfterInlining(std::unordered_set& funcs, Module* module, PassRunner* parentRunner) { // save the full list of functions on the side @@ -85,11 +83,14 @@ name = iter->second; } }; - // replace direct calls in code both functions and module elements - FunctionRefReplacer replacer(maybeReplace); - replacer.run(runner, &module); - replacer.runOnModuleCode(runner, &module); - + // replace direct calls + FunctionRefReplacer(maybeReplace).run(runner, &module); + // replace in table + for (auto& segment : module.table.segments) { + for (auto& name : segment.data) { + maybeReplace(name); + } + } // replace in start if (module.start.is()) { maybeReplace(module.start); diff -Nru binaryen-108/src/passes/param-utils.cpp binaryen-99/src/passes/param-utils.cpp --- binaryen-108/src/passes/param-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/param-utils.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,232 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ir/function-utils.h" -#include "ir/local-graph.h" -#include "ir/possible-constant.h" -#include "ir/type-updating.h" -#include "support/sorted_vector.h" -#include "wasm.h" - -namespace wasm::ParamUtils { - -std::unordered_set getUsedParams(Function* func) { - LocalGraph localGraph(func); - - std::unordered_set usedParams; - - for (auto& [get, sets] : localGraph.getSetses) { - if (!func->isParam(get->index)) { - continue; - } - - for (auto* set : sets) { - // A nullptr value indicates there is no LocalSet* that sets the value, - // so it must be the parameter value. - if (!set) { - usedParams.insert(get->index); - } - } - } - - return usedParams; -} - -bool removeParameter(const std::vector& funcs, - Index index, - const std::vector& calls, - const std::vector& callRefs, - Module* module, - PassRunner* runner) { - assert(funcs.size() > 0); - auto* first = funcs[0]; -#ifndef NDEBUG - for (auto* func : funcs) { - assert(func->type == first->type); - } -#endif - - // Check if none of the calls has a param with side effects that we cannot - // remove (as if we can remove them, we will simply do that when we remove the - // parameter). Note: flattening the IR beforehand can help here. - auto hasBadEffects = [&](ExpressionList& operands) { - return EffectAnalyzer(runner->options, *module, operands[index]) - .hasUnremovableSideEffects(); - }; - bool callParamsAreValid = - std::none_of(calls.begin(), calls.end(), [&](Call* call) { - return hasBadEffects(call->operands); - }); - if (!callParamsAreValid) { - return false; - } - bool callRefParamsAreValid = - std::none_of(callRefs.begin(), callRefs.end(), [&](CallRef* call) { - return hasBadEffects(call->operands); - }); - if (!callRefParamsAreValid) { - return false; - } - - // The type must be valid for us to handle as a local (since we - // replace the parameter with a local). - // TODO: if there are no references at all, we can avoid creating a - // local - bool typeIsValid = TypeUpdating::canHandleAsLocal(first->getLocalType(index)); - if (!typeIsValid) { - return false; - } - - // We can do it! - - // Remove the parameter from the function. We must add a new local - // for uses of the parameter, but cannot make it use the same index - // (in general). - auto paramsType = first->getParams(); - std::vector params(paramsType.begin(), paramsType.end()); - auto type = params[index]; - params.erase(params.begin() + index); - // TODO: parallelize some of these loops? - for (auto* func : funcs) { - func->setParams(Type(params)); - - // It's cumbersome to adjust local names - TODO don't clear them? - Builder::clearLocalNames(func); - } - std::vector newIndexes; - for (auto* func : funcs) { - newIndexes.push_back(Builder::addVar(func, type)); - } - // Update local operations. - struct LocalUpdater : public PostWalker { - Index removedIndex; - Index newIndex; - LocalUpdater(Function* func, Index removedIndex, Index newIndex) - : removedIndex(removedIndex), newIndex(newIndex) { - walk(func->body); - } - void visitLocalGet(LocalGet* curr) { updateIndex(curr->index); } - void visitLocalSet(LocalSet* curr) { updateIndex(curr->index); } - void updateIndex(Index& index) { - if (index == removedIndex) { - index = newIndex; - } else if (index > removedIndex) { - index--; - } - } - }; - for (Index i = 0; i < funcs.size(); i++) { - auto* func = funcs[i]; - if (!func->imported()) { - LocalUpdater(funcs[i], index, newIndexes[i]); - TypeUpdating::handleNonDefaultableLocals(func, *module); - } - } - - // Remove the arguments from the calls. - for (auto* call : calls) { - call->operands.erase(call->operands.begin() + index); - } - for (auto* call : callRefs) { - call->operands.erase(call->operands.begin() + index); - } - - return true; -} - -SortedVector removeParameters(const std::vector& funcs, - SortedVector indexes, - const std::vector& calls, - const std::vector& callRefs, - Module* module, - PassRunner* runner) { - if (indexes.empty()) { - return {}; - } - - assert(funcs.size() > 0); - auto* first = funcs[0]; -#ifndef NDEBUG - for (auto* func : funcs) { - assert(func->type == first->type); - } -#endif - - // Iterate downwards, as we may remove more than one, and going forwards would - // alter the indexes after us. - Index i = first->getNumParams() - 1; - SortedVector removed; - while (1) { - if (indexes.has(i)) { - if (removeParameter(funcs, i, calls, callRefs, module, runner)) { - // Success! - removed.insert(i); - } - } - if (i == 0) { - break; - } - i--; - } - return removed; -} - -SortedVector applyConstantValues(const std::vector& funcs, - const std::vector& calls, - const std::vector& callRefs, - Module* module) { - assert(funcs.size() > 0); - auto* first = funcs[0]; -#ifndef NDEBUG - for (auto* func : funcs) { - assert(func->type == first->type); - } -#endif - - SortedVector optimized; - auto numParams = first->getNumParams(); - for (Index i = 0; i < numParams; i++) { - PossibleConstantValues value; - for (auto* call : calls) { - value.note(call->operands[i], *module); - if (!value.isConstant()) { - break; - } - } - for (auto* call : callRefs) { - value.note(call->operands[i], *module); - if (!value.isConstant()) { - break; - } - } - if (!value.isConstant()) { - continue; - } - - // Optimize: write the constant value in the function bodies, making them - // ignore the parameter's value. - Builder builder(*module); - for (auto* func : funcs) { - func->body = builder.makeSequence( - builder.makeLocalSet(i, value.makeExpression(*module)), func->body); - } - optimized.insert(i); - } - - return optimized; -} - -} // namespace wasm::ParamUtils diff -Nru binaryen-108/src/passes/param-utils.h binaryen-99/src/passes/param-utils.h --- binaryen-108/src/passes/param-utils.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/param-utils.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_ir_function_h -#define wasm_ir_function_h - -#include "pass.h" -#include "support/sorted_vector.h" -#include "wasm.h" - -// Helper code for passes that manipulate function parameters, specifically -// checking if they are used and removing them if so. This is closely tied to -// the internals of those passes, and so is not in /ir/ (it would be inside the -// pass .cpp file, but there is more than one). - -namespace wasm::ParamUtils { - -// Find which parameters are actually used in the function, that is, that the -// values arriving in the parameter are read. This ignores values set in the -// function, like this: -// -// function foo(x) { -// x = 10; -// bar(x); // read of a param index, but not the param value passed in. -// } -// -// This is an actual use: -// -// function foo(x) { -// bar(x); // read of a param value -// } -std::unordered_set getUsedParams(Function* func); - -// Try to remove a parameter from a set of functions and replace it with a local -// instead. This may not succeed if the parameter type cannot be used in a -// local, or if we hit another limitation, in which case this returns false and -// does nothing. If we succeed then the parameter is removed both from the -// functions and from the calls to it, which are passed in (the caller must -// ensure to pass in all relevant calls and call_refs). -// -// This does not check if removing the parameter would change the semantics -// (say, if the parameter's value is used), which the caller is assumed to do. -// -// This assumes that the set of functions all have the same signature. The main -// use cases are either to send a single function, or to send a set of functions -// that all have the same heap type (and so if they all do not use some -// parameter, it can be removed from them all). -// -// This does *not* update the types in call_refs. It is assumed that the caller -// will be updating types, which is simpler as there may be other locations that -// need adjusting and it is easier to do it all in one place. Also, the caller -// can update all the types at once throughout the program after making -// multiple calls to removeParameter(). -bool removeParameter(const std::vector& funcs, - Index index, - const std::vector& calls, - const std::vector& callRefs, - Module* module, - PassRunner* runner); - -// The same as removeParameter, but gets a sorted list of indexes. It tries to -// remove them all, and returns which we removed. -SortedVector removeParameters(const std::vector& funcs, - SortedVector indexes, - const std::vector& calls, - const std::vector& callRefs, - Module* module, - PassRunner* runner); - -// Given a set of functions and the calls and call_refs that reach them, find -// which parameters are passed the same constant value in all the calls. For -// each such parameter, apply it inside the function, that is, do a local.set of -// that value in the function. The parameter's incoming value is then ignored, -// which allows other optimizations to remove it. -// -// Returns the indexes that were optimized. -SortedVector applyConstantValues(const std::vector& funcs, - const std::vector& calls, - const std::vector& callRefs, - Module* module); - -} // namespace wasm::ParamUtils - -#endif // wasm_ir_function_h diff -Nru binaryen-108/src/passes/pass.cpp binaryen-99/src/passes/pass.cpp --- binaryen-108/src/passes/pass.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/pass.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -47,16 +47,9 @@ passInfos[name] = PassInfo(description, create); } -void PassRegistry::registerTestPass(const char* name, - const char* description, - Creator create) { - assert(passInfos.find(name) == passInfos.end()); - passInfos[name] = PassInfo(description, create, true); -} - std::unique_ptr PassRegistry::createPass(std::string name) { if (passInfos.find(name) == passInfos.end()) { - Fatal() << "Could not find pass: " << name << "\n"; + return nullptr; } std::unique_ptr ret; ret.reset(passInfos[name].create()); @@ -66,8 +59,8 @@ std::vector PassRegistry::getRegisteredNames() { std::vector ret; - for (auto& [name, _] : passInfos) { - ret.push_back(name); + for (auto pair : passInfos) { + ret.push_back(pair.first); } return ret; } @@ -77,11 +70,6 @@ return passInfos[name].description; } -bool PassRegistry::isPassHidden(std::string name) { - assert(passInfos.find(name) != passInfos.end()); - return passInfos[name].hidden; -} - // PassRunner void PassRegistry::registerPasses() { @@ -114,9 +102,6 @@ registerPass("const-hoisting", "hoist repeated constants to a local", createConstHoistingPass); - registerPass("cfp", - "propagate constant struct field values", - createConstantFieldPropagationPass); registerPass( "dce", "removes unreachable code", createDeadCodeEliminationPass); registerPass("dealign", @@ -144,9 +129,6 @@ registerPass("extract-function", "leaves just one function (useful for debugging)", createExtractFunctionPass); - registerPass("extract-function-index", - "leaves just one function selected by index", - createExtractFunctionIndexPass); registerPass( "flatten", "flattens out code, removing nesting", createFlattenPass); registerPass("fpcast-emu", @@ -158,24 +140,14 @@ registerPass("generate-dyncalls", "generate dynCall fuctions used by emscripten ABI", createGenerateDynCallsPass); - registerPass( - "generate-i64-dyncalls", - "generate dynCall functions used by emscripten ABI, but only for " - "functions with i64 in their signature (which cannot be invoked " - "via the wasm table without JavaScript BigInt support).", - createGenerateI64DynCallsPass); + registerPass("generate-i64-dyncalls", + "generate dynCall functions used by emscripten ABI, but only for " + "functions with i64 in their signature (which cannot be invoked " + "via the wasm table without JavaScript BigInt support).", + createGenerateI64DynCallsPass); registerPass( "generate-stack-ir", "generate Stack IR", createGenerateStackIRPass); registerPass( - "global-refining", "refine the types of globals", createGlobalRefiningPass); - registerPass( - "gto", "globally optimize GC types", createGlobalTypeOptimizationPass); - registerPass("type-refining", - "apply more specific subtypes to type fields where possible", - createTypeRefiningPass); - registerPass( - "heap2local", "replace GC allocations with locals", createHeap2LocalPass); - registerPass( "inline-main", "inline __original_main into main", createInlineMainPass); registerPass("inlining", "inline functions (you probably want inlining-optimizing)", @@ -183,9 +155,6 @@ registerPass("inlining-optimizing", "inline functions and optimizes where we inlined", createInliningOptimizingPass); - registerPass("intrinsic-lowering", - "lower away binaryen intrinsics", - createIntrinsicLoweringPass); registerPass("legalize-js-interface", "legalizes i64 types on the import/export boundary", createLegalizeJSInterfacePass); @@ -196,9 +165,6 @@ registerPass("local-cse", "common subexpression elimination inside basic blocks", createLocalCSEPass); - registerPass("local-subtyping", - "apply more specific subtypes to locals where possible", - createLocalSubtypingPass); registerPass("log-execution", "instrument the build with logging of where execution goes", createLogExecutionPass); @@ -227,9 +193,6 @@ createMemoryPackingPass); registerPass( "merge-blocks", "merges blocks to their parents", createMergeBlocksPass); - registerPass("merge-similar-functions", - "merges similar functions when benefical", - createMergeSimilarFunctionsPass); registerPass( "merge-locals", "merges locals when beneficial", createMergeLocalsPass); registerPass("metrics", "reports metrics", createMetricsPass); @@ -253,10 +216,10 @@ "apply the assumption that asyncify never unwinds", createModAsyncifyNeverUnwindPass); registerPass("nm", "name list", createNameListPass); - registerPass("name-types", "(re)name all heap types", createNameTypesPass); - registerPass("once-reduction", - "reduces calls to code that only runs once", - createOnceReductionPass); + registerPass("no-exit-runtime", + "removes calls to atexit(), which is valid if the C runtime " + "will never be exited", + createNoExitRuntimePass); registerPass("optimize-added-constants", "optimizes added constants into load/store offsets", createOptimizeAddedConstantsPass); @@ -272,14 +235,15 @@ registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass); - registerPass( - "poppify", "Tranform Binaryen IR into Poppy IR", createPoppifyPass); + registerPass("post-assemblyscript", + "eliminates redundant ARC patterns in AssemblyScript output", + createPostAssemblyScriptPass); + registerPass("post-assemblyscript-finalize", + "eliminates collapsed ARC patterns after other optimizations", + createPostAssemblyScriptFinalizePass); registerPass("post-emscripten", "miscellaneous optimizations for Emscripten-generated code", createPostEmscriptenPass); - registerPass("optimize-for-js", - "early optimize of the instruction combinations for js", - createOptimizeForJSPass); registerPass("precompute", "computes compile-time evaluatable expressions", createPrecomputePass); @@ -298,18 +262,9 @@ "print-full", "print in full s-expression format", createFullPrinterPass); registerPass( "print-call-graph", "print call graph", createPrintCallGraphPass); - - // Register PrintFunctionMap using its normal name. registerPass("print-function-map", "print a map of function indexes to names", createPrintFunctionMapPass); - // Also register it as "symbolmap" so that wasm-opt --symbolmap=foo is the - // same as wasm-as --symbolmap=foo even though the latter is not a pass - // (wasm-as cannot run arbitrary passes). - // TODO: switch emscripten to this name, then remove the old one - registerPass( - "symbolmap", "(alias for print-function-map)", createPrintFunctionMapPass); - registerPass("print-stack-ir", "print out Stack IR (useful for internal debugging)", createPrintStackIRPass); @@ -350,15 +305,6 @@ registerPass("safe-heap", "instrument loads and stores to check for invalid behavior", createSafeHeapPass); - registerPass("set-globals", - "sets specified globals to specified values", - createSetGlobalsPass); - registerPass("signature-pruning", - "remove params from function signature types where possible", - createSignaturePruningPass); - registerPass("signature-refining", - "apply more specific subtypes to signature types where possible", - createSignatureRefiningPass); registerPass("simplify-globals", "miscellaneous globals-related optimizations", createSimplifyGlobalsPass); @@ -424,18 +370,6 @@ registerPass("vacuum", "removes obviously unneeded code", createVacuumPass); // registerPass( // "lower-i64", "lowers i64 into pairs of i32s", createLowerInt64Pass); - - // Register passes used for internal testing. These don't show up in --help. - registerTestPass("catch-pop-fixup", - "fixup nested pops within catches", - createCatchPopFixupPass); -} - -void PassRunner::addIfNoDWARFIssues(std::string passName) { - auto pass = PassRegistry::get()->createPass(passName); - if (!pass->invalidatesDWARF() || !shouldPreserveDWARF()) { - doAdd(std::move(pass)); - } } void PassRunner::addDefaultOptimizationPasses() { @@ -444,157 +378,138 @@ addDefaultGlobalOptimizationPostPasses(); } -void PassRunner::addDefaultFunctionOptimizationPasses() { - // All the additions here are optional if DWARF must be preserved. That is, - // when DWARF is relevant we run fewer optimizations. - // FIXME: support DWARF in all of them. +// Check whether we should preserve valid DWARF while optimizing. If so, we +// disable optimizations that currently cause issues with debug info. +static bool shouldPreserveDWARF(PassOptions& options, Module& wasm) { + return options.debugInfo && Debug::hasDWARFSections(wasm); +} +void PassRunner::addDefaultFunctionOptimizationPasses() { + auto preserveDWARF = shouldPreserveDWARF(options, *wasm); // Untangling to semi-ssa form is helpful (but best to ignore merges // so as to not introduce new copies). - if (options.optimizeLevel >= 3 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("ssa-nomerge"); + // FIXME DWARF updating does not handle local changes yet. + if (!preserveDWARF && + (options.optimizeLevel >= 3 || options.shrinkLevel >= 1)) { + add("ssa-nomerge"); } // if we are willing to work very very hard, flatten the IR and do opts // that depend on flat IR - if (options.optimizeLevel >= 4) { - addIfNoDWARFIssues("flatten"); - // LocalCSE is particularly useful after flatten (see comment in the pass - // itself), but we must simplify locals a little first (as flatten adds many - // new and redundant ones, which make things seem different if we do not - // run some amount of simplify-locals first). - addIfNoDWARFIssues("simplify-locals-notee-nostructure"); - addIfNoDWARFIssues("local-cse"); - // TODO: add rereloop etc. here - } - addIfNoDWARFIssues("dce"); - addIfNoDWARFIssues("remove-unused-names"); - addIfNoDWARFIssues("remove-unused-brs"); - addIfNoDWARFIssues("remove-unused-names"); - addIfNoDWARFIssues("optimize-instructions"); + // FIXME DWARF updating does not handle local changes yet. + if (!preserveDWARF && options.optimizeLevel >= 4) { + add("flatten"); + add("local-cse"); + } + add("dce"); + add("remove-unused-names"); + add("remove-unused-brs"); + add("remove-unused-names"); + add("optimize-instructions"); if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("pick-load-signs"); + add("pick-load-signs"); } // early propagation if (options.optimizeLevel >= 3 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("precompute-propagate"); + add("precompute-propagate"); } else { - addIfNoDWARFIssues("precompute"); + add("precompute"); } if (options.lowMemoryUnused) { if (options.optimizeLevel >= 3 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("optimize-added-constants-propagate"); + add("optimize-added-constants-propagate"); } else { - addIfNoDWARFIssues("optimize-added-constants"); + add("optimize-added-constants"); } } if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("code-pushing"); + add("code-pushing"); } // don't create if/block return values yet, as coalesce can remove copies that // that could inhibit - addIfNoDWARFIssues("simplify-locals-nostructure"); - addIfNoDWARFIssues("vacuum"); // previous pass creates garbage - addIfNoDWARFIssues("reorder-locals"); + add("simplify-locals-nostructure"); + add("vacuum"); // previous pass creates garbage + add("reorder-locals"); // simplify-locals opens opportunities for optimizations - addIfNoDWARFIssues("remove-unused-brs"); - if (options.optimizeLevel > 1 && wasm->features.hasGC()) { - addIfNoDWARFIssues("heap2local"); - } + add("remove-unused-brs"); // if we are willing to work hard, also optimize copies before coalescing - if (options.optimizeLevel >= 3 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("merge-locals"); // very slow on e.g. sqlite + // FIXME DWARF updating does not handle local changes yet. + if (!preserveDWARF && + (options.optimizeLevel >= 3 || options.shrinkLevel >= 2)) { + add("merge-locals"); // very slow on e.g. sqlite + } + // FIXME DWARF updating does not handle local changes yet. + if (!preserveDWARF) { + add("coalesce-locals"); + } + add("simplify-locals"); + add("vacuum"); + add("reorder-locals"); + // FIXME DWARF updating does not handle local changes yet. + if (!preserveDWARF) { + add("coalesce-locals"); + add("reorder-locals"); } - if (options.optimizeLevel > 1 && wasm->features.hasGC()) { - // Coalescing may prevent subtyping (as a coalesced local must have the - // supertype of all those combined into it), so subtype first. - // TODO: when optimizing for size, maybe the order should reverse? - addIfNoDWARFIssues("local-subtyping"); - } - addIfNoDWARFIssues("coalesce-locals"); - if (options.optimizeLevel >= 3 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("local-cse"); - } - addIfNoDWARFIssues("simplify-locals"); - addIfNoDWARFIssues("vacuum"); - addIfNoDWARFIssues("reorder-locals"); - addIfNoDWARFIssues("coalesce-locals"); - addIfNoDWARFIssues("reorder-locals"); - addIfNoDWARFIssues("vacuum"); + add("vacuum"); if (options.optimizeLevel >= 3 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("code-folding"); + add("code-folding"); } - addIfNoDWARFIssues("merge-blocks"); // makes remove-unused-brs more effective - addIfNoDWARFIssues( - "remove-unused-brs"); // coalesce-locals opens opportunities - addIfNoDWARFIssues( - "remove-unused-names"); // remove-unused-brs opens opportunities - addIfNoDWARFIssues("merge-blocks"); // clean up remove-unused-brs new blocks + add("merge-blocks"); // makes remove-unused-brs more effective + add("remove-unused-brs"); // coalesce-locals opens opportunities + add("remove-unused-names"); // remove-unused-brs opens opportunities + add("merge-blocks"); // clean up remove-unused-brs new blocks // late propagation if (options.optimizeLevel >= 3 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("precompute-propagate"); + add("precompute-propagate"); } else { - addIfNoDWARFIssues("precompute"); + add("precompute"); } - addIfNoDWARFIssues("optimize-instructions"); + add("optimize-instructions"); if (options.optimizeLevel >= 2 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues( - "rse"); // after all coalesce-locals, and before a final vacuum + add("rse"); // after all coalesce-locals, and before a final vacuum } - addIfNoDWARFIssues("vacuum"); // just to be safe + add("vacuum"); // just to be safe } void PassRunner::addDefaultGlobalOptimizationPrePasses() { - addIfNoDWARFIssues("duplicate-function-elimination"); - addIfNoDWARFIssues("memory-packing"); - if (options.optimizeLevel >= 2) { - addIfNoDWARFIssues("once-reduction"); - } - if (wasm->features.hasGC() && getTypeSystem() == TypeSystem::Nominal && - options.optimizeLevel >= 2) { - addIfNoDWARFIssues("type-refining"); - addIfNoDWARFIssues("signature-pruning"); - addIfNoDWARFIssues("signature-refining"); - addIfNoDWARFIssues("global-refining"); - // Global type optimization can remove fields that are not needed, which can - // remove ref.funcs that were once assigned to vtables but are no longer - // needed, which can allow more code to be removed globally. After those, - // constant field propagation can be more effective. - addIfNoDWARFIssues("gto"); - addIfNoDWARFIssues("remove-unused-module-elements"); - addIfNoDWARFIssues("cfp"); + // FIXME DWARF updating does not handle merging debug info with merged code. + if (!shouldPreserveDWARF(options, *wasm)) { + add("duplicate-function-elimination"); } + add("memory-packing"); } void PassRunner::addDefaultGlobalOptimizationPostPasses() { - if (options.optimizeLevel >= 2 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("dae-optimizing"); - } - if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("inlining-optimizing"); + auto preserveDWARF = shouldPreserveDWARF(options, *wasm); + // FIXME DWARF may be badly affected currently as DAE changes function + // signatures and hence params and locals. + if (!preserveDWARF && + (options.optimizeLevel >= 2 || options.shrinkLevel >= 1)) { + add("dae-optimizing"); + } + // FIXME DWARF updating does not handle inlining yet. + if (!preserveDWARF && + (options.optimizeLevel >= 2 || options.shrinkLevel >= 2)) { + add("inlining-optimizing"); } - // Optimizations show more functions as duplicate, so run this here in Post. - addIfNoDWARFIssues("duplicate-function-elimination"); - addIfNoDWARFIssues("duplicate-import-elimination"); - - // perform after the number of functions is reduced by inlining-optimizing - if (options.shrinkLevel >= 2) { - addIfNoDWARFIssues("merge-similar-functions"); + // FIXME DWARF updating does not handle merging debug info with merged code. + if (!preserveDWARF) { + add("duplicate-function-elimination"); } - + add("duplicate-import-elimination"); if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) { - addIfNoDWARFIssues("simplify-globals-optimizing"); + add("simplify-globals-optimizing"); } else { - addIfNoDWARFIssues("simplify-globals"); + add("simplify-globals"); } - addIfNoDWARFIssues("remove-unused-module-elements"); + add("remove-unused-module-elements"); // may allow more inlining/dae/etc., need --converge for that - addIfNoDWARFIssues("directize"); + add("directize"); // perform Stack IR optimizations here, at the very end of the // optimization pipeline if (options.optimizeLevel >= 2 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("generate-stack-ir"); - addIfNoDWARFIssues("optimize-stack-ir"); + add("generate-stack-ir"); + add("optimize-stack-ir"); } } @@ -618,9 +533,6 @@ } void PassRunner::run() { - assert(!ran); - ran = true; - static const int passDebug = getPassDebug(); // Emit logging information when asked for. At passDebug level 1+ we log // the main passes, while in 2 we also log nested ones. Note that for @@ -758,13 +670,6 @@ } void PassRunner::doAdd(std::unique_ptr pass) { - if (pass->invalidatesDWARF() && shouldPreserveDWARF()) { - std::cerr << "warning: running pass '" << pass->name - << "' which is not fully compatible with DWARF\n"; - } - if (passRemovesDebugInfo(pass->name)) { - addedPassesRemovedDWARF = true; - } passes.emplace_back(std::move(pass)); } @@ -911,23 +816,4 @@ return passDebug; } -bool PassRunner::passRemovesDebugInfo(const std::string& name) { - return name == "strip" || name == "strip-debug" || name == "strip-dwarf"; -} - -bool PassRunner::shouldPreserveDWARF() { - // Check if the debugging subsystem wants to preserve DWARF. - if (!Debug::shouldPreserveDWARF(options, *wasm)) { - return false; - } - - // We may need DWARF. Check if one of our previous passes would remove it - // anyhow, in which case, there is nothing to preserve. - if (addedPassesRemovedDWARF) { - return false; - } - - return true; -} - } // namespace wasm diff -Nru binaryen-108/src/passes/passes.h binaryen-99/src/passes/passes.h --- binaryen-108/src/passes/passes.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/passes.h 2021-01-07 20:01:06.000000000 +0000 @@ -21,7 +21,7 @@ class Pass; -// Normal passes: +// All passes: Pass* createAlignmentLoweringPass(); Pass* createAsyncifyPass(); Pass* createAvoidReinterpretsPass(); @@ -30,7 +30,6 @@ Pass* createCodeFoldingPass(); Pass* createCodePushingPass(); Pass* createConstHoistingPass(); -Pass* createConstantFieldPropagationPass(); Pass* createDAEPass(); Pass* createDAEOptimizingPass(); Pass* createDataFlowOptsPass(); @@ -43,7 +42,6 @@ Pass* createDuplicateFunctionEliminationPass(); Pass* createEmitTargetFeaturesPass(); Pass* createExtractFunctionPass(); -Pass* createExtractFunctionIndexPass(); Pass* createFlattenPass(); Pass* createFuncCastEmulationPass(); Pass* createFullPrinterPass(); @@ -51,9 +49,6 @@ Pass* createGenerateDynCallsPass(); Pass* createGenerateI64DynCallsPass(); Pass* createGenerateStackIRPass(); -Pass* createGlobalRefiningPass(); -Pass* createGlobalTypeOptimizationPass(); -Pass* createHeap2LocalPass(); Pass* createI64ToI32LoweringPass(); Pass* createInlineMainPass(); Pass* createInliningPass(); @@ -62,16 +57,13 @@ Pass* createLegalizeJSInterfaceMinimallyPass(); Pass* createLimitSegmentsPass(); Pass* createLocalCSEPass(); -Pass* createLocalSubtypingPass(); Pass* createLogExecutionPass(); -Pass* createIntrinsicLoweringPass(); Pass* createInstrumentLocalsPass(); Pass* createInstrumentMemoryPass(); Pass* createLoopInvariantCodeMotionPass(); Pass* createMemory64LoweringPass(); Pass* createMemoryPackingPass(); Pass* createMergeBlocksPass(); -Pass* createMergeSimilarFunctionsPass(); Pass* createMergeLocalsPass(); Pass* createMinifiedPrinterPass(); Pass* createMinifyImportsPass(); @@ -79,17 +71,16 @@ Pass* createMinifyImportsAndExportsAndModulesPass(); Pass* createMetricsPass(); Pass* createNameListPass(); -Pass* createNameTypesPass(); -Pass* createOnceReductionPass(); +Pass* createNoExitRuntimePass(); Pass* createOptimizeAddedConstantsPass(); Pass* createOptimizeAddedConstantsPropagatePass(); Pass* createOptimizeInstructionsPass(); -Pass* createOptimizeForJSPass(); Pass* createOptimizeStackIRPass(); Pass* createPickLoadSignsPass(); Pass* createModAsyncifyAlwaysOnlyUnwindPass(); Pass* createModAsyncifyNeverUnwindPass(); -Pass* createPoppifyPass(); +Pass* createPostAssemblyScriptPass(); +Pass* createPostAssemblyScriptFinalizePass(); Pass* createPostEmscriptenPass(); Pass* createPrecomputePass(); Pass* createPrecomputePropagatePass(); @@ -111,9 +102,6 @@ Pass* createRedundantSetEliminationPass(); Pass* createRoundTripPass(); Pass* createSafeHeapPass(); -Pass* createSetGlobalsPass(); -Pass* createSignaturePruningPass(); -Pass* createSignatureRefiningPass(); Pass* createSimplifyLocalsPass(); Pass* createSimplifyGlobalsPass(); Pass* createSimplifyGlobalsOptimizingPass(); @@ -133,13 +121,9 @@ Pass* createSSAifyNoMergePass(); Pass* createTrapModeClamp(); Pass* createTrapModeJS(); -Pass* createTypeRefiningPass(); Pass* createUnteePass(); Pass* createVacuumPass(); -// Test passes: -Pass* createCatchPopFixupPass(); - } // namespace wasm #endif diff -Nru binaryen-108/src/passes/PickLoadSigns.cpp binaryen-99/src/passes/PickLoadSigns.cpp --- binaryen-108/src/passes/PickLoadSigns.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/PickLoadSigns.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -93,7 +93,9 @@ void optimize() { // optimize based on the info we saw - for (auto& [load, index] : loads) { + for (auto& pair : loads) { + auto* load = pair.first; + auto index = pair.second; auto& usage = usages[index]; // if we can't optimize, give up if (usage.totalUsages == 0 || // no usages, so no idea diff -Nru binaryen-108/src/passes/Poppify.cpp binaryen-99/src/passes/Poppify.cpp --- binaryen-108/src/passes/Poppify.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Poppify.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,513 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Poppify.cpp - Transform Binaryen IR to Poppy IR. -// -// Poppy IR represents stack machine code using normal Binaryen IR types by -// imposing the following constraints: -// -// 1. Function bodies and children of control flow (except If conditions) must -// be blocks. -// -// 2. Blocks may have any Expressions as children. The sequence of instructions -// in a block follows the same validation rules as in WebAssembly. That -// means that any expression may have a concrete type, not just the final -// expression in the block. -// -// 3. All other children must be Pops, which are used to determine the input -// stack type of each instruction. Pops may not have `unreachable` type. -// Pops must correspond to the results of previous expressions or block -// inputs in a stack discipline. -// -// 4. Only control flow structures and instructions that have polymorphic -// unreachable behavior in WebAssembly may have unreachable type. Blocks may -// be unreachable when they are not branch targets and when they have an -// unreachable child. Note that this means a block may be unreachable even -// if it would otherwise have a concrete type, unlike in Binaryen IR. For -// example, this block could have unreachable type in Poppy IR but would -// have to have type i32 in Binaryen IR: -// -// (block -// (unreachable) -// (i32.const 1) -// ) -// -// As an example of Poppification, the following Binaryen IR Function: -// -// (func $foo (result i32) -// (i32.add -// (i32.const 42) -// (i32.const 5) -// ) -// ) -// -// would look like this in Poppy IR: -// -// (func $foo (result i32) -// (block -// (i32.const 42) -// (i32.const 5) -// (i32.add -// (pop i32) -// (pop i32) -// ) -// ) -// ) -// -// Notice that the sequence of instructions in the block is now identical to the -// sequence of instructions in a WebAssembly binary. Also note that Poppy IR's -// validation rules are largely additional on top of the normal Binaryen IR -// validation rules, with the only exceptions being block body validation and -// block unreachability rules. -// - -#include "ir/names.h" -#include "ir/properties.h" -#include "ir/stack-utils.h" -#include "ir/utils.h" -#include "pass.h" -#include "wasm-stack.h" - -namespace wasm { - -namespace { - -// Generate names for the elements of tuple globals -Name getGlobalElem(Module* module, Name global, Index i) { - return Names::getValidGlobalName( - *module, std::string(global.c_str()) + '$' + std::to_string(i)); -} - -struct Poppifier : BinaryenIRWriter { - // Collects instructions to be inserted into a block at a certain scope, as - // well as what kind of scope it is, which determines how the instructions are - // inserted. - struct Scope { - enum Kind { Func, Block, Loop, If, Else, Try, Catch } kind; - std::vector instrs; - Scope(Kind kind) : kind(kind) {} - }; - - Module* module; - Builder builder; - std::vector scopeStack; - - // Maps tuple locals to the new locals that will hold their elements - std::unordered_map> tupleVars; - - // Records the scratch local to be used for tuple.extracts of each type - std::unordered_map scratchLocals; - - Poppifier(Function* func, Module* module); - - Index getScratchLocal(Type type); - - // Replace `expr`'s children with Pops of the correct type. - void poppify(Expression* expr); - - // Pops the current scope off the scope stack and replaces `expr` with a block - // containing the instructions from that scope. - void patchScope(Expression*& expr); - - // BinaryenIRWriter methods - void emit(Expression* curr); - void emitHeader() {} - void emitIfElse(If* curr); - void emitCatch(Try* curr, Index i); - void emitCatchAll(Try* curr); - void emitDelegate(Try* curr); - void emitScopeEnd(Expression* curr); - void emitFunctionEnd(); - void emitUnreachable(); - void emitDebugLocation(Expression* curr) {} - - // Tuple lowering methods - void emitTupleExtract(TupleExtract* curr); - void emitDrop(Drop* curr); - void emitLocalGet(LocalGet* curr); - void emitLocalSet(LocalSet* curr); - void emitGlobalGet(GlobalGet* curr); - void emitGlobalSet(GlobalSet* curr); -}; - -Poppifier::Poppifier(Function* func, Module* module) - : BinaryenIRWriter(func), module(module), builder(*module) { - // Start with a scope to emit top-level instructions into - scopeStack.emplace_back(Scope::Func); - - // Map each tuple local to a set of expanded locals - for (Index i = func->getNumParams(), end = func->getNumLocals(); i < end; - ++i) { - Type localType = func->getLocalType(i); - if (localType.isTuple()) { - auto& vars = tupleVars[i]; - for (auto type : localType) { - vars.push_back(builder.addVar(func, type)); - } - } - } -} - -Index Poppifier::getScratchLocal(Type type) { - // If there is no scratch local for `type`, allocate a new one - auto insert = scratchLocals.insert({type, Index(-1)}); - if (insert.second) { - insert.first->second = builder.addVar(func, type); - } - return insert.first->second; -} - -void Poppifier::patchScope(Expression*& expr) { - auto scope = std::move(scopeStack.back()); - auto& instrs = scope.instrs; - scopeStack.pop_back(); - if (auto* block = expr->dynCast()) { - // Reuse blocks, but do not patch a block into itself, which would otherwise - // happen when emitting if/else or try/catch arms and function bodies. - if (instrs.size() == 0 || instrs[0] != block) { - block->list.set(instrs); - } - } else { - // Otherwise create a new block, even if we have just a single - // expression. We want blocks in every new scope rather than other - // instructions because Poppy IR optimizations only look at the children of - // blocks. - expr = builder.makeBlock(instrs, expr->type); - } -} - -void Poppifier::emit(Expression* curr) { - // Control flow structures introduce new scopes. The instructions collected - // for the new scope will be patched back into the original Expression when - // the scope ends. - if (Properties::isControlFlowStructure(curr)) { - Scope::Kind kind; - switch (curr->_id) { - case Expression::BlockId: { - kind = Scope::Block; - break; - } - case Expression::LoopId: { - kind = Scope::Loop; - break; - } - case Expression::IfId: - // The condition has already been emitted - curr->cast()->condition = builder.makePop(Type::i32); - kind = Scope::If; - break; - case Expression::TryId: - kind = Scope::Try; - break; - default: - WASM_UNREACHABLE("Unexpected control flow structure"); - } - scopeStack.emplace_back(kind); - } else if (curr->is()) { - // Turns into nothing when poppified - return; - } else if (curr->is()) { - // Turns into nothing when poppified - return; - } else if (auto* extract = curr->dynCast()) { - emitTupleExtract(extract); - } else if (auto* drop = curr->dynCast()) { - emitDrop(drop); - } else if (auto* get = curr->dynCast()) { - emitLocalGet(get); - } else if (auto* set = curr->dynCast()) { - emitLocalSet(set); - } else if (auto* get = curr->dynCast()) { - emitGlobalGet(get); - } else if (auto* set = curr->dynCast()) { - emitGlobalSet(set); - } else { - // Replace all children (which have already been emitted) with pops and emit - // the current instruction into the current scope. - poppify(curr); - scopeStack.back().instrs.push_back(curr); - } -}; - -void Poppifier::emitIfElse(If* curr) { - auto& scope = scopeStack.back(); - WASM_UNUSED(scope); - assert(scope.kind == Scope::If); - patchScope(curr->ifTrue); - scopeStack.emplace_back(Scope::Else); -} - -void Poppifier::emitCatch(Try* curr, Index i) { - auto& scope = scopeStack.back(); - WASM_UNUSED(scope); - if (i == 0) { - assert(scope.kind == Scope::Try); - patchScope(curr->body); - } else { - assert(scope.kind == Scope::Catch); - patchScope(curr->catchBodies[i - 1]); - } - scopeStack.emplace_back(Scope::Catch); -} - -void Poppifier::emitCatchAll(Try* curr) { - auto& scope = scopeStack.back(); - WASM_UNUSED(scope); - if (curr->catchBodies.size() == 1) { - assert(scope.kind == Scope::Try); - patchScope(curr->body); - } else { - assert(scope.kind == Scope::Catch); - patchScope(curr->catchBodies[curr->catchBodies.size() - 2]); - } - scopeStack.emplace_back(Scope::Catch); -} - -void Poppifier::emitDelegate(Try* curr) { - auto& scope = scopeStack.back(); - WASM_UNUSED(scope); - assert(scope.kind == Scope::Try); - patchScope(curr->body); - scopeStack.back().instrs.push_back(curr); -} - -void Poppifier::emitScopeEnd(Expression* curr) { - switch (scopeStack.back().kind) { - case Scope::Block: - patchScope(curr); - break; - case Scope::Loop: - patchScope(curr->cast()->body); - break; - case Scope::If: - patchScope(curr->cast()->ifTrue); - break; - case Scope::Else: - patchScope(curr->cast()->ifFalse); - break; - case Scope::Catch: - patchScope(curr->cast()->catchBodies.back()); - break; - case Scope::Try: - WASM_UNREACHABLE("try without catch"); - case Scope::Func: - WASM_UNREACHABLE("unexpected end of function"); - } - scopeStack.back().instrs.push_back(curr); -} - -void Poppifier::emitFunctionEnd() { - auto& scope = scopeStack.back(); - WASM_UNUSED(scope); - assert(scope.kind == Scope::Func); - patchScope(func->body); -} - -void Poppifier::emitUnreachable() { - // TODO: Try making this a nop - auto& instrs = scopeStack.back().instrs; - instrs.push_back(builder.makeUnreachable()); -} - -void Poppifier::emitTupleExtract(TupleExtract* curr) { - auto& instrs = scopeStack.back().instrs; - auto types = curr->tuple->type; - // Drop all the values after the one we want - for (size_t i = types.size() - 1; i > curr->index; --i) { - instrs.push_back(builder.makeDrop(builder.makePop(types[i]))); - } - // If the extracted value is the only one left, we're done - if (curr->index == 0) { - return; - } - // Otherwise, save it to a scratch local and drop the other values - auto type = types[curr->index]; - Index scratch = getScratchLocal(type); - instrs.push_back(builder.makeLocalSet(scratch, builder.makePop(type))); - for (size_t i = curr->index - 1; i != size_t(-1); --i) { - instrs.push_back(builder.makeDrop(builder.makePop(types[i]))); - } - // Retrieve the saved value - instrs.push_back(builder.makeLocalGet(scratch, type)); -} - -void Poppifier::emitDrop(Drop* curr) { - auto& instrs = scopeStack.back().instrs; - if (curr->value->type.isTuple()) { - // Drop each element individually - auto types = curr->value->type; - for (auto it = types.rbegin(), end = types.rend(); it != end; ++it) { - instrs.push_back(builder.makeDrop(builder.makePop(*it))); - } - } else { - poppify(curr); - instrs.push_back(curr); - } -} - -void Poppifier::emitLocalGet(LocalGet* curr) { - auto& instrs = scopeStack.back().instrs; - if (curr->type.isTuple()) { - auto types = func->getLocalType(curr->index); - const auto& elems = tupleVars[curr->index]; - for (size_t i = 0; i < types.size(); ++i) { - instrs.push_back(builder.makeLocalGet(elems[i], types[i])); - } - } else { - instrs.push_back(curr); - } -} - -void Poppifier::emitLocalSet(LocalSet* curr) { - auto& instrs = scopeStack.back().instrs; - if (curr->value->type.isTuple()) { - auto types = func->getLocalType(curr->index); - const auto& elems = tupleVars[curr->index]; - // Add the unconditional sets - for (size_t i = types.size() - 1; i >= 1; --i) { - instrs.push_back( - builder.makeLocalSet(elems[i], builder.makePop(types[i]))); - } - if (curr->isTee()) { - // Use a tee followed by gets to retrieve the tuple - instrs.push_back( - builder.makeLocalTee(elems[0], builder.makePop(types[0]), types[0])); - for (size_t i = 1; i < types.size(); ++i) { - instrs.push_back(builder.makeLocalGet(elems[i], types[i])); - } - } else { - // Otherwise just add the last set - instrs.push_back( - builder.makeLocalSet(elems[0], builder.makePop(types[0]))); - } - } else { - poppify(curr); - instrs.push_back(curr); - } -} - -void Poppifier::emitGlobalGet(GlobalGet* curr) { - auto& instrs = scopeStack.back().instrs; - if (curr->type.isTuple()) { - auto types = module->getGlobal(curr->name)->type; - for (Index i = 0; i < types.size(); ++i) { - instrs.push_back( - builder.makeGlobalGet(getGlobalElem(module, curr->name, i), types[i])); - } - } else { - instrs.push_back(curr); - } -} - -void Poppifier::emitGlobalSet(GlobalSet* curr) { - auto& instrs = scopeStack.back().instrs; - if (curr->value->type.isTuple()) { - auto types = module->getGlobal(curr->name)->type; - for (Index i = types.size(); i > 0; --i) { - instrs.push_back( - builder.makeGlobalSet(getGlobalElem(module, curr->name, i - 1), - builder.makePop(types[i - 1]))); - } - } else { - poppify(curr); - instrs.push_back(curr); - } -} - -void Poppifier::poppify(Expression* expr) { - struct Poppifier : PostWalker { - bool scanned = false; - Builder builder; - Poppifier(Builder& builder) : builder(builder) {} - - static void scan(Poppifier* self, Expression** currp) { - if (!self->scanned) { - self->scanned = true; - PostWalker::scan(self, currp); - } else { - *currp = self->builder.makePop((*currp)->type); - } - } - } poppifier(builder); - poppifier.walk(expr); -} - -class PoppifyFunctionsPass : public Pass { - bool isFunctionParallel() override { return true; } - void - runOnFunction(PassRunner* runner, Module* module, Function* func) override { - if (func->profile != IRProfile::Poppy) { - Poppifier(func, module).write(); - func->profile = IRProfile::Poppy; - } - } - Pass* create() override { return new PoppifyFunctionsPass; } -}; - -} // anonymous namespace - -class PoppifyPass : public Pass { - void run(PassRunner* runner, Module* module) { - PassRunner subRunner(runner); - subRunner.add(std::make_unique()); - // TODO: Enable this once it handles Poppy blocks correctly - // subRunner.add(std::make_unique()); - subRunner.run(); - lowerTupleGlobals(module); - } - - void lowerTupleGlobals(Module* module) { - Builder builder(*module); - std::vector> newGlobals; - for (int g = module->globals.size() - 1; g >= 0; --g) { - const auto& global = *module->globals[g]; - if (!global.type.isTuple()) { - continue; - } - assert(!global.imported()); - for (Index i = 0; i < global.type.size(); ++i) { - Expression* init; - if (global.init == nullptr) { - init = nullptr; - } else if (auto* make = global.init->dynCast()) { - init = make->operands[i]; - } else if (auto* get = global.init->dynCast()) { - init = builder.makeGlobalGet(getGlobalElem(module, get->name, i), - global.type[i]); - } else { - WASM_UNREACHABLE("Unexpected tuple global initializer"); - } - auto mutability = - global.mutable_ ? Builder::Mutable : Builder::Immutable; - newGlobals.emplace_back( - builder.makeGlobal(getGlobalElem(module, global.name, i), - global.type[i], - init, - mutability)); - } - module->removeGlobal(global.name); - } - while (newGlobals.size()) { - module->addGlobal(std::move(newGlobals.back())); - newGlobals.pop_back(); - } - module->updateMaps(); - } -}; - -Pass* createPoppifyPass() { return new PoppifyPass; } - -} // namespace wasm diff -Nru binaryen-108/src/passes/PostAssemblyScript.cpp binaryen-99/src/passes/PostAssemblyScript.cpp --- binaryen-108/src/passes/PostAssemblyScript.cpp 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/src/passes/PostAssemblyScript.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,640 @@ +/* + * Copyright 2019 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Misc optimizations that are useful for and/or are only valid for +// AssemblyScript output. +// + +#include "ir/flat.h" +#include "ir/local-graph.h" +#include "pass.h" +#include "wasm-builder.h" +#include "wasm-traversal.h" +#include "wasm.h" +#include +#include +#ifdef POST_ASSEMBLYSCRIPT_DEBUG +#include +#endif + +namespace wasm { + +namespace PostAssemblyScript { + +static Name RETAIN = Name("~lib/rt/pure/__retain"); +static Name RELEASE = Name("~lib/rt/pure/__release"); +static Name ALLOC = Name("~lib/rt/tlsf/__alloc"); +static Name ALLOCARRAY = Name("~lib/rt/__allocArray"); + +template using Map = std::unordered_map; +template using Set = std::unordered_set; + +// A variant of LocalGraph that considers only assignments when computing +// influences. +// +// This allows us to find locals aliasing a retain, while ignoring other +// influences. +// +// For example, we are interested in +// +// var a = __retain(X) +// var b = a; +// __release(b); // releases X +// +// but not in +// +// var a = __retain(X); +// var b = someFunction(a); +// __release(b); +// return a; +// +// since the latter releases not 'X' but the reference returned by the call, +// which is usually something else. +struct AliasGraph : LocalGraph { + AliasGraph(Function* func) : LocalGraph(func) {} + void computeInfluences() { + for (auto& pair : locations) { + auto* curr = pair.first; + if (auto* set = curr->dynCast()) { + if (auto* get = set->value->dynCast()) { + getInfluences[get].insert(set); + } + } else { + auto* get = curr->cast(); + for (auto* set : getSetses[get]) { + setInfluences[set].insert(get); + } + } + } + } +}; + +// Tests if the given call calls retain. Note that this differs from what we +// consider a full retain pattern, which must also set a local. +static bool isRetainCall(Call* expr) { + // __retain(...) + return expr->target == RETAIN && expr->type == Type::i32 && + expr->operands.size() == 1 && expr->operands[0]->type == Type::i32; +} + +// Tests if a local.set is considered to be a full retain pattern. +static bool isRetain(LocalSet* expr) { + // local.set(X, __retain(...)) + if (auto* call = expr->value->dynCast()) { + return isRetainCall(call); + } + return false; +} + +#ifndef NDEBUG +// Tests if the given location is that of a full retain pattern. +static bool isRetainLocation(Expression** expr) { + if (expr != nullptr) { + if (auto localSet = (*expr)->dynCast()) { + return isRetain(localSet); + } + } + return false; +} +#endif + +// Tests if the given call calls release. Note that this differs from what we +// consider a full release pattern, which must also get a local. +static bool isReleaseCall(Call* expr) { + // __release(...) + return expr->target == RELEASE && expr->type == Type::none && + expr->operands.size() == 1 && expr->operands[0]->type == Type::i32; +} + +// Tests if the given location is that of a full release pattern. Note that +// the local.get is our key when checking for releases to align with +// AliasGraph, and not the outer call, which is also the reason why there is +// no `isRelease` as we can't tell from the local.get alone. +static bool isReleaseLocation(Expression** expr) { + // __release(local.get(X, ...)) + if (expr != nullptr) { + if (auto* call = (*expr)->dynCast()) { + return isReleaseCall(call) && call->operands[0]->is(); + } + } + return false; +} + +// Tests if the given call calls any allocation function. +static bool isAllocCall(Call* expr) { + return (expr->target == ALLOC || expr->target == ALLOCARRAY) && + expr->type == Type::i32; +} + +// A pass that eliminates redundant retain and release calls. +// +// Does a cheap traversal first, remembering ARC-style patterns, and goes all-in +// only if it finds any. +// +// This is based on the assumption that the compiler is not allowed to emit +// unbalanced retains or releases, except if +// +// * a value is returned or otherwise escapes in one branch or +// * a branch is being internally unified by the compiler +// +// which we detect below. In turn, we do not have to deal with control +// structures but can instead look for escapes reached (by any alias) using +// AliasGraph. +// +// For example, in code like +// +// var a = __retain(X); +// if (cond) { +// return a; +// } +// __release(a); +// return null; +// +// we cannot eliminate the retain/release pair because the implementation +// dictates that returned references must remain retained for the caller since +// dropping to RC=0 on the boundary would prematurely free the object. +// +// Typical patterns this recognizes are simple pairs of the form +// +// var a = __retain(X); +// __release(a); +// +// retains with balanced releases of the form +// +// var a = __retain(X); +// if (cond) { +// __release(a); +// } else { +// __release(a); +// } +// +// releases with balanced retains of the form +// +// var a; +// if (cond) { +// a = __retain(X); +// } else { +// a = __retain(Y); +// } +// __release(a); +// +// including technically invalid patterns assumed to be not present in compiler +// output, like: +// +// var b = __retain(a); +// if (cond) { +// __release(b); // unbalanced release +// } +// +// To detect the latter, we'd have to follow control structures around, which +// we don't do since it isn't neccessary / to keep the amount of work minimal. +struct OptimizeARC : public WalkerPass> { + + bool isFunctionParallel() override { return true; } + + Pass* create() override { return new OptimizeARC; } + + // Sets that are retains, to location + Map retains; + + // Gets that are releases, to location + Map releases; + + // Gets that are escapes, i.e. being returned or thrown + Set escapes; + + void visitLocalSet(LocalSet* curr) { + if (isRetain(curr)) { + retains[curr] = getCurrentPointer(); + } + } + + void visitCall(Call* curr) { + auto** currp = getCurrentPointer(); + if (isReleaseLocation(currp)) { + releases[curr->operands[0]->cast()] = currp; + } + } + + void visitReturn(Return* curr) { + // return(local.get(X, ...)) ? + // indicates that an object is returned from one function and given to + // another, so releasing it would be invalid. + auto* value = curr->value; + if (value) { + if (auto* localGet = value->dynCast()) { + escapes.insert(localGet); + } + } + } + + void visitThrow(Throw* curr) { + // throw(..., local.get(X, ...), ...) ? + // indicates that an object is thrown in one function and can be caught + // anywhere, like in another function, so releasing it would be invalid. + for (auto* operand : curr->operands) { + if (auto* localGet = operand->dynCast()) { + escapes.insert(localGet); + break; + } + } + } + + void eliminateRetain(Expression** location) { + assert(isRetainLocation(location)); + auto* localSet = (*location)->cast(); + localSet->value = localSet->value->cast()->operands[0]; + } + + void eliminateRelease(Expression** location) { + assert(isReleaseLocation(location)); + Builder builder(*getModule()); + *location = builder.makeNop(); + } + + // Tests if a retain reaches an escape and thus is considered necessary. + bool + testReachesEscape(LocalSet* retain, AliasGraph& graph, Set& seen) { + for (auto* localGet : graph.setInfluences[retain]) { + if (releases.find(localGet) != releases.end()) { + continue; + } + if (escapes.find(localGet) != escapes.end()) { + return true; + } + for (auto* localSet : graph.getInfluences[localGet]) { + if (seen.find(localSet) == seen.end()) { + seen.insert(localSet); + if (testReachesEscape(localSet, graph, seen)) { + return true; + } + } + } + } + return false; + } + + bool testReachesEscape(LocalSet* retain, AliasGraph& graph) { + Set seen; + return testReachesEscape(retain, graph, seen); + } + + // Collects all reachable releases of a retain. + void collectReleases(LocalSet* retain, + AliasGraph& graph, + Set& found, + Set& seen) { + for (auto* localGet : graph.setInfluences[retain]) { + auto foundRelease = releases.find(localGet); + if (foundRelease != releases.end()) { + found.insert(foundRelease->second); + } else { + for (auto* localSet : graph.getInfluences[localGet]) { + if (seen.find(localSet) == seen.end()) { + seen.insert(localSet); + collectReleases(localSet, graph, found, seen); + } + } + } + } + } + + void collectReleases(LocalSet* retain, + AliasGraph& graph, + Set& found) { + Set seen; + collectReleases(retain, graph, found, seen); + } + + // Given a retain, gets the retained expression + static Expression* getRetainedExpression(LocalSet* retain) { + assert(isRetain(retain)); + return retain->value->cast()->operands[0]; + } + + // Tests if a retained value originates at an allocation and thus is + // considered necessary. + bool testRetainsAllocation(Expression* retained, + AliasGraph& graph, + Set& seen) { + if (auto* call = retained->dynCast()) { + if (call->target == ALLOC || call->target == ALLOCARRAY) { + return true; + } + } else { + if (auto* localGet = retained->dynCast()) { + for (auto* localSet : graph.getSetses[localGet]) { + if (localSet != nullptr) { + if (seen.find(localSet) == seen.end()) { + seen.insert(localSet); + if (testRetainsAllocation(localSet->value, graph, seen)) { + return true; + } + } + } + } + } + } + return false; + } + + bool testRetainsAllocation(Expression* retained, AliasGraph& graph) { + Set seen; + return testRetainsAllocation(retained, graph, seen); + } + + // Given a release location, gets the local.get that is our release indicator + static LocalGet* getReleaseByLocation(Expression** releaseLocation) { + assert(isReleaseLocation(releaseLocation)); + return (*releaseLocation)->cast()->operands[0]->cast(); + } + + // Tests if a release has balanced retains, that is it is being retained in + // any path leading to the release. For example + // + // var c = somethingElse() || a; + // ... + // + // which compiles to + // + // if (!(b = somethingElse())) { + // b = __retain(a); + // } + // var c = b; + // ... + // __release(c); + // + // is unbalanced since it reaches a retain and something else. Here, the + // compiler inserts the retain call because it must unify the two branches + // since the result of `somethingElse()` is known to be retained for the + // caller and the other branch must yield a retained value as well. + bool testBalancedRetains(LocalGet* release, + AliasGraph& graph, + Map& cache, + Set& seen) { + auto cached = cache.find(release); + if (cached != cache.end()) { + return cached->second; + } + for (auto* localSet : graph.getSetses[release]) { + if (localSet == nullptr) { + return cache[release] = false; + } + if (retains.find(localSet) == retains.end()) { + if (auto* localGet = localSet->value->dynCast()) { + if (seen.find(localGet) == seen.end()) { + seen.insert(localGet); + if (!testBalancedRetains(localGet, graph, cache, seen)) { + return cache[release] = false; + } + } else { + return cache[release] = false; + } + } else { + return cache[release] = false; + } + } + } + return cache[release] = true; + } + + bool testBalancedRetains(LocalGet* release, + AliasGraph& graph, + Map& cache) { + Set seen; + return testBalancedRetains(release, graph, cache, seen); + } + + void doWalkFunction(Function* func) { + Flat::verifyFlatness(func); +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << "[PostAssemblyScript::OptimizeARC] walking " << func->name + << "\n"; +#endif + super::doWalkFunction(func); + if (retains.empty()) { +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " no ARC code\n"; +#endif + return; + } + + AliasGraph graph(func); + graph.computeInfluences(); + + Set redundantRetains; + Set redundantReleases; + Map balancedRetainsCache; + + // For each retain, check that it + // + // * doesn't reach an escape + // * doesn't retain an allocation + // * reaches at least one release + // * reaches only releases with balanced retains + // + for (auto& pair : retains) { + auto* retain = pair.first; + auto** retainLocation = pair.second; + if (!testReachesEscape(retain, graph)) { + if (!testRetainsAllocation(getRetainedExpression(retain), graph)) { + Set releaseLocations; + collectReleases(retain, graph, releaseLocations); + if (!releaseLocations.empty()) { + bool allBalanced = true; + for (auto** releaseLocation : releaseLocations) { + if (!testBalancedRetains(getReleaseByLocation(releaseLocation), + graph, + balancedRetainsCache)) { + allBalanced = false; + break; + } + } + if (allBalanced) { +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " eliminating "; + std::cerr << *retain << '\n'; + std::cerr << " reaching\n"; +#endif + redundantRetains.insert(retainLocation); + for (auto** getLocation : releaseLocations) { +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " "; + std::cerr << **getLocation << '\n'; + std::cerr << "\n"; +#endif + redundantReleases.insert(getLocation); + } +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + } else { + std::cerr << " cannot eliminate "; + std::cerr << *retain << '\n'; + std::cerr << " - unbalanced\n"; +#endif + } +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + } else { + std::cerr << " cannot eliminate "; + std::cerr << *retain << '\n'; + std::cerr << " - zero releases\n"; +#endif + } +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + } else { + std::cerr << " cannot eliminate "; + std::cerr << *retain << '\n'; + std::cerr << " - retains allocation\n"; +#endif + } +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + } else { + std::cerr << " cannot eliminate "; + std::cerr << *retain << '\n'; + std::cerr << " - reaches return\n"; +#endif + } + } + for (auto** location : redundantRetains) { + eliminateRetain(location); + } + for (auto** location : redundantReleases) { + eliminateRelease(location); + } +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " eliminated " << redundantRetains.size() << "/" + << retains.size() << " retains and " << redundantReleases.size() + << "/" << releases.size() << " releases\n"; +#endif + } +}; + +// Eliminating retains and releases makes it more likely that other passes lead +// to collapsed release/retain pairs that are not full retain or release +// patterns, and this pass finalizes such pairs. Typical patterns are entire +// unnecessary allocations of the form +// +// __release(__retain(__alloc(...)); +// +// otherwise unnecessary pairs of the form +// +// __release(__retain(...)); +// +// or retains/releases of constants which indicate data in static memory which +// are unnecessary to refcount: +// +// __retain("staticString"); +// +// __release("staticString"); +// +struct FinalizeARC : public WalkerPass> { + + bool isFunctionParallel() override { return true; } + + Pass* create() override { return new FinalizeARC; } + + uint32_t eliminatedAllocations = 0; + uint32_t eliminatedRetains = 0; + uint32_t eliminatedReleases = 0; + + void visitCall(Call* curr) { + if (isReleaseCall(curr)) { + if (auto* releasedCall = curr->operands[0]->dynCast()) { + if (isRetainCall(releasedCall)) { + if (auto* retainedCall = releasedCall->operands[0]->dynCast()) { + if (isAllocCall(retainedCall)) { + // __release(__retain(__alloc(...))) - unnecessary allocation +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " finalizing "; + std::cerr << *curr << '\n'; + std::cerr << " - unnecessary allocation\n"; +#endif + Builder builder(*getModule()); + replaceCurrent(builder.makeNop()); + ++eliminatedAllocations; + ++eliminatedRetains; + ++eliminatedReleases; + return; + } + } + // __release(__retain(...)) - unnecessary pair +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " finalizing "; + std::cerr << *curr << '\n'; + std::cerr << " - unnecessary pair\n"; +#endif + Builder builder(*getModule()); + replaceCurrent(builder.makeDrop(releasedCall->operands[0])); + ++eliminatedRetains; + ++eliminatedReleases; + } + } else if (curr->operands[0]->is()) { + // __release(42) - unnecessary static release +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " finalizing "; + std::cerr << *curr << '\n'; + std::cerr << " - static release\n"; +#endif + Builder builder(*getModule()); + replaceCurrent(builder.makeNop()); + ++eliminatedReleases; + } + } else if (isRetainCall(curr)) { + if (auto* retainedConst = curr->operands[0]->dynCast()) { + // __retain(42) - unnecessary static retain +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << " finalizing "; + std::cerr << *curr << '\n'; + std::cerr << " - static retain\n"; +#endif + replaceCurrent(retainedConst); + ++eliminatedRetains; + } + } + } + + void doWalkFunction(Function* func) { +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + std::cerr << "[PostAssemblyScript::FinalizeARC] walking " << func->name + << "\n"; +#endif + super::doWalkFunction(func); +#ifdef POST_ASSEMBLYSCRIPT_DEBUG + if (eliminatedAllocations > 0 || eliminatedRetains > 0 || + eliminatedReleases > 0) { + std::cerr << " finalized " << eliminatedAllocations << " allocations, " + << eliminatedRetains << " retains and" << eliminatedReleases + << " releases\n"; + } else { + std::cerr << " nothing to do\n"; + } +#endif + } +}; + +} // namespace PostAssemblyScript + +// declare passes + +Pass* createPostAssemblyScriptPass() { + return new PostAssemblyScript::OptimizeARC(); +} + +Pass* createPostAssemblyScriptFinalizePass() { + return new PostAssemblyScript::FinalizeARC(); +} + +} // namespace wasm diff -Nru binaryen-108/src/passes/PostEmscripten.cpp binaryen-99/src/passes/PostEmscripten.cpp --- binaryen-108/src/passes/PostEmscripten.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/PostEmscripten.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -61,13 +61,13 @@ hasInvokes = true; } } - if (!hasInvokes || module->tables.empty()) { + if (!hasInvokes) { return; } // Next, see if the Table is flat, which we need in order to see where // invokes go statically. (In dynamic linking, the table is not flat, // and we can't do this.) - TableUtils::FlatTable flatTable(*module, *module->tables[0]); + TableUtils::FlatTable flatTable(module->table); if (!flatTable.valid) { return; } @@ -108,32 +108,20 @@ void visitCall(Call* curr) { auto* target = getModule()->getFunction(curr->target); - if (!isInvoke(target)) { - return; - } - // The first operand is the function pointer index, which must be - // constant if we are to optimize it statically. - if (auto* index = curr->operands[0]->dynCast()) { - size_t indexValue = index->value.geti32(); - if (indexValue >= flatTable.names.size()) { - // UB can lead to indirect calls to invalid pointers. - return; - } - auto actualTarget = flatTable.names[indexValue]; - if (actualTarget.isNull()) { - // UB can lead to an indirect call of 0 or an index in which there - // is no function name. - return; - } - if (map[getModule()->getFunction(actualTarget)].canThrow) { - return; - } - // This invoke cannot throw! Make it a direct call. - curr->target = actualTarget; - for (Index i = 0; i < curr->operands.size() - 1; i++) { - curr->operands[i] = curr->operands[i + 1]; + if (isInvoke(target)) { + // The first operand is the function pointer index, which must be + // constant if we are to optimize it statically. + if (auto* index = curr->operands[0]->dynCast()) { + auto actualTarget = flatTable.names.at(index->value.geti32()); + if (!map[getModule()->getFunction(actualTarget)].canThrow) { + // This invoke cannot throw! Make it a direct call. + curr->target = actualTarget; + for (Index i = 0; i < curr->operands.size() - 1; i++) { + curr->operands[i] = curr->operands[i + 1]; + } + curr->operands.resize(curr->operands.size() - 1); + } } - curr->operands.resize(curr->operands.size() - 1); } } }; diff -Nru binaryen-108/src/passes/Precompute.cpp binaryen-99/src/passes/Precompute.cpp --- binaryen-108/src/passes/Precompute.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Precompute.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -33,40 +33,13 @@ #include #include #include -#include #include #include #include namespace wasm { -using GetValues = std::unordered_map; - -// A map of values on the heap. This maps the expressions that create the -// heap data (struct.new, array.new, etc.) to the data they are created with. -// Each such expression gets its own GCData created for it. This allows -// computing identity between locals referring to the same GCData, by seeing -// if they point to the same thing. -// -// Note that a source expression may create different data each time it is -// reached in a loop, -// -// (loop -// (if .. -// (local.set $x -// (struct.new .. -// ) -// ) -// ..compare $x to something.. -// ) -// -// Just like in SSA form, this is not a problem because the loop entry must -// have a merge, if a value entering the loop might be noticed. In SSA form -// that means a phi is created, and identity is set there. In our -// representation, the merge will cause a local.get of $x to have more -// possible input values than that struct.new, which means we will not infer -// a value for it, and not attempt to say anything about comparisons of $x. -using HeapValues = std::unordered_map>; +typedef std::unordered_map GetValues; // Precomputes an expression. Errors if we hit anything that can't be // precomputed. Inherits most of its functionality from @@ -75,14 +48,10 @@ class PrecomputingExpressionRunner : public ConstantExpressionRunner { - using Super = ConstantExpressionRunner; - // Concrete values of gets computed during the pass, which the runner does not // know about since it only records values of sets it visits. GetValues& getValues; - HeapValues& heapValues; - // Limit evaluation depth for 2 reasons: first, it is highly unlikely // that we can do anything useful to precompute a hugely nested expression // (we should succed at smaller parts of it first). Second, a low limit is @@ -98,7 +67,6 @@ public: PrecomputingExpressionRunner(Module* module, GetValues& getValues, - HeapValues& heapValues, bool replaceExpression) : ConstantExpressionRunner( module, @@ -106,7 +74,7 @@ : FlagValues::DEFAULT, MAX_DEPTH, MAX_LOOP_ITERATIONS), - getValues(getValues), heapValues(heapValues) {} + getValues(getValues) {} Flow visitLocalGet(LocalGet* curr) { auto iter = getValues.find(curr); @@ -119,79 +87,6 @@ return ConstantExpressionRunner< PrecomputingExpressionRunner>::visitLocalGet(curr); } - - // TODO: Use immutability for values - Flow visitStructNew(StructNew* curr) { - auto flow = Super::visitStructNew(curr); - if (flow.breaking()) { - return flow; - } - return getHeapCreationFlow(flow, curr); - } - Flow visitStructSet(StructSet* curr) { return Flow(NONCONSTANT_FLOW); } - Flow visitStructGet(StructGet* curr) { - if (curr->ref->type != Type::unreachable) { - // If this field is immutable then we may be able to precompute this, as - // if we also created the data in this function (or it was created in an - // immutable global) then we know the value in the field. If it is - // immutable, call the super method which will do the rest here. That - // includes checking for the data being properly created, as if it was - // not then we will not have a constant value for it, which means the - // local.get of that value will stop us. - auto& field = - curr->ref->type.getHeapType().getStruct().fields[curr->index]; - if (field.mutable_ == Immutable) { - return Super::visitStructGet(curr); - } - } - - // Otherwise, we've failed to precompute. - return Flow(NONCONSTANT_FLOW); - } - Flow visitArrayNew(ArrayNew* curr) { - auto flow = Super::visitArrayNew(curr); - if (flow.breaking()) { - return flow; - } - return getHeapCreationFlow(flow, curr); - } - Flow visitArrayInit(ArrayInit* curr) { - auto flow = Super::visitArrayInit(curr); - if (flow.breaking()) { - return flow; - } - return getHeapCreationFlow(flow, curr); - } - Flow visitArraySet(ArraySet* curr) { return Flow(NONCONSTANT_FLOW); } - Flow visitArrayGet(ArrayGet* curr) { - if (curr->ref->type != Type::unreachable) { - // See above with struct.get - auto element = curr->ref->type.getHeapType().getArray().element; - if (element.mutable_ == Immutable) { - return Super::visitArrayGet(curr); - } - } - - // Otherwise, we've failed to precompute. - return Flow(NONCONSTANT_FLOW); - } - Flow visitArrayLen(ArrayLen* curr) { return Flow(NONCONSTANT_FLOW); } - Flow visitArrayCopy(ArrayCopy* curr) { return Flow(NONCONSTANT_FLOW); } - - // Generates heap info for a heap-allocating expression. - template Flow getHeapCreationFlow(Flow flow, T* curr) { - // We must return a literal that refers to the canonical location for this - // source expression, so that each time we compute a specific struct.new - // we get the same identity. - std::shared_ptr& canonical = heapValues[curr]; - std::shared_ptr newGCData = flow.getSingleValue().getGCData(); - if (!canonical) { - canonical = std::make_shared(*newGCData); - } else { - *canonical = *newGCData; - } - return Literal(canonical, curr->type); - } }; struct Precompute @@ -206,29 +101,25 @@ Precompute(bool propagate) : propagate(propagate) {} GetValues getValues; - HeapValues heapValues; + + bool worked; void doWalkFunction(Function* func) { - // Walk the function and precompute things. - super::doWalkFunction(func); - if (!propagate) { - return; - } - // When propagating, we can utilize the graph of local operations to - // precompute the values from a local.set to a local.get. This populates - // getValues which is then used by a subsequent walk that applies those - // values. - bool propagated = propagateLocals(func); - if (propagated) { - // We found constants to propagate and entered them in getValues. Do - // another walk to apply them and perhaps other optimizations that are - // unlocked. + // if propagating, we may need multiple rounds: each propagation can + // lead to the main walk removing code, which might open up more + // propagation opportunities + do { + getValues.clear(); + // with extra effort, we can utilize the get-set graph to precompute + // things that use locals that are known to be constant. otherwise, + // we just look at what is immediately before us + if (propagate) { + optimizeLocals(func); + } + // do the main walk over everything + worked = false; super::doWalkFunction(func); - } - // Note that in principle even more cycles could find further work here, in - // very rare cases. To avoid constructing a LocalGraph again just for that - // unlikely chance, we leave such things for later runs of this pass and for - // --converge. + } while (propagate && worked); } template void reuseConstantNode(T* curr, Flow flow) { @@ -271,15 +162,24 @@ if (Properties::isConstantExpression(curr) || curr->is()) { return; } + // Until engines implement v128.const and we have SIMD-aware optimizations + // that can break large v128.const instructions into smaller consts and + // splats, do not try to precompute v128 expressions. + if (curr->type.isVector()) { + return; + } // try to evaluate this into a const Flow flow = precomputeExpression(curr); - if (!canEmitConstantFor(flow.values)) { + if (flow.getType().hasVector()) { return; } if (flow.breaking()) { if (flow.breakTo == NONCONSTANT_FLOW) { return; } + if (!canEmitConstantFor(flow.values)) { + return; + } if (flow.breakTo == RETURN_FLOW) { // this expression causes a return. if it's already a return, reuse the // node @@ -311,6 +211,7 @@ // this was precomputed if (flow.values.isConcrete()) { replaceCurrent(flow.getConstExpression(*getModule())); + worked = true; } else { ExpressionManipulator::nop(curr); } @@ -325,21 +226,16 @@ // Precompute an expression, returning a flow, which may be a constant // (that we can replace the expression with if replaceExpression is set). Flow precomputeExpression(Expression* curr, bool replaceExpression = true) { - Flow flow; - try { - flow = PrecomputingExpressionRunner( - getModule(), getValues, heapValues, replaceExpression) - .visit(curr); - } catch (PrecomputingExpressionRunner::NonconstantException&) { + if (!canEmitConstantFor(curr->type)) { return Flow(NONCONSTANT_FLOW); } - // If we are replacing the expression, then the resulting value must be of - // a type we can emit a constant for. - if (!flow.breaking() && replaceExpression && - !canEmitConstantFor(flow.values)) { + try { + return PrecomputingExpressionRunner( + getModule(), getValues, replaceExpression) + .visit(curr); + } catch (PrecomputingExpressionRunner::NonconstantException&) { return Flow(NONCONSTANT_FLOW); } - return flow; } // Precomputes the value of an expression, as opposed to the expression @@ -360,8 +256,7 @@ } // Propagates values around. Returns whether we propagated. - bool propagateLocals(Function* func) { - bool propagated = false; + void optimizeLocals(Function* func) { // using the graph of get-set interactions, do a constant-propagation type // operation: note which sets are assigned locals, then see if that lets us // compute other sets as locals (since some of the gets they read may be @@ -369,17 +264,21 @@ // compute all dependencies LocalGraph localGraph(func); localGraph.computeInfluences(); + localGraph.computeSSAIndexes(); // prepare the work list. we add things here that might change to a constant // initially, that means everything - UniqueDeferredQueue work; - for (auto& [curr, _] : localGraph.locations) { - work.push(curr); + std::unordered_set work; + for (auto& pair : localGraph.locations) { + auto* curr = pair.first; + work.insert(curr); } // the constant value, or none if not a constant std::unordered_map setValues; // propagate constant values while (!work.empty()) { - auto* curr = work.pop(); + auto iter = work.begin(); + auto* curr = *iter; + work.erase(iter); // see if this set or get is actually a constant value, and if so, // mark it as such and add everything it influences to the work list, // as they may be constant too. @@ -387,42 +286,12 @@ if (setValues[set].isConcrete()) { continue; // already known constant } - // Precompute the value. Note that this executes the code from scratch - // each time we reach this point, and so we need to be careful about - // repeating side effects if those side effects are expressed *in the - // value*. A case where that can happen is GC data (each struct.new - // creates a new, unique struct, even if the data is equal), and so - // PrecomputingExpressionRunner has special logic to make sure that - // reference identity is preserved properly. - // - // (Other side effects are fine; if an expression does a call and we - // somehow know the entire expression precomputes to a 42, then we can - // propagate that 42 along to the users, regardless of whatever the call - // did globally.) - auto values = precomputeValue(Properties::getFallthrough( - set->value, getPassOptions(), *getModule())); - // Fix up the value. The computation we just did was to look at the - // fallthrough, then precompute that; that looks through expressions - // that pass through the value. Normally that does not matter here, - // for example, (block .. (value)) returns the value unmodified. - // However, some things change the type, for example RefAsNonNull has - // a non-null type, while its input may be nullable. That does not - // matter either, as if we managed to precompute it then the value had - // the more specific (in this example, non-nullable) type. But there - // is a situation where this can cause an issue: RefCast. An attempt to - // perform a "bad" cast, say of a function to a struct, is a case where - // the fallthrough value's type is very different than the actually - // returned value's type. To handle that, if we precomputed a value and - // if it has the wrong type then precompute it again without looking - // through to the fallthrough. - if (values.isConcrete() && - !Type::isSubType(values.getType(), set->value->type)) { - values = precomputeValue(set->value); - } - setValues[set] = values; + auto values = setValues[set] = + precomputeValue(Properties::getFallthrough( + set->value, getPassOptions(), getModule()->features)); if (values.isConcrete()) { for (auto* get : localGraph.setInfluences[set]) { - work.push(get); + work.insert(get); } } } else { @@ -437,12 +306,8 @@ Literals curr; if (set == nullptr) { if (getFunction()->isVar(get->index)) { - auto localType = getFunction()->getLocalType(get->index); - if (localType.isNonNullable()) { - Fatal() << "Non-nullable local accessing the default value in " - << getFunction()->name << " (" << get->index << ')'; - } - curr = Literal::makeZeros(localType); + curr = + Literal::makeZeros(getFunction()->getLocalType(get->index)); } else { // it's a param, so it's hopeless values = {}; @@ -473,13 +338,11 @@ // we did! getValues[get] = values; for (auto* set : localGraph.getInfluences[get]) { - work.push(set); + work.insert(set); } - propagated = true; } } } - return propagated; } bool canEmitConstantFor(const Literals& values) { @@ -497,25 +360,20 @@ if (value.isNull()) { return true; } - return canEmitConstantFor(value.type); - } - - bool canEmitConstantFor(Type type) { // A function is fine to emit a constant for - we'll emit a RefFunc, which // is compact and immutable, so there can't be a problem. - if (type.isFunction()) { + if (value.type.isFunction()) { return true; } - // All other reference types cannot be precomputed. Even an immutable GC - // reference is not currently something this pass can handle, as it will - // evaluate and reevaluate code multiple times in e.g. propagateLocals, see - // the comment above. - if (type.isRef()) { - return false; - } + return canEmitConstantFor(value.type); + } + + bool canEmitConstantFor(Type type) { + // Don't try to precompute a reference. We can't replace it with a constant + // expression, as that would make a copy of it by value. // For now, don't try to precompute an Rtt. TODO figure out when that would // be safe and useful. - return !type.isRtt(); + return !type.isRef() && !type.isRtt(); } }; diff -Nru binaryen-108/src/passes/PrintCallGraph.cpp binaryen-99/src/passes/PrintCallGraph.cpp --- binaryen-108/src/passes/PrintCallGraph.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/PrintCallGraph.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,6 @@ #include #include -#include "ir/element-utils.h" #include "ir/module-utils.h" #include "ir/utils.h" #include "pass.h" @@ -86,9 +85,10 @@ } void visitCall(Call* curr) { auto* target = module->getFunction(curr->target); - if (!visitedTargets.emplace(target->name).second) { + if (visitedTargets.count(target->name) > 0) { return; } + visitedTargets.insert(target->name); std::cout << " \"" << currFunction->name << "\" -> \"" << target->name << "\"; // call\n"; } @@ -96,10 +96,12 @@ CallPrinter printer(module); // Indirect Targets - ElementUtils::iterAllElementFunctionNames(module, [&](Name& name) { - auto* func = module->getFunction(name); - o << " \"" << func->name << "\" [style=\"filled, rounded\"];\n"; - }); + for (auto& segment : module->table.segments) { + for (auto& curr : segment.data) { + auto* func = module->getFunction(curr); + o << " \"" << func->name << "\" [style=\"filled, rounded\"];\n"; + } + } o << "}\n"; } diff -Nru binaryen-108/src/passes/Print.cpp binaryen-99/src/passes/Print.cpp --- binaryen-108/src/passes/Print.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Print.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -18,9 +18,7 @@ // Print out text in s-expression format // -#include #include -#include #include #include #include @@ -31,8 +29,7 @@ static std::ostream& printExpression(Expression* expression, std::ostream& o, bool minify = false, - bool full = false, - Module* wasm = nullptr); + bool full = false); static std::ostream& printStackInst(StackInst* inst, std::ostream& o, Function* func = nullptr); @@ -70,134 +67,47 @@ return printName(name, o); } -namespace { - -// Helper for printing the name of a type. This output is guaranteed to not -// contain spaces. -struct TypeNamePrinter { - // Optional. If present, the module's HeapType names will be used. - Module* wasm; - - // Keep track of the first depth at which we see each HeapType so if we see it - // again, we can unambiguously refer to it without infinitely recursing. - size_t currHeapTypeDepth = 0; - std::unordered_map heapTypeDepths; - - // The stream we are printing to. - std::ostream& os; - - TypeNamePrinter(std::ostream& os, Module* wasm = nullptr) - : wasm(wasm), os(os) {} - - void print(Type type); - void print(HeapType heapType); - void print(const Tuple& tuple); - void print(const Field& field); - void print(const Signature& sig); - void print(const Struct& struct_); - void print(const Array& array); - void print(const Rtt& rtt); - - // FIXME: This hard limit on how many times we call print() avoids extremely - // large outputs, which can be inconveniently large in some cases, but - // we should have a better mechanism for this. - static const size_t MaxPrints = 100; - - size_t prints = 0; - - bool exceededLimit() { - if (prints >= MaxPrints) { - os << "?"; - return true; - } - prints++; - return false; - } -}; +static void +printHeapTypeName(std::ostream& os, HeapType type, bool first = true); -void TypeNamePrinter::print(Type type) { - if (exceededLimit()) { - return; - } +// Prints the name of a type. This output is guaranteed to not contain spaces. +static void printTypeName(std::ostream& os, Type type) { if (type.isBasic()) { os << type; - } else if (type.isTuple()) { - print(type.getTuple()); - } else if (type.isRtt()) { - print(type.getRtt()); - } else if (type.isRef()) { - os << "ref"; - if (type.isNullable()) { - os << "?"; - } - os << '|'; - print(type.getHeapType()); - os << '|'; - } else { - WASM_UNREACHABLE("unexpected type"); - } -} - -void TypeNamePrinter::print(HeapType type) { - if (exceededLimit()) { return; } - if (type.isBasic()) { - os << type; + if (type.isRtt()) { + auto rtt = type.getRtt(); + os << "rtt_"; + if (rtt.hasDepth()) { + os << rtt.depth << '_'; + } + printHeapTypeName(os, rtt.heapType); return; } - // If there is a name for this type in this module, use it. - // FIXME: in theory there could be two types, one with a name, and one - // without, and the one without gets an automatic name that matches the - // other's. To check for that, if (first) we could assert at the very end of - // this function that the automatic name is not present in the given names. - if (wasm && wasm->typeNames.count(type)) { - os << '$' << wasm->typeNames[type].name; + if (type.isTuple()) { + auto sep = ""; + for (auto t : type) { + os << sep; + sep = "_"; + printTypeName(os, t); + } return; } - // If we have seen this HeapType before, just print its relative depth instead - // of infinitely recursing. - auto it = heapTypeDepths.find(type); - if (it != heapTypeDepths.end()) { - assert(it->second <= currHeapTypeDepth); - size_t relativeDepth = currHeapTypeDepth - it->second; - os << "..." << relativeDepth; + if (type.isRef()) { + os << "ref"; + if (type.isNullable()) { + os << "?"; + } + os << "|"; + printHeapTypeName(os, type.getHeapType(), false); + os << "|"; return; } - - // If this is the top-level heap type, add a $ - if (currHeapTypeDepth == 0) { - os << "$"; - } - - // Update the context for the current HeapType before recursing. - heapTypeDepths[type] = ++currHeapTypeDepth; - - if (type.isSignature()) { - print(type.getSignature()); - } else if (type.isStruct()) { - print(type.getStruct()); - } else if (type.isArray()) { - print(type.getArray()); - } else { - WASM_UNREACHABLE("unexpected type"); - } - - // Restore the previous context after the recursion. - heapTypeDepths.erase(type); - --currHeapTypeDepth; -} - -void TypeNamePrinter::print(const Tuple& tuple) { - auto sep = ""; - for (auto type : tuple.types) { - os << sep; - sep = "_"; - print(type); - } + WASM_UNREACHABLE("unsupported print type"); } -void TypeNamePrinter::print(const Field& field) { +static void printFieldName(std::ostream& os, const Field& field) { if (field.mutable_) { os << "mut:"; } @@ -210,58 +120,62 @@ WASM_UNREACHABLE("invalid packed type"); } } else { - print(field.type); + printTypeName(os, field.type); } } -void TypeNamePrinter::print(const Signature& sig) { - // TODO: Switch to using an unambiguous delimiter rather than differentiating - // only the top level with a different arrow. - print(sig.params); - if (currHeapTypeDepth == 1) { - os << "_=>_"; - } else { - os << "_->_"; +// Prints the name of a heap type. As with printTypeName, this output is +// guaranteed to not contain spaces. +static void printHeapTypeName(std::ostream& os, HeapType type, bool first) { + if (type.isBasic()) { + os << type; + return; } - print(sig.results); -} - -void TypeNamePrinter::print(const Struct& struct_) { - os << '{'; - auto sep = ""; - for (const auto& field : struct_.fields) { - os << sep; - sep = "_"; - print(field); + if (first) { + os << '$'; } - os << '}'; -} - -void TypeNamePrinter::print(const Array& array) { - os << '['; - print(array.element); - os << ']'; -} - -void TypeNamePrinter::print(const Rtt& rtt) { - os << "rtt_"; - if (rtt.hasDepth()) { - os << rtt.depth << '_'; + if (type.isSignature()) { + auto sig = type.getSignature(); + printTypeName(os, sig.params); + if (first) { + os << "_=>_"; + } else { + os << "_->_"; + } + printTypeName(os, sig.results); + } else if (type.isStruct()) { + auto struct_ = type.getStruct(); + os << "{"; + auto sep = ""; + for (auto& field : struct_.fields) { + os << sep; + sep = "_"; + printFieldName(os, field); + } + os << "}"; + } else if (type.isArray()) { + os << "["; + printFieldName(os, type.getArray().element); + os << "]"; + } else { + os << type; } - print(rtt.heapType); } -} // anonymous namespace +// Unlike the default format, tuple types in s-expressions should not have +// commas. +struct SExprType { + Type type; + SExprType(Type type) : type(type){}; +}; -static std::ostream& printType(std::ostream& o, Type type, Module* wasm) { - if (type.isBasic()) { - o << type; - } else if (type.isTuple()) { +static std::ostream& operator<<(std::ostream& o, const SExprType& sType) { + Type type = sType.type; + if (type.isTuple()) { o << '('; auto sep = ""; for (const auto& t : type) { - o << sep; - printType(o, t, wasm); + o << sep << t; sep = " "; } o << ')'; @@ -271,77 +185,45 @@ if (rtt.hasDepth()) { o << rtt.depth << ' '; } - TypeNamePrinter(o, wasm).print(rtt.heapType); + printHeapTypeName(o, rtt.heapType); o << ')'; } else if (type.isRef() && !type.isBasic()) { o << "(ref "; if (type.isNullable()) { o << "null "; } - TypeNamePrinter(o, wasm).print(type.getHeapType()); + printHeapTypeName(o, type.getHeapType()); o << ')'; } else { - WASM_UNREACHABLE("unexpected type"); + printTypeName(o, sType.type); } return o; } -static std::ostream& -printHeapType(std::ostream& o, HeapType type, Module* wasm) { - TypeNamePrinter(o, wasm).print(type); - return o; -} +// TODO: try to simplify or even remove this, as we may be able to do the same +// things with SExprType +struct ResultTypeName { + Type type; + ResultTypeName(Type type) : type(type) {} +}; -static std::ostream& printPrefixedTypes(std::ostream& o, - const char* prefix, - Type type, - Module* wasm) { - o << '(' << prefix; - if (type == Type::none) { - return o << ')'; - } +std::ostream& operator<<(std::ostream& os, ResultTypeName typeName) { + auto type = typeName.type; + os << "(result "; if (type.isTuple()) { // Tuple types are not printed in parens, we can just emit them one after // the other in the same list as the "result". + auto sep = ""; for (auto t : type) { - o << ' '; - printType(o, t, wasm); + os << sep; + sep = " "; + os << SExprType(t); } } else { - o << ' '; - printType(o, type, wasm); - } - o << ')'; - return o; -} - -static std::ostream& printResultType(std::ostream& o, Type type, Module* wasm) { - return printPrefixedTypes(o, "result", type, wasm); -} - -static std::ostream& printParamType(std::ostream& o, Type type, Module* wasm) { - return printPrefixedTypes(o, "param", type, wasm); -} - -// Generic processing of a struct's field, given an optional module. Calls func -// with the field name, if it is present, or with a null Name if not. -template -void processFieldName(Module* wasm, HeapType type, Index index, T func) { - if (wasm) { - auto it = wasm->typeNames.find(type); - if (it != wasm->typeNames.end()) { - auto& fieldNames = it->second.fieldNames; - auto it = fieldNames.find(index); - if (it != fieldNames.end()) { - auto name = it->second; - if (name.is()) { - func(it->second); - return; - } - } - } + os << SExprType(type); } - func(Name()); + os << ')'; + return os; } } // anonymous namespace @@ -356,16 +238,11 @@ // the children. struct PrintExpressionContents : public OverriddenVisitor { - Module* wasm = nullptr; Function* currFunction = nullptr; std::ostream& o; - FeatureSet features; - - PrintExpressionContents(Module* wasm, Function* currFunction, std::ostream& o) - : wasm(wasm), currFunction(currFunction), o(o), features(wasm->features) {} PrintExpressionContents(Function* currFunction, std::ostream& o) - : currFunction(currFunction), o(o), features(FeatureSet::All) {} + : currFunction(currFunction), o(o) {} void visitBlock(Block* curr) { printMedium(o, "block"); @@ -374,15 +251,13 @@ printName(curr->name, o); } if (curr->type.isConcrete()) { - o << ' '; - printResultType(o, curr->type, wasm); + o << ' ' << ResultTypeName(curr->type); } } void visitIf(If* curr) { printMedium(o, "if"); if (curr->type.isConcrete()) { - o << ' '; - printResultType(o, curr->type, wasm); + o << ' ' << ResultTypeName(curr->type); } } void visitLoop(Loop* curr) { @@ -392,8 +267,7 @@ printName(curr->name, o); } if (curr->type.isConcrete()) { - o << ' '; - printResultType(o, curr->type, wasm); + o << ' ' << ResultTypeName(curr->type); } } void visitBreak(Break* curr) { @@ -423,21 +297,11 @@ } void visitCallIndirect(CallIndirect* curr) { if (curr->isReturn) { - printMedium(o, "return_call_indirect "); + printMedium(o, "return_call_indirect (type "); } else { - printMedium(o, "call_indirect "); + printMedium(o, "call_indirect (type "); } - - if (features.hasReferenceTypes()) { - printName(curr->table, o); - o << ' '; - } - - o << '('; - printMinor(o, "type "); - - TypeNamePrinter(o, wasm).print(curr->heapType); - + printHeapTypeName(o, curr->sig); o << ')'; } void visitLocalGet(LocalGet* curr) { @@ -577,7 +441,6 @@ Type type = forceConcrete(curr->expectedType); assert(type == Type::i32 || type == Type::i64); o << "memory.atomic.wait" << (type == Type::i32 ? "32" : "64"); - restoreNormalColor(o); if (curr->offset) { o << " offset=" << curr->offset; } @@ -617,7 +480,6 @@ o << "f64x2.extract_lane"; break; } - restoreNormalColor(o); o << " " << int(curr->index); } void visitSIMDReplace(SIMDReplace* curr) { @@ -642,13 +504,11 @@ o << "f64x2.replace_lane"; break; } - restoreNormalColor(o); o << " " << int(curr->index); } void visitSIMDShuffle(SIMDShuffle* curr) { prepareColor(o); - o << "i8x16.shuffle"; - restoreNormalColor(o); + o << "v8x16.shuffle"; for (uint8_t mask_index : curr->mask) { o << " " << std::to_string(mask_index); } @@ -659,38 +519,31 @@ case Bitselect: o << "v128.bitselect"; break; - case LaneselectI8x16: - o << "i8x16.laneselect"; - break; - case LaneselectI16x8: - o << "i16x8.laneselect"; + case QFMAF32x4: + o << "f32x4.qfma"; break; - case LaneselectI32x4: - o << "i32x4.laneselect"; + case QFMSF32x4: + o << "f32x4.qfms"; break; - case LaneselectI64x2: - o << "i64x2.laneselect"; + case QFMAF64x2: + o << "f64x2.qfma"; break; - case RelaxedFmaVecF32x4: - o << "f32x4.relaxed_fma"; + case QFMSF64x2: + o << "f64x2.qfms"; break; - case RelaxedFmsVecF32x4: - o << "f32x4.relaxed_fms"; + case SignSelectVec8x16: + o << "v8x16.signselect"; break; - case RelaxedFmaVecF64x2: - o << "f64x2.relaxed_fma"; + case SignSelectVec16x8: + o << "v16x8.signselect"; break; - case RelaxedFmsVecF64x2: - o << "f64x2.relaxed_fms"; + case SignSelectVec32x4: + o << "v32x4.signselect"; break; - case DotI8x16I7x16AddSToVecI32x4: - o << "i32x4.dot_i8x16_i7x16_add_s"; - break; - case DotI8x16I7x16AddUToVecI32x4: - o << "i32x4.dot_i8x16_i7x16_add_u"; + case SignSelectVec64x2: + o << "v64x2.signselect"; break; } - restoreNormalColor(o); } void visitSIMDShift(SIMDShift* curr) { prepareColor(o); @@ -732,45 +585,44 @@ o << "i64x2.shr_u"; break; } - restoreNormalColor(o); } void visitSIMDLoad(SIMDLoad* curr) { prepareColor(o); switch (curr->op) { - case Load8SplatVec128: - o << "v128.load8_splat"; + case LoadSplatVec8x16: + o << "v8x16.load_splat"; break; - case Load16SplatVec128: - o << "v128.load16_splat"; + case LoadSplatVec16x8: + o << "v16x8.load_splat"; break; - case Load32SplatVec128: - o << "v128.load32_splat"; + case LoadSplatVec32x4: + o << "v32x4.load_splat"; break; - case Load64SplatVec128: - o << "v128.load64_splat"; + case LoadSplatVec64x2: + o << "v64x2.load_splat"; break; - case Load8x8SVec128: - o << "v128.load8x8_s"; + case LoadExtSVec8x8ToVecI16x8: + o << "i16x8.load8x8_s"; break; - case Load8x8UVec128: - o << "v128.load8x8_u"; + case LoadExtUVec8x8ToVecI16x8: + o << "i16x8.load8x8_u"; break; - case Load16x4SVec128: - o << "v128.load16x4_s"; + case LoadExtSVec16x4ToVecI32x4: + o << "i32x4.load16x4_s"; break; - case Load16x4UVec128: - o << "v128.load16x4_u"; + case LoadExtUVec16x4ToVecI32x4: + o << "i32x4.load16x4_u"; break; - case Load32x2SVec128: - o << "v128.load32x2_s"; + case LoadExtSVec32x2ToVecI64x2: + o << "i64x2.load32x2_s"; break; - case Load32x2UVec128: - o << "v128.load32x2_u"; + case LoadExtUVec32x2ToVecI64x2: + o << "i64x2.load32x2_u"; break; - case Load32ZeroVec128: + case Load32Zero: o << "v128.load32_zero"; break; - case Load64ZeroVec128: + case Load64Zero: o << "v128.load64_zero"; break; } @@ -785,28 +637,28 @@ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { prepareColor(o); switch (curr->op) { - case Load8LaneVec128: + case LoadLaneVec8x16: o << "v128.load8_lane"; break; - case Load16LaneVec128: + case LoadLaneVec16x8: o << "v128.load16_lane"; break; - case Load32LaneVec128: + case LoadLaneVec32x4: o << "v128.load32_lane"; break; - case Load64LaneVec128: + case LoadLaneVec64x2: o << "v128.load64_lane"; break; - case Store8LaneVec128: + case StoreLaneVec8x16: o << "v128.store8_lane"; break; - case Store16LaneVec128: + case StoreLaneVec16x8: o << "v128.store16_lane"; break; - case Store32LaneVec128: + case StoreLaneVec32x4: o << "v128.store32_lane"; break; - case Store64LaneVec128: + case StoreLaneVec64x2: o << "v128.store64_lane"; break; } @@ -819,27 +671,39 @@ } o << " " << int(curr->index); } - void visitMemoryInit(MemoryInit* curr) { + void visitPrefetch(Prefetch* curr) { prepareColor(o); - o << "memory.init"; + switch (curr->op) { + case PrefetchTemporal: + o << "prefetch.t"; + break; + case PrefetchNontemporal: + o << "prefetch.nt"; + break; + } restoreNormalColor(o); - o << ' ' << curr->segment; + if (curr->offset) { + o << " offset=" << curr->offset; + } + if (curr->align != 1) { + o << " align=" << curr->align; + } + } + void visitMemoryInit(MemoryInit* curr) { + prepareColor(o); + o << "memory.init " << curr->segment; } void visitDataDrop(DataDrop* curr) { prepareColor(o); - o << "data.drop"; - restoreNormalColor(o); - o << ' ' << curr->segment; + o << "data.drop " << curr->segment; } void visitMemoryCopy(MemoryCopy* curr) { prepareColor(o); o << "memory.copy"; - restoreNormalColor(o); } void visitMemoryFill(MemoryFill* curr) { prepareColor(o); o << "memory.fill"; - restoreNormalColor(o); } void visitConst(Const* curr) { o << curr->value.type << ".const " << curr->value; @@ -1048,15 +912,15 @@ case NotVec128: o << "v128.not"; break; - case AnyTrueVec128: - o << "v128.any_true"; - break; case AbsVecI8x16: o << "i8x16.abs"; break; case NegVecI8x16: o << "i8x16.neg"; break; + case AnyTrueVecI8x16: + o << "i8x16.any_true"; + break; case AllTrueVecI8x16: o << "i8x16.all_true"; break; @@ -1072,6 +936,9 @@ case NegVecI16x8: o << "i16x8.neg"; break; + case AnyTrueVecI16x8: + o << "i16x8.any_true"; + break; case AllTrueVecI16x8: o << "i16x8.all_true"; break; @@ -1084,21 +951,18 @@ case NegVecI32x4: o << "i32x4.neg"; break; + case AnyTrueVecI32x4: + o << "i32x4.any_true"; + break; case AllTrueVecI32x4: o << "i32x4.all_true"; break; case BitmaskVecI32x4: o << "i32x4.bitmask"; break; - case AbsVecI64x2: - o << "i64x2.abs"; - break; case NegVecI64x2: o << "i64x2.neg"; break; - case AllTrueVecI64x2: - o << "i64x2.all_true"; - break; case BitmaskVecI64x2: o << "i64x2.bitmask"; break; @@ -1162,82 +1026,63 @@ case TruncSatUVecF32x4ToVecI32x4: o << "i32x4.trunc_sat_f32x4_u"; break; + case TruncSatSVecF64x2ToVecI64x2: + o << "i64x2.trunc_sat_f64x2_s"; + break; + case TruncSatUVecF64x2ToVecI64x2: + o << "i64x2.trunc_sat_f64x2_u"; + break; case ConvertSVecI32x4ToVecF32x4: o << "f32x4.convert_i32x4_s"; break; case ConvertUVecI32x4ToVecF32x4: o << "f32x4.convert_i32x4_u"; break; - case ExtendLowSVecI8x16ToVecI16x8: - o << "i16x8.extend_low_i8x16_s"; - break; - case ExtendHighSVecI8x16ToVecI16x8: - o << "i16x8.extend_high_i8x16_s"; - break; - case ExtendLowUVecI8x16ToVecI16x8: - o << "i16x8.extend_low_i8x16_u"; - break; - case ExtendHighUVecI8x16ToVecI16x8: - o << "i16x8.extend_high_i8x16_u"; - break; - case ExtendLowSVecI16x8ToVecI32x4: - o << "i32x4.extend_low_i16x8_s"; - break; - case ExtendHighSVecI16x8ToVecI32x4: - o << "i32x4.extend_high_i16x8_s"; + case ConvertSVecI64x2ToVecF64x2: + o << "f64x2.convert_i64x2_s"; break; - case ExtendLowUVecI16x8ToVecI32x4: - o << "i32x4.extend_low_i16x8_u"; + case ConvertUVecI64x2ToVecF64x2: + o << "f64x2.convert_i64x2_u"; break; - case ExtendHighUVecI16x8ToVecI32x4: - o << "i32x4.extend_high_i16x8_u"; + case WidenLowSVecI8x16ToVecI16x8: + o << "i16x8.widen_low_i8x16_s"; break; - case ExtendLowSVecI32x4ToVecI64x2: - o << "i64x2.extend_low_i32x4_s"; + case WidenHighSVecI8x16ToVecI16x8: + o << "i16x8.widen_high_i8x16_s"; break; - case ExtendHighSVecI32x4ToVecI64x2: - o << "i64x2.extend_high_i32x4_s"; + case WidenLowUVecI8x16ToVecI16x8: + o << "i16x8.widen_low_i8x16_u"; break; - case ExtendLowUVecI32x4ToVecI64x2: - o << "i64x2.extend_low_i32x4_u"; + case WidenHighUVecI8x16ToVecI16x8: + o << "i16x8.widen_high_i8x16_u"; break; - case ExtendHighUVecI32x4ToVecI64x2: - o << "i64x2.extend_high_i32x4_u"; + case WidenLowSVecI16x8ToVecI32x4: + o << "i32x4.widen_low_i16x8_s"; break; - case ConvertLowSVecI32x4ToVecF64x2: - o << "f64x2.convert_low_i32x4_s"; + case WidenHighSVecI16x8ToVecI32x4: + o << "i32x4.widen_high_i16x8_s"; break; - case ConvertLowUVecI32x4ToVecF64x2: - o << "f64x2.convert_low_i32x4_u"; + case WidenLowUVecI16x8ToVecI32x4: + o << "i32x4.widen_low_i16x8_u"; break; - case TruncSatZeroSVecF64x2ToVecI32x4: - o << "i32x4.trunc_sat_f64x2_s_zero"; + case WidenHighUVecI16x8ToVecI32x4: + o << "i32x4.widen_high_i16x8_u"; break; - case TruncSatZeroUVecF64x2ToVecI32x4: - o << "i32x4.trunc_sat_f64x2_u_zero"; + case WidenLowSVecI32x4ToVecI64x2: + o << "i64x2.widen_low_i32x4_s"; break; - case DemoteZeroVecF64x2ToVecF32x4: - o << "f32x4.demote_f64x2_zero"; + case WidenHighSVecI32x4ToVecI64x2: + o << "i64x2.widen_high_i32x4_s"; break; - case PromoteLowVecF32x4ToVecF64x2: - o << "f64x2.promote_low_f32x4"; + case WidenLowUVecI32x4ToVecI64x2: + o << "i64x2.widen_low_i32x4_u"; break; - case RelaxedTruncSVecF32x4ToVecI32x4: - o << "i32x4.relaxed_trunc_f32x4_s"; - break; - case RelaxedTruncUVecF32x4ToVecI32x4: - o << "i32x4.relaxed_trunc_f32x4_u"; - break; - case RelaxedTruncZeroSVecF64x2ToVecI32x4: - o << "i32x4.relaxed_trunc_f64x2_s_zero"; - break; - case RelaxedTruncZeroUVecF64x2ToVecI32x4: - o << "i32x4.relaxed_trunc_f64x2_u_zero"; + case WidenHighUVecI32x4ToVecI64x2: + o << "i64x2.widen_high_i32x4_u"; break; case InvalidUnary: WASM_UNREACHABLE("unvalid unary operator"); } - restoreNormalColor(o); } void visitBinary(Binary* curr) { prepareColor(o); @@ -1567,21 +1412,6 @@ case EqVecI64x2: o << "i64x2.eq"; break; - case NeVecI64x2: - o << "i64x2.ne"; - break; - case LtSVecI64x2: - o << "i64x2.lt_s"; - break; - case GtSVecI64x2: - o << "i64x2.gt_s"; - break; - case LeSVecI64x2: - o << "i64x2.le_s"; - break; - case GeSVecI64x2: - o << "i64x2.ge_s"; - break; case EqVecF32x4: o << "f32x4.eq"; break; @@ -1636,19 +1466,22 @@ o << "i8x16.add"; break; case AddSatSVecI8x16: - o << "i8x16.add_sat_s"; + o << "i8x16.add_saturate_s"; break; case AddSatUVecI8x16: - o << "i8x16.add_sat_u"; + o << "i8x16.add_saturate_u"; break; case SubVecI8x16: o << "i8x16.sub"; break; case SubSatSVecI8x16: - o << "i8x16.sub_sat_s"; + o << "i8x16.sub_saturate_s"; break; case SubSatUVecI8x16: - o << "i8x16.sub_sat_u"; + o << "i8x16.sub_saturate_u"; + break; + case MulVecI8x16: + o << "i8x16.mul"; break; case MinSVecI8x16: o << "i8x16.min_s"; @@ -1669,19 +1502,19 @@ o << "i16x8.add"; break; case AddSatSVecI16x8: - o << "i16x8.add_sat_s"; + o << "i16x8.add_saturate_s"; break; case AddSatUVecI16x8: - o << "i16x8.add_sat_u"; + o << "i16x8.add_saturate_u"; break; case SubVecI16x8: o << "i16x8.sub"; break; case SubSatSVecI16x8: - o << "i16x8.sub_sat_s"; + o << "i16x8.sub_saturate_s"; break; case SubSatUVecI16x8: - o << "i16x8.sub_sat_u"; + o << "i16x8.sub_saturate_u"; break; case MulVecI16x8: o << "i16x8.mul"; @@ -1838,33 +1671,8 @@ o << "i16x8.narrow_i32x4_u"; break; - case SwizzleVecI8x16: - o << "i8x16.swizzle"; - break; - - case RelaxedMinVecF32x4: - o << "f32x4.relaxed_min"; - break; - case RelaxedMaxVecF32x4: - o << "f32x4.relaxed_max"; - break; - case RelaxedMinVecF64x2: - o << "f64x2.relaxed_min"; - break; - case RelaxedMaxVecF64x2: - o << "f64x2.relaxed_max"; - break; - case RelaxedSwizzleVecI8x16: - o << "i8x16.relaxed_swizzle"; - break; - case RelaxedQ15MulrSVecI16x8: - o << "i16x8.relaxed_q15mulr_s"; - break; - case DotI8x16I7x16SToVecI16x8: - o << "i16x8.dot_i8x16_i7x16_s"; - break; - case DotI8x16I7x16UToVecI16x8: - o << "i16x8.dot_i8x16_i7x16_u"; + case SwizzleVec8x16: + o << "v8x16.swizzle"; break; case InvalidBinary: @@ -1874,10 +1682,8 @@ } void visitSelect(Select* curr) { prepareColor(o) << "select"; - restoreNormalColor(o); if (curr->type.isRef()) { - o << ' '; - printResultType(o, curr->type, wasm); + o << ' ' << ResultTypeName(curr->type); } } void visitDrop(Drop* curr) { printMedium(o, "drop"); } @@ -1886,73 +1692,38 @@ void visitMemoryGrow(MemoryGrow* curr) { printMedium(o, "memory.grow"); } void visitRefNull(RefNull* curr) { printMedium(o, "ref.null "); - printHeapType(o, curr->type.getHeapType(), wasm); - } - void visitRefIs(RefIs* curr) { - switch (curr->op) { - case RefIsNull: - printMedium(o, "ref.is_null"); - break; - case RefIsFunc: - printMedium(o, "ref.is_func"); - break; - case RefIsData: - printMedium(o, "ref.is_data"); - break; - case RefIsI31: - printMedium(o, "ref.is_i31"); - break; - default: - WASM_UNREACHABLE("unimplemented ref.is_*"); - } + printHeapTypeName(o, curr->type.getHeapType()); } + void visitRefIsNull(RefIsNull* curr) { printMedium(o, "ref.is_null"); } void visitRefFunc(RefFunc* curr) { printMedium(o, "ref.func "); printName(curr->func, o); } void visitRefEq(RefEq* curr) { printMedium(o, "ref.eq"); } - void visitTableGet(TableGet* curr) { - printMedium(o, "table.get "); - printName(curr->table, o); - } - void visitTableSet(TableSet* curr) { - printMedium(o, "table.set "); - printName(curr->table, o); - } - void visitTableSize(TableSize* curr) { - printMedium(o, "table.size "); - printName(curr->table, o); - } - void visitTableGrow(TableGrow* curr) { - printMedium(o, "table.grow "); - printName(curr->table, o); - } void visitTry(Try* curr) { printMedium(o, "try"); - if (curr->name.is()) { - o << ' '; - printName(curr->name, o); - } if (curr->type.isConcrete()) { - o << ' '; - printResultType(o, curr->type, wasm); + o << ' ' << ResultType(curr->type); } } void visitThrow(Throw* curr) { printMedium(o, "throw "); - printName(curr->tag, o); + printName(curr->event, o); } - void visitRethrow(Rethrow* curr) { - printMedium(o, "rethrow "); - printName(curr->target, o); + void visitRethrow(Rethrow* curr) { printMedium(o, "rethrow"); } + void visitBrOnExn(BrOnExn* curr) { + printMedium(o, "br_on_exn "); + printName(curr->name, o); + o << " "; + printName(curr->event, o); } void visitNop(Nop* curr) { printMinor(o, "nop"); } void visitUnreachable(Unreachable* curr) { printMinor(o, "unreachable"); } void visitPop(Pop* curr) { prepareColor(o) << "pop"; for (auto type : curr->type) { - o << ' '; - printType(o, type, wasm); + assert(type.isBasic() && "TODO: print and parse compound types"); + o << " " << type; } restoreNormalColor(o); } @@ -1973,136 +1744,38 @@ } } void visitRefTest(RefTest* curr) { - if (curr->rtt) { - printMedium(o, "ref.test"); - } else { - printMedium(o, "ref.test_static "); - printHeapType(o, curr->intendedType, wasm); - } + printMedium(o, "ref.test "); + printHeapTypeName(o, curr->getCastType().getHeapType()); } void visitRefCast(RefCast* curr) { - if (curr->rtt) { - printMedium(o, "ref.cast"); - } else { - if (curr->safety == RefCast::Unsafe) { - printMedium(o, "ref.cast_nop_static "); - } else { - printMedium(o, "ref.cast_static "); - } - printHeapType(o, curr->intendedType, wasm); - } + printMedium(o, "ref.cast "); + printHeapTypeName(o, curr->getCastType().getHeapType()); } - void visitBrOn(BrOn* curr) { - switch (curr->op) { - case BrOnNull: - printMedium(o, "br_on_null "); - break; - case BrOnNonNull: - printMedium(o, "br_on_non_null "); - break; - case BrOnCast: - if (curr->rtt) { - printMedium(o, "br_on_cast "); - } else { - printMedium(o, "br_on_cast_static "); - printName(curr->name, o); - o << ' '; - printHeapType(o, curr->intendedType, wasm); - return; - } - break; - case BrOnCastFail: - if (curr->rtt) { - printMedium(o, "br_on_cast_fail "); - } else { - printMedium(o, "br_on_cast_static_fail "); - printName(curr->name, o); - o << ' '; - printHeapType(o, curr->intendedType, wasm); - return; - } - break; - case BrOnFunc: - printMedium(o, "br_on_func "); - break; - case BrOnNonFunc: - printMedium(o, "br_on_non_func "); - break; - case BrOnData: - printMedium(o, "br_on_data "); - break; - case BrOnNonData: - printMedium(o, "br_on_non_data "); - break; - case BrOnI31: - printMedium(o, "br_on_i31 "); - break; - case BrOnNonI31: - printMedium(o, "br_on_non_i31 "); - break; - default: - WASM_UNREACHABLE("invalid ref.is_*"); - } + void visitBrOnCast(BrOnCast* curr) { + printMedium(o, "br_on_cast "); printName(curr->name, o); + o << " "; + printHeapTypeName(o, curr->getCastType().getHeapType()); } void visitRttCanon(RttCanon* curr) { printMedium(o, "rtt.canon "); - TypeNamePrinter(o, wasm).print(curr->type.getRtt().heapType); + printHeapTypeName(o, curr->type.getRtt().heapType); } void visitRttSub(RttSub* curr) { - if (curr->fresh) { - printMedium(o, "rtt.fresh_sub "); - } else { - printMedium(o, "rtt.sub "); - } - TypeNamePrinter(o, wasm).print(curr->type.getRtt().heapType); - } - - // If we cannot print a valid unreachable instruction (say, a struct.get, - // where if the ref is unreachable, we don't know what heap type to print), - // then print the children in a block, which is good enough as this - // instruction is never reached anyhow. - // - // This function checks if the input is in fact unreachable, and if so, begins - // to emit a replacement for it and returns true. - bool printUnreachableReplacement(Expression* curr) { - if (curr->type == Type::unreachable) { - printMedium(o, "block"); - return true; - } - return false; + printMedium(o, "rtt.sub "); + printHeapTypeName(o, curr->type.getRtt().heapType); } - void visitStructNew(StructNew* curr) { - if (printUnreachableReplacement(curr)) { - return; - } - printMedium(o, "struct.new"); + printMedium(o, "struct.new_"); if (curr->isWithDefault()) { - printMedium(o, "_default"); + o << "default_"; } - if (curr->rtt) { - printMedium(o, "_with_rtt"); - } - o << ' '; - TypeNamePrinter(o, wasm).print(curr->type.getHeapType()); - } - - void printFieldName(HeapType type, Index index) { - processFieldName(wasm, type, index, [&](Name name) { - if (name.is()) { - o << '$' << name; - } else { - o << index; - } - }); + o << "with_rtt "; + printHeapTypeName(o, curr->rtt->type.getHeapType()); } void visitStructGet(StructGet* curr) { - if (printUnreachableReplacement(curr->ref)) { - return; - } - auto heapType = curr->ref->type.getHeapType(); - const auto& field = heapType.getStruct().fields[curr->index]; + const auto& field = + curr->ref->type.getHeapType().getStruct().fields[curr->index]; if (field.type == Type::i32 && field.packedType != Field::not_packed) { if (curr->signed_) { printMedium(o, "struct.get_s "); @@ -2112,49 +1785,25 @@ } else { printMedium(o, "struct.get "); } - TypeNamePrinter(o, wasm).print(heapType); + printHeapTypeName(o, curr->ref->type.getHeapType()); o << ' '; - printFieldName(heapType, curr->index); + o << curr->index; } void visitStructSet(StructSet* curr) { - if (printUnreachableReplacement(curr->ref)) { - return; - } printMedium(o, "struct.set "); - auto heapType = curr->ref->type.getHeapType(); - TypeNamePrinter(o, wasm).print(heapType); + printHeapTypeName(o, curr->ref->type.getHeapType()); o << ' '; - printFieldName(heapType, curr->index); + o << curr->index; } void visitArrayNew(ArrayNew* curr) { - if (printUnreachableReplacement(curr)) { - return; - } - printMedium(o, "array.new"); + printMedium(o, "array.new_"); if (curr->isWithDefault()) { - printMedium(o, "_default"); - } - if (curr->rtt) { - printMedium(o, "_with_rtt"); - } - o << ' '; - TypeNamePrinter(o, wasm).print(curr->type.getHeapType()); - } - void visitArrayInit(ArrayInit* curr) { - if (printUnreachableReplacement(curr)) { - return; - } - printMedium(o, "array.init"); - if (!curr->rtt) { - printMedium(o, "_static"); + o << "default_"; } - o << ' '; - TypeNamePrinter(o, wasm).print(curr->type.getHeapType()); + o << "with_rtt "; + printHeapTypeName(o, curr->rtt->type.getHeapType()); } void visitArrayGet(ArrayGet* curr) { - if (printUnreachableReplacement(curr->ref)) { - return; - } const auto& element = curr->ref->type.getHeapType().getArray().element; if (element.type == Type::i32 && element.packedType != Field::not_packed) { if (curr->signed_) { @@ -2165,55 +1814,21 @@ } else { printMedium(o, "array.get "); } - TypeNamePrinter(o, wasm).print(curr->ref->type.getHeapType()); + printHeapTypeName(o, curr->ref->type.getHeapType()); } void visitArraySet(ArraySet* curr) { - if (printUnreachableReplacement(curr->ref)) { - return; - } printMedium(o, "array.set "); - TypeNamePrinter(o, wasm).print(curr->ref->type.getHeapType()); + printHeapTypeName(o, curr->ref->type.getHeapType()); } void visitArrayLen(ArrayLen* curr) { - if (printUnreachableReplacement(curr->ref)) { - return; - } printMedium(o, "array.len "); - TypeNamePrinter(o, wasm).print(curr->ref->type.getHeapType()); - } - void visitArrayCopy(ArrayCopy* curr) { - if (printUnreachableReplacement(curr->srcRef) || - printUnreachableReplacement(curr->destRef)) { - return; - } - printMedium(o, "array.copy "); - TypeNamePrinter(o, wasm).print(curr->destRef->type.getHeapType()); - o << ' '; - TypeNamePrinter(o, wasm).print(curr->srcRef->type.getHeapType()); - } - void visitRefAs(RefAs* curr) { - switch (curr->op) { - case RefAsNonNull: - printMedium(o, "ref.as_non_null"); - break; - case RefAsFunc: - printMedium(o, "ref.as_func"); - break; - case RefAsData: - printMedium(o, "ref.as_data"); - break; - case RefAsI31: - printMedium(o, "ref.as_i31"); - break; - default: - WASM_UNREACHABLE("invalid ref.is_*"); - } + printHeapTypeName(o, curr->ref->type.getHeapType()); } }; // Prints an expression in s-expr format, including both the // internal contents and the nested children. -struct PrintSExpression : public UnifiedExpressionVisitor { +struct PrintSExpression : public OverriddenVisitor { std::ostream& o; unsigned indent = 0; @@ -2221,8 +1836,8 @@ const char* maybeSpace; const char* maybeNewLine; - bool full = false; // whether to not elide nodes in output when possible - // (like implicit blocks) and to emit types + bool full = false; // whether to not elide nodes in output when possible + // (like implicit blocks) and to emit types bool stackIR = false; // whether to print stack IR if it is present // (if false, and Stack IR is there, we just // note it exists) @@ -2232,9 +1847,6 @@ Function::DebugLocation lastPrintedLocation; bool debugInfo; - // Used to print delegate's depth argument when it throws to the caller - int controlFlowDepth = 0; - PrintSExpression(std::ostream& o) : o(o) { setMinify(false); if (!full) { @@ -2275,32 +1887,9 @@ } } - // Prints debug info for a delimiter in an expression. - void printDebugDelimiterLocation(Expression* curr, Index i) { - if (currFunction && debugInfo) { - auto iter = currFunction->delimiterLocations.find(curr); - if (iter != currFunction->delimiterLocations.end()) { - auto& locations = iter->second; - Colors::grey(o); - o << ";; code offset: 0x" << std::hex << locations[i] << std::dec - << '\n'; - restoreNormalColor(o); - doIndent(o, indent); - } - } - } - - void printExpressionContents(Expression* curr) { - if (currModule) { - PrintExpressionContents(currModule, currFunction, o).visit(curr); - } else { - PrintExpressionContents(currFunction, o).visit(curr); - } - } - void visit(Expression* curr) { printDebugLocation(curr); - UnifiedExpressionVisitor::visit(curr); + OverriddenVisitor::visit(curr); } void setMinify(bool minify_) { @@ -2355,22 +1944,6 @@ } } - // Generic visitor, overridden only when necessary. - void visitExpression(Expression* curr) { - o << '('; - printExpressionContents(curr); - auto it = ChildIterator(curr); - if (!it.children.empty()) { - incIndent(); - for (auto* child : it) { - printFullLine(child); - } - decIndent(); - } else { - o << ')'; - } - } - void visitBlock(Block* curr) { // special-case Block, because Block nesting (in their first element) can be // incredibly deep @@ -2385,7 +1958,7 @@ o << "[" << curr->type << "] "; } o << '('; - printExpressionContents(curr); + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); if (curr->list.size() > 0 && curr->list[0]->is()) { // recurse into the first element @@ -2395,9 +1968,6 @@ break; // that's all we can recurse, start to unwind } } - - int startControlFlowDepth = controlFlowDepth; - controlFlowDepth += stack.size(); auto* top = stack.back(); while (stack.size() > 0) { curr = stack.back(); @@ -2427,32 +1997,24 @@ o << ' ' << curr->name; } } - controlFlowDepth = startControlFlowDepth; } void visitIf(If* curr) { - controlFlowDepth++; o << '('; - printExpressionContents(curr); + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); printFullLine(curr->condition); maybePrintImplicitBlock(curr->ifTrue, false); if (curr->ifFalse) { - // Note: debug info here is not used as LLVM does not emit ifs, and since - // LLVM is the main source of DWARF, effectively we never encounter ifs - // with DWARF. - printDebugDelimiterLocation(curr, BinaryLocations::Else); maybePrintImplicitBlock(curr->ifFalse, false); } decIndent(); if (full) { o << " ;; end if"; } - controlFlowDepth--; } void visitLoop(Loop* curr) { - controlFlowDepth++; o << '('; - printExpressionContents(curr); + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); maybePrintImplicitBlock(curr->body, true); decIndent(); @@ -2462,182 +2024,556 @@ o << ' ' << curr->name; } } - controlFlowDepth--; + } + void visitBreak(Break* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + if (curr->condition) { + incIndent(); + } else { + if (!curr->value || curr->value->is()) { + // avoid a new line just for the parens + o << ')'; + return; + } + incIndent(); + } + if (curr->value && !curr->value->is()) { + printFullLine(curr->value); + } + if (curr->condition) { + printFullLine(curr->condition); + } + decIndent(); + } + void visitSwitch(Switch* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + if (curr->value && !curr->value->is()) { + printFullLine(curr->value); + } + printFullLine(curr->condition); + decIndent(); + } + + template void printCallOperands(CallBase* curr) { + if (curr->operands.size() > 0) { + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); + } + decIndent(); + } else { + o << ')'; + } + } + + void visitCall(Call* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + printCallOperands(curr); + } + void visitCallIndirect(CallIndirect* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); + } + printFullLine(curr->target); + decIndent(); + } + void visitLocalGet(LocalGet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitLocalSet(LocalSet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitGlobalGet(GlobalGet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitGlobalSet(GlobalSet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitLoad(Load* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + decIndent(); + } + void visitStore(Store* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->value); + decIndent(); + } + void visitAtomicRMW(AtomicRMW* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->value); + decIndent(); + } + void visitAtomicCmpxchg(AtomicCmpxchg* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->expected); + printFullLine(curr->replacement); + decIndent(); + } + void visitAtomicWait(AtomicWait* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + restoreNormalColor(o); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->expected); + printFullLine(curr->timeout); + decIndent(); + } + void visitAtomicNotify(AtomicNotify* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->notifyCount); + decIndent(); + } + void visitAtomicFence(AtomicFence* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitSIMDExtract(SIMDExtract* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->vec); + decIndent(); + } + void visitSIMDReplace(SIMDReplace* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->vec); + printFullLine(curr->value); + decIndent(); + } + void visitSIMDShuffle(SIMDShuffle* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->left); + printFullLine(curr->right); + decIndent(); + } + void visitSIMDTernary(SIMDTernary* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->a); + printFullLine(curr->b); + printFullLine(curr->c); + decIndent(); + } + void visitSIMDShift(SIMDShift* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->vec); + printFullLine(curr->shift); + decIndent(); + } + void visitSIMDLoad(SIMDLoad* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + decIndent(); + } + void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + printFullLine(curr->vec); + decIndent(); + } + void visitPrefetch(Prefetch* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ptr); + decIndent(); + } + void visitMemoryInit(MemoryInit* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->dest); + printFullLine(curr->offset); + printFullLine(curr->size); + decIndent(); + } + void visitDataDrop(DataDrop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitMemoryCopy(MemoryCopy* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->dest); + printFullLine(curr->source); + printFullLine(curr->size); + decIndent(); + } + void visitMemoryFill(MemoryFill* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->dest); + printFullLine(curr->value); + printFullLine(curr->size); + decIndent(); + } + void visitConst(Const* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitUnary(Unary* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitBinary(Binary* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->left); + printFullLine(curr->right); + decIndent(); + } + void visitSelect(Select* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ifTrue); + printFullLine(curr->ifFalse); + printFullLine(curr->condition); + decIndent(); + } + void visitDrop(Drop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitReturn(Return* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + if (!curr->value) { + // avoid a new line just for the parens + o << ')'; + return; + } + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitMemorySize(MemorySize* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitMemoryGrow(MemoryGrow* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->delta); + decIndent(); + } + void visitRefNull(RefNull* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitRefIsNull(RefIsNull* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitRefFunc(RefFunc* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitRefEq(RefEq* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->left); + printFullLine(curr->right); + decIndent(); } // try-catch-end is written in the folded wat format as // (try // (do // ... // ) - // (catch $e - // ... - // ) - // ... - // (catch_all - // ... - // ) - // ) - // The parenthesis wrapping do/catch/catch_all is just a syntax and does not - // affect nested depths of instructions within. - // - // try-delegate is written in the forded format as - // (try - // (do - // ... + // (catch + // ... // ) - // (delegate $label) // ) - // When the 'delegate' delegates to the caller, we write the argument as an - // immediate. + // The parenthesis wrapping 'catch' is just a syntax and does not affect + // nested depths of instructions within. void visitTry(Try* curr) { - controlFlowDepth++; o << '('; - printExpressionContents(curr); + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); doIndent(o, indent); - o << '('; - printMedium(o, "do"); + o << "(do"; incIndent(); maybePrintImplicitBlock(curr->body, true); decIndent(); o << "\n"; - for (size_t i = 0; i < curr->catchTags.size(); i++) { - doIndent(o, indent); - printDebugDelimiterLocation(curr, i); - o << '('; - printMedium(o, "catch "); - printName(curr->catchTags[i], o); - incIndent(); - maybePrintImplicitBlock(curr->catchBodies[i], true); - decIndent(); - o << "\n"; - } - if (curr->hasCatchAll()) { - doIndent(o, indent); - printDebugDelimiterLocation(curr, curr->catchTags.size()); - o << '('; - printMedium(o, "catch_all"); - incIndent(); - maybePrintImplicitBlock(curr->catchBodies.back(), true); - decIndent(); - o << "\n"; - } - controlFlowDepth--; - - if (curr->isDelegate()) { - doIndent(o, indent); - o << '('; - printMedium(o, "delegate "); - if (curr->delegateTarget == DELEGATE_CALLER_TARGET) { - o << controlFlowDepth; - } else { - printName(curr->delegateTarget, o); - } - o << ")\n"; - } + doIndent(o, indent); + o << "(catch"; + incIndent(); + maybePrintImplicitBlock(curr->catchBody, true); + decIndent(); + o << "\n"; decIndent(); if (full) { o << " ;; end try"; } } - void maybePrintUnreachableReplacement(Expression* curr, Type type) { - // See the parallel function - // PrintExpressionContents::printUnreachableReplacement for background. That - // one handles the header, and this one the body. For convenience, this one - // also gets a parameter of the type to check for unreachability, to avoid - // boilerplate in the callers; if the type is not unreachable, it does the - // normal behavior. - // - // Note that the list of instructions using that function must match those - // using this one, so we print the header and body properly together. - - if (type != Type::unreachable) { - visitExpression(curr); - return; + void visitThrow(Throw* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); } - - // Emit a block with drops of the children. - o << "(block"; - if (!minify) { - o << " ;; (replaces something unreachable we can't emit)"; + decIndent(); + } + void visitRethrow(Rethrow* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->exnref); + decIndent(); + } + void visitBrOnExn(BrOnExn* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->exnref); + decIndent(); + } + void visitNop(Nop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitUnreachable(Unreachable* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitPop(Pop* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitTupleMake(TupleMake* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); } + decIndent(); + } + void visitTupleExtract(TupleExtract* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->tuple); + decIndent(); + } + void visitI31New(I31New* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->value); + decIndent(); + } + void visitI31Get(I31Get* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); incIndent(); - for (auto* child : ChildIterator(curr)) { - Drop drop; - drop.value = child; - printFullLine(&drop); + printFullLine(curr->i31); + decIndent(); + } + void visitCallRef(CallRef* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + for (auto operand : curr->operands) { + printFullLine(operand); } + printFullLine(curr->target); decIndent(); } - void visitStructNew(StructNew* curr) { - maybePrintUnreachableReplacement(curr, curr->type); + void visitRefTest(RefTest* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->rtt); + decIndent(); } - void visitStructSet(StructSet* curr) { - maybePrintUnreachableReplacement(curr, curr->ref->type); + void visitRefCast(RefCast* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->rtt); + decIndent(); + } + void visitBrOnCast(BrOnCast* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->rtt); + decIndent(); + } + void visitRttCanon(RttCanon* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + o << ')'; + } + void visitRttSub(RttSub* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->parent); + decIndent(); + } + void visitStructNew(StructNew* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->rtt); + for (auto& operand : curr->operands) { + printFullLine(operand); + } + decIndent(); } void visitStructGet(StructGet* curr) { - maybePrintUnreachableReplacement(curr, curr->ref->type); + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + decIndent(); + } + void visitStructSet(StructSet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->value); + decIndent(); } void visitArrayNew(ArrayNew* curr) { - maybePrintUnreachableReplacement(curr, curr->type); + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->rtt); + printFullLine(curr->size); + if (curr->init) { + printFullLine(curr->init); + } + decIndent(); } - void visitArrayInit(ArrayInit* curr) { - maybePrintUnreachableReplacement(curr, curr->type); + void visitArrayGet(ArrayGet* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->index); + decIndent(); } void visitArraySet(ArraySet* curr) { - maybePrintUnreachableReplacement(curr, curr->ref->type); + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->index); + printFullLine(curr->value); + decIndent(); } - void visitArrayGet(ArrayGet* curr) { - maybePrintUnreachableReplacement(curr, curr->ref->type); + void visitArrayLen(ArrayLen* curr) { + o << '('; + PrintExpressionContents(currFunction, o).visit(curr); + incIndent(); + printFullLine(curr->ref); + decIndent(); } // Module-level visitors - void printSupertypeOr(HeapType curr, std::string noSuper) { - if (auto super = curr.getSuperType()) { - TypeNamePrinter(o, currModule).print(*super); - } else { - o << noSuper; - } - } - - void handleSignature(HeapType curr, Name name = Name()) { - Signature sig = curr.getSignature(); - bool hasSupertype = - !name.is() && (getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive); - if (hasSupertype) { - o << "(func_subtype"; - } else { - o << "(func"; - } + void handleSignature(Signature curr, Name name = Name()) { + o << "(func"; if (name.is()) { o << " $" << name; } - if (sig.params.size() > 0) { + if (curr.params.size() > 0) { o << maybeSpace; o << "(param "; auto sep = ""; - for (auto type : sig.params) { - o << sep; - printType(o, type, currModule); + for (auto type : curr.params) { + o << sep << SExprType(type); sep = " "; } o << ')'; } - if (sig.results.size() > 0) { + if (curr.results.size() > 0) { o << maybeSpace; o << "(result "; auto sep = ""; - for (auto type : sig.results) { - o << sep; - printType(o, type, currModule); + for (auto type : curr.results) { + o << sep << SExprType(type); sep = " "; } o << ')'; } - if (hasSupertype) { - o << ' '; - printSupertypeOr(curr, "func"); - } o << ")"; } void handleFieldBody(const Field& field) { @@ -2653,61 +2589,35 @@ WASM_UNREACHABLE("invalid packed type"); } } else { - printType(o, field.type, currModule); + o << SExprType(field.type); } if (field.mutable_) { o << ')'; } } - void handleArray(HeapType curr) { - bool hasSupertype = getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive; - if (hasSupertype) { - o << "(array_subtype "; - } else { - o << "(array "; - } - handleFieldBody(curr.getArray().element); - if (hasSupertype) { - o << ' '; - printSupertypeOr(curr, "data"); - } + void handleArray(const Array& curr) { + o << "(array "; + handleFieldBody(curr.element); o << ')'; } - void handleStruct(HeapType curr) { - bool hasSupertype = getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive; - const auto& fields = curr.getStruct().fields; - if (hasSupertype) { - o << "(struct_subtype "; - } else { - o << "(struct "; - } + void handleStruct(const Struct& curr) { + o << "(struct "; auto sep = ""; - for (Index i = 0; i < fields.size(); i++) { + for (auto field : curr.fields) { o << sep << "(field "; - processFieldName(currModule, curr, i, [&](Name name) { - if (name.is()) { - o << '$' << name << ' '; - } - }); - handleFieldBody(fields[i]); + handleFieldBody(field); o << ')'; sep = " "; } - if (hasSupertype) { - o << ' '; - printSupertypeOr(curr, "data"); - } o << ')'; } void handleHeapType(HeapType type) { if (type.isSignature()) { - handleSignature(type); + handleSignature(type.getSignature()); } else if (type.isArray()) { - handleArray(type); + handleArray(type.getArray()); } else if (type.isStruct()) { - handleStruct(type); + handleStruct(type.getStruct()); } else { o << type; } @@ -2729,8 +2639,8 @@ case ExternalKind::Global: o << "global"; break; - case ExternalKind::Tag: - o << "tag"; + case ExternalKind::Event: + o << "event"; break; case ExternalKind::Invalid: WASM_UNREACHABLE("invalid ExternalKind"); @@ -2752,10 +2662,9 @@ } void emitGlobalType(Global* curr) { if (curr->mutable_) { - o << "(mut "; - printType(o, curr->type, currModule) << ')'; + o << "(mut " << SExprType(curr->type) << ')'; } else { - printType(o, curr->type, currModule); + o << SExprType(curr->type); } } void visitImportedGlobal(Global* curr) { @@ -2791,7 +2700,7 @@ lastPrintedLocation = {0, 0, 0}; o << '('; emitImportHeader(curr); - handleSignature(curr->getSig(), curr->name); + handleSignature(curr->sig, curr->name); o << ')'; o << maybeNewLine; } @@ -2805,37 +2714,31 @@ o << '('; printMajor(o, "func "); printName(curr->name, o); - if (getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive) { - o << " (type "; - printHeapType(o, curr->type, currModule) << ')'; - } if (!stackIR && curr->stackIR && !minify) { o << " (; has Stack IR ;)"; } - if (curr->getParams().size() > 0) { + if (curr->sig.params.size() > 0) { Index i = 0; - for (const auto& param : curr->getParams()) { + for (const auto& param : curr->sig.params) { o << maybeSpace; o << '('; printMinor(o, "param "); printLocal(i, currFunction, o); - o << ' '; - printType(o, param, currModule) << ')'; + o << ' ' << SExprType(param) << ')'; ++i; } } - if (curr->getResults() != Type::none) { + if (curr->sig.results != Type::none) { o << maybeSpace; - printResultType(o, curr->getResults(), currModule); + o << ResultTypeName(curr->sig.results); } incIndent(); for (size_t i = curr->getVarIndexBase(); i < curr->getNumLocals(); i++) { doIndent(o, indent); o << '('; printMinor(o, "local "); - printLocal(i, currFunction, o) << ' '; - printType(o, curr->getLocalType(i), currModule) << ')'; + printLocal(i, currFunction, o) + << ' ' << SExprType(curr->getLocalType(i)) << ')'; o << maybeNewLine; } // Print the body. @@ -2852,7 +2755,6 @@ } else { printFullLine(curr->body); } - assert(controlFlowDepth == 0); } else { // Print the stack IR. printStackIR(curr->stackIR.get(), o, curr); @@ -2872,31 +2774,31 @@ } o << maybeNewLine; } - void visitTag(Tag* curr) { + void visitEvent(Event* curr) { if (curr->imported()) { - visitImportedTag(curr); + visitImportedEvent(curr); } else { - visitDefinedTag(curr); + visitDefinedEvent(curr); } } - void visitImportedTag(Tag* curr) { + void visitImportedEvent(Event* curr) { doIndent(o, indent); o << '('; emitImportHeader(curr); - o << "(tag "; + o << "(event "; printName(curr->name, o); - o << maybeSpace; - printParamType(o, curr->sig.params, currModule); + o << maybeSpace << "(attr " << curr->attribute << ')' << maybeSpace; + o << ParamType(curr->sig.params); o << "))"; o << maybeNewLine; } - void visitDefinedTag(Tag* curr) { + void visitDefinedEvent(Event* curr) { doIndent(o, indent); o << '('; - printMedium(o, "tag "); + printMedium(o, "event "); printName(curr->name, o); - o << maybeSpace; - printParamType(o, curr->sig.params, currModule); + o << maybeSpace << "(attr " << curr->attribute << ')' << maybeSpace; + o << ParamType(curr->sig.params); o << ")" << maybeNewLine; } void printTableHeader(Table* curr) { @@ -2907,75 +2809,38 @@ if (curr->hasMax()) { o << ' ' << curr->max; } - o << ' '; - printType(o, curr->type, currModule) << ')'; + o << " funcref)"; } void visitTable(Table* curr) { + if (!curr->exists) { + return; + } if (curr->imported()) { doIndent(o, indent); o << '('; emitImportHeader(curr); - printTableHeader(curr); + printTableHeader(&currModule->table); o << ')' << maybeNewLine; } else { doIndent(o, indent); printTableHeader(curr); o << maybeNewLine; } - } - void visitElementSegment(ElementSegment* curr) { - bool usesExpressions = TableUtils::usesExpressions(curr, currModule); - auto printElemType = [&]() { - if (!usesExpressions) { - o << "func"; - } else { - printType(o, curr->type, currModule); - } - }; - - doIndent(o, indent); - o << '('; - printMedium(o, "elem"); - // If there is no explicit name, and there are multiple segments, use our - // internal names to differentiate them. - if (curr->hasExplicitName || currModule->elementSegments.size() > 1) { - o << ' '; - printName(curr->name, o); - } - - if (curr->table.is()) { - if (usesExpressions || currModule->tables.size() > 1) { - // tableuse - o << " (table "; - printName(curr->table, o); - o << ")"; - } - - o << ' '; - visit(curr->offset); - - if (usesExpressions || currModule->tables.size() > 1) { - o << ' '; - printElemType(); - } - } else { - o << ' '; - printElemType(); - } - - if (!usesExpressions) { - for (auto* entry : curr->data) { - auto* refFunc = entry->cast(); - o << ' '; - printName(refFunc->func, o); + for (auto& segment : curr->segments) { + // Don't print empty segments + if (segment.data.empty()) { + continue; } - } else { - for (auto* entry : curr->data) { + doIndent(o, indent); + o << '('; + printMajor(o, "elem "); + visit(segment.offset); + for (auto name : segment.data) { o << ' '; - printExpression(entry, o); + printName(name, o); } + o << ')' << maybeNewLine; } - o << ')' << maybeNewLine; } void printMemoryHeader(Memory* curr) { o << '('; @@ -3020,11 +2885,12 @@ printName(segment.name, o); o << ' '; } - if (!segment.isPassive) { + if (segment.isPassive) { + printMedium(o, "passive"); + } else { visit(segment.offset); - o << ' '; } - o << "\""; + o << " \""; for (size_t i = 0; i < segment.data.size(); i++) { unsigned char c = segment.data[i]; switch (c) { @@ -3077,10 +2943,6 @@ for (auto& neededDynlib : dylinkSection->neededDynlibs) { doIndent(o, indent) << ";; needed dynlib: " << neededDynlib << '\n'; } - if (dylinkSection->tail.size()) { - doIndent(o, indent) << ";; extra dylink data, size " - << dylinkSection->tail.size() << "\n"; - } } void visitModule(Module* curr) { currModule = curr; @@ -3091,42 +2953,18 @@ printName(curr->name, o); } incIndent(); - - // Use the same type order as the binary output would even though there is - // no code size benefit in the text format. - auto indexedTypes = ModuleUtils::getOptimizedIndexedHeapTypes(*curr); - std::optional currGroup; - bool nontrivialGroup = false; - auto finishGroup = [&]() { - if (nontrivialGroup) { - decIndent(); - o << maybeNewLine; - } - }; - for (auto type : indexedTypes.types) { - RecGroup newGroup = type.getRecGroup(); - if (!currGroup || *currGroup != newGroup) { - if (currGroup) { - finishGroup(); - } - currGroup = newGroup; - nontrivialGroup = currGroup->size() > 1; - if (nontrivialGroup) { - doIndent(o, indent); - o << "(rec "; - incIndent(); - } - } + std::vector types; + std::unordered_map indices; + ModuleUtils::collectHeapTypes(*curr, types, indices); + for (auto type : types) { doIndent(o, indent); o << '('; printMedium(o, "type") << ' '; - TypeNamePrinter(o, curr).print(type); + printHeapTypeName(o, type); o << ' '; handleHeapType(type); o << ")" << maybeNewLine; } - finishGroup(); - ModuleUtils::iterImportedMemories( *curr, [&](Memory* memory) { visitMemory(memory); }); ModuleUtils::iterImportedTables(*curr, @@ -3135,27 +2973,16 @@ *curr, [&](Global* global) { visitGlobal(global); }); ModuleUtils::iterImportedFunctions( *curr, [&](Function* func) { visitFunction(func); }); - ModuleUtils::iterImportedTags(*curr, [&](Tag* tag) { visitTag(tag); }); - ModuleUtils::iterDefinedGlobals( - *curr, [&](Global* global) { visitGlobal(global); }); + ModuleUtils::iterImportedEvents(*curr, + [&](Event* event) { visitEvent(event); }); ModuleUtils::iterDefinedMemories( *curr, [&](Memory* memory) { visitMemory(memory); }); ModuleUtils::iterDefinedTables(*curr, [&](Table* table) { visitTable(table); }); - for (auto& segment : curr->elementSegments) { - visitElementSegment(segment.get()); - } - auto elemDeclareNames = TableUtils::getFunctionsNeedingElemDeclare(*curr); - if (!elemDeclareNames.empty()) { - doIndent(o, indent); - printMedium(o, "(elem"); - o << " declare func"; - for (auto name : elemDeclareNames) { - o << " $" << name; - } - o << ')' << maybeNewLine; - } - ModuleUtils::iterDefinedTags(*curr, [&](Tag* tag) { visitTag(tag); }); + ModuleUtils::iterDefinedGlobals( + *curr, [&](Global* global) { visitGlobal(global); }); + ModuleUtils::iterDefinedEvents(*curr, + [&](Event* event) { visitEvent(event); }); for (auto& child : curr->exports) { doIndent(o, indent); visitExport(child.get()); @@ -3198,10 +3025,6 @@ } o << maybeNewLine; } - if (curr->hasFeaturesSection) { - doIndent(o, indent); - o << ";; features section: " << curr->features.toString() << '\n'; - } decIndent(); o << maybeNewLine; currModule = nullptr; @@ -3282,15 +3105,13 @@ static std::ostream& printExpression(Expression* expression, std::ostream& o, bool minify, - bool full, - Module* wasm) { + bool full) { if (!expression) { o << "(null expression)"; return o; } PrintSExpression print(o); print.setMinify(minify); - print.currModule = wasm; if (full || isFullForced()) { print.setFull(true); o << "[" << expression->type << "] "; @@ -3302,40 +3123,30 @@ static std::ostream& printStackInst(StackInst* inst, std::ostream& o, Function* func) { switch (inst->op) { - case StackInst::Basic: + case StackInst::Basic: { + PrintExpressionContents(func, o).visit(inst->origin); + break; + } case StackInst::BlockBegin: case StackInst::IfBegin: case StackInst::LoopBegin: case StackInst::TryBegin: { - PrintExpressionContents(func, o).visit(inst->origin); + o << getExpressionName(inst->origin); break; } case StackInst::BlockEnd: case StackInst::IfEnd: case StackInst::LoopEnd: case StackInst::TryEnd: { - printMedium(o, "end"); - o << " ;; type: "; - TypeNamePrinter(o).print(inst->type); + o << "end (" << inst->type << ')'; break; } case StackInst::IfElse: { - printMedium(o, "else"); + o << "else"; break; } case StackInst::Catch: { - // Because StackInst does not have info on which catch within a try this - // is, we can't print the tag name. - printMedium(o, "catch"); - break; - } - case StackInst::CatchAll: { - printMedium(o, "catch_all"); - break; - } - case StackInst::Delegate: { - printMedium(o, "delegate "); - printName(inst->origin->cast()->delegateTarget, o); + o << "catch"; break; } default: @@ -3352,10 +3163,6 @@ o << ' '; } }; - - int controlFlowDepth = 0; - // Stack to track indices of catches within a try - SmallVector catchIndexStack; for (Index i = 0; i < (*ir).size(); i++) { auto* inst = (*ir)[i]; if (!inst) { @@ -3369,76 +3176,46 @@ if (inst->origin->is()) { break; } - PrintExpressionContents(func, o).visit(inst->origin); break; } - case StackInst::TryBegin: - catchIndexStack.push_back(0); - [[fallthrough]]; case StackInst::BlockBegin: case StackInst::IfBegin: - case StackInst::LoopBegin: { - controlFlowDepth++; + case StackInst::LoopBegin: + case StackInst::TryBegin: { doIndent(); PrintExpressionContents(func, o).visit(inst->origin); indent++; break; } - case StackInst::TryEnd: - catchIndexStack.pop_back(); - [[fallthrough]]; case StackInst::BlockEnd: case StackInst::IfEnd: - case StackInst::LoopEnd: { - controlFlowDepth--; + case StackInst::LoopEnd: + case StackInst::TryEnd: { indent--; doIndent(); - printMedium(o, "end"); + o << "end"; break; } case StackInst::IfElse: { indent--; doIndent(); - printMedium(o, "else"); + o << "else"; indent++; break; } case StackInst::Catch: { indent--; doIndent(); - printMedium(o, "catch "); - Try* curr = inst->origin->cast(); - printName(curr->catchTags[catchIndexStack.back()++], o); + o << "catch"; indent++; break; } - case StackInst::CatchAll: { - indent--; - doIndent(); - printMedium(o, "catch_all"); - indent++; - break; - } - case StackInst::Delegate: { - controlFlowDepth--; - indent--; - doIndent(); - printMedium(o, "delegate "); - Try* curr = inst->origin->cast(); - if (curr->delegateTarget == DELEGATE_CALLER_TARGET) { - o << controlFlowDepth; - } else { - printName(curr->delegateTarget, o); - } - break; - } default: WASM_UNREACHABLE("unexpeted op"); } std::cout << '\n'; } - assert(controlFlowDepth == 0); return o; } @@ -3460,10 +3237,6 @@ return wasm::printExpression(expression, o); } -std::ostream& operator<<(std::ostream& o, wasm::ModuleExpression pair) { - return wasm::printExpression(pair.second, o, false, false, &pair.first); -} - std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst) { return wasm::printStackInst(&inst, o); } diff -Nru binaryen-108/src/passes/PrintFunctionMap.cpp binaryen-99/src/passes/PrintFunctionMap.cpp --- binaryen-108/src/passes/PrintFunctionMap.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/PrintFunctionMap.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -24,9 +24,7 @@ // 2:baz // -#include "ir/module-utils.h" #include "pass.h" -#include "support/file.h" #include "wasm.h" namespace wasm { @@ -35,17 +33,10 @@ bool modifiesBinaryenIR() override { return false; } void run(PassRunner* runner, Module* module) override { - // If an argument is provided, write to that file; otherwise write to - // stdout. - auto outFile = runner->options.getArgumentOrDefault("symbolmap", ""); - Output output(outFile, Flags::Text); - auto& o = output.getStream(); Index i = 0; - auto write = [&](Function* func) { - o << i++ << ':' << func->name.str << '\n'; - }; - ModuleUtils::iterImportedFunctions(*module, write); - ModuleUtils::iterDefinedFunctions(*module, write); + for (auto& func : module->functions) { + std::cout << i++ << ':' << func->name.str << '\n'; + } } }; diff -Nru binaryen-108/src/passes/RedundantSetElimination.cpp binaryen-99/src/passes/RedundantSetElimination.cpp --- binaryen-108/src/passes/RedundantSetElimination.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RedundantSetElimination.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -45,9 +44,11 @@ namespace wasm { -// Map each local index to its current value number (which is computed in -// ValueNumbering). -using LocalValues = std::vector; +// We do a very simple numbering of local values, just a unique +// number for constants so far, enough to see +// trivial duplication. LocalValues maps each local index to +// its current value +typedef std::vector LocalValues; namespace { @@ -83,10 +84,6 @@ if (numLocals == 0) { return; // nothing to do } - - // Create a unique value for use to mark unseen locations. - unseenValue = valueNumbering.getUniqueValue(); - // create the CFG by walking the IR CFGWalker, Info>:: doWalkFunction(func); @@ -96,30 +93,47 @@ optimize(); } - // Use a value numbering for the values of expressions. - ValueNumbering valueNumbering; + // numbering - // In additon to valueNumbering, each block has values for each merge. + Index nextValue = 1; // 0 is reserved for the "unseen value" + // each constant has a value + std::unordered_map literalValues; + // each value can have a value + std::unordered_map expressionValues; + // each block has values for each merge std::unordered_map> blockMergeValues; - // A value that indicates we haven't seen this location yet. - Index unseenValue; - + Index getUnseenValue() { // we haven't seen this location yet + return 0; + } Index getUniqueValue() { - auto value = valueNumbering.getUniqueValue(); #ifdef RSE_DEBUG - std::cout << "new unique value " << value << '\n'; + std::cout << "new unique value " << nextValue << '\n'; #endif - return value; + return nextValue++; } - Index getValue(Literals lit) { - auto value = valueNumbering.getValue(lit); + Index getLiteralValue(Literals lit) { + auto iter = literalValues.find(lit); + if (iter != literalValues.end()) { + return iter->second; + } #ifdef RSE_DEBUG - std::cout << "lit value " << value << '\n'; + std::cout << "new literal value for " << lit << '\n'; #endif - return value; + return literalValues[lit] = getUniqueValue(); + } + + Index getExpressionValue(Expression* expr) { + auto iter = expressionValues.find(expr); + if (iter != expressionValues.end()) { + return iter->second; + } +#ifdef RSE_DEBUG + std::cout << "new expr value for " << expr << '\n'; +#endif + return expressionValues[expr] = getUniqueValue(); } Index getBlockMergeValue(BasicBlock* block, Index index) { @@ -148,16 +162,17 @@ return value == iter2->second; } - Index getValue(Expression* expr, LocalValues& currValues) { - if (auto* get = expr->dynCast()) { + Index getValue(Expression* value, LocalValues& currValues) { + if (Properties::isConstantExpression(value)) { + // a constant + return getLiteralValue(Properties::getLiterals(value)); + } else if (auto* get = value->dynCast()) { // a copy of whatever that was return currValues[get->index]; + } else { + // get the value's own unique value + return getExpressionValue(value); } - auto value = valueNumbering.getValue(expr); -#ifdef RSE_DEBUG - std::cout << "expr value " << value << '\n'; -#endif - return value; } // flowing @@ -169,32 +184,27 @@ if (block.get() == entry) { // params are complex values we can't optimize; vars are zeros for (Index i = 0; i < numLocals; i++) { - auto type = func->getLocalType(i); if (func->isParam(i)) { #ifdef RSE_DEBUG std::cout << "new param value for " << i << '\n'; #endif start[i] = getUniqueValue(); - } else if (!LiteralUtils::canMakeZero(type)) { -#ifdef RSE_DEBUG - std::cout << "new unique value for non-zeroable " << i << '\n'; -#endif - start[i] = getUniqueValue(); } else { - start[i] = getValue(Literal::makeZeros(type)); + start[i] = + getLiteralValue(Literal::makeZeros(func->getLocalType(i))); } } } else { // other blocks have all unseen values to begin with for (Index i = 0; i < numLocals; i++) { - start[i] = unseenValue; + start[i] = getUnseenValue(); } } // the ends all begin unseen LocalValues& end = block->contents.end; end.resize(numLocals); for (Index i = 0; i < numLocals; i++) { - end[i] = unseenValue; + end[i] = getUnseenValue(); } } // keep working while stuff is flowing. we use a unique deferred queue @@ -265,9 +275,9 @@ iter++; while (iter != in.end()) { auto otherValue = (*iter)->contents.end[i]; - if (value == unseenValue) { + if (value == getUnseenValue()) { value = otherValue; - } else if (otherValue == unseenValue) { + } else if (otherValue == getUnseenValue()) { // nothing to do, other has no information } else if (value != otherValue) { // 2 different values, this is a merged value diff -Nru binaryen-108/src/passes/RemoveImports.cpp binaryen-99/src/passes/RemoveImports.cpp --- binaryen-108/src/passes/RemoveImports.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RemoveImports.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,6 @@ // look at all the rest of the code). // -#include "ir/element-utils.h" #include "ir/module-utils.h" #include "pass.h" #include "wasm.h" @@ -35,7 +34,7 @@ if (!func->imported()) { return; } - Type type = func->getResults(); + Type type = func->sig.results; if (type == Type::none) { replaceCurrent(getModule()->allocator.alloc()); } else { @@ -50,8 +49,13 @@ *curr, [&](Function* func) { names.push_back(func->name); }); // Do not remove names referenced in a table std::set indirectNames; - ElementUtils::iterAllElementFunctionNames( - curr, [&](Name& name) { indirectNames.insert(name); }); + if (curr->table.exists) { + for (auto& segment : curr->table.segments) { + for (auto& name : segment.data) { + indirectNames.insert(name); + } + } + } for (auto& name : names) { if (indirectNames.find(name) == indirectNames.end()) { curr->removeFunction(name); diff -Nru binaryen-108/src/passes/RemoveNonJSOps.cpp binaryen-99/src/passes/RemoveNonJSOps.cpp --- binaryen-108/src/passes/RemoveNonJSOps.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RemoveNonJSOps.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -43,7 +43,6 @@ #include "ir/memory-utils.h" #include "ir/module-utils.h" #include "passes/intrinsics-module.h" -#include "support/insert_ordered.h" #include "wasm-builder.h" #include "wasm-s-parser.h" @@ -52,7 +51,7 @@ struct RemoveNonJSOpsPass : public WalkerPass> { std::unique_ptr builder; std::unordered_set neededIntrinsics; - InsertOrderedSet> neededImportedGlobals; + std::set> neededImportedGlobals; bool isFunctionParallel() override { return false; } @@ -125,7 +124,9 @@ MemoryUtils::ensureExists(module->memory); // Add missing globals - for (auto& [name, type] : neededImportedGlobals) { + for (auto& pair : neededImportedGlobals) { + auto name = pair.first; + auto type = pair.second; if (!getModule()->getGlobalOrNull(name)) { auto global = make_unique(); global->name = name; @@ -139,9 +140,10 @@ } void addNeededFunctions(Module& m, Name name, std::set& needed) { - if (!needed.emplace(name).second) { + if (needed.count(name)) { return; } + needed.insert(name); auto function = m.getFunction(name); FindAll calls(function->body); @@ -249,29 +251,17 @@ } void rewriteCopysign(Binary* curr) { - - // i32.copysign(x, y) => f32.reinterpret( - // (i32.reinterpret(x) & ~(1 << 31)) | - // (i32.reinterpret(y) & (1 << 31) - // ) - // - // i64.copysign(x, y) => f64.reinterpret( - // (i64.reinterpret(x) & ~(1 << 63)) | - // (i64.reinterpret(y) & (1 << 63) - // ) - Literal signBit, otherBits; UnaryOp int2float, float2int; BinaryOp bitAnd, bitOr; - switch (curr->op) { case CopySignFloat32: float2int = ReinterpretFloat32; int2float = ReinterpretInt32; bitAnd = AndInt32; bitOr = OrInt32; - signBit = Literal(uint32_t(1U << 31)); - otherBits = Literal(~uint32_t(1U << 31)); + signBit = Literal(uint32_t(1 << 31)); + otherBits = Literal(uint32_t(1 << 31) - 1); break; case CopySignFloat64: @@ -279,8 +269,8 @@ int2float = ReinterpretInt64; bitAnd = AndInt64; bitOr = OrInt64; - signBit = Literal(uint64_t(1ULL << 63)); - otherBits = Literal(~uint64_t(1ULL << 63)); + signBit = Literal(uint64_t(1) << 63); + otherBits = Literal((uint64_t(1) << 63) - 1); break; default: @@ -331,7 +321,7 @@ } void visitGlobalGet(GlobalGet* curr) { - neededImportedGlobals.insert({curr->name, curr->type}); + neededImportedGlobals.insert(std::make_pair(curr->name, curr->type)); } }; diff -Nru binaryen-108/src/passes/RemoveUnusedBrs.cpp binaryen-99/src/passes/RemoveUnusedBrs.cpp --- binaryen-108/src/passes/RemoveUnusedBrs.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RemoveUnusedBrs.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -31,41 +30,13 @@ namespace wasm { -// Grab a slice out of a block, replacing it with nops, and returning -// either another block with the contents (if more than 1) or a single -// expression. -// This does not finalize the input block; it leaves that for the caller. -static Expression* -stealSlice(Builder& builder, Block* input, Index from, Index to) { - Expression* ret; - if (to == from + 1) { - // just one - ret = input->list[from]; - } else { - auto* block = builder.makeBlock(); - for (Index i = from; i < to; i++) { - block->list.push_back(input->list[i]); - } - block->finalize(); - ret = block; - } - if (to == input->list.size()) { - input->list.resize(from); - } else { - for (Index i = from; i < to; i++) { - input->list[i] = builder.makeNop(); - } - } - return ret; -} - // to turn an if into a br-if, we must be able to reorder the // condition and possible value, and the possible value must // not have side effects (as they would run unconditionally) static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue, PassOptions& options, - Module& wasm) { + FeatureSet features) { // if the if isn't even reached, this is all dead code anyhow if (ifCondition->type == Type::unreachable) { return false; @@ -73,18 +44,13 @@ if (!brValue) { return true; } - EffectAnalyzer value(options, wasm, brValue); + EffectAnalyzer value(options, features, brValue); if (value.hasSideEffects()) { return false; } - return !EffectAnalyzer(options, wasm, ifCondition).invalidates(value); + return !EffectAnalyzer(options, features, ifCondition).invalidates(value); } -// This leads to similar choices as LLVM does. -// See https://github.com/WebAssembly/binaryen/pull/4228 -// It can be tuned more later. -const Index TooCostlyToRunUnconditionally = 9; - // Check if it is not worth it to run code unconditionally. This // assumes we are trying to run two expressions where previously // only one of the two might have executed. We assume here that @@ -97,18 +63,9 @@ return false; } // Consider the cost of executing all the code unconditionally. + const auto TOO_MUCH = 7; auto total = CostAnalyzer(one).cost + CostAnalyzer(two).cost; - return total >= TooCostlyToRunUnconditionally; -} - -// As above, but a single expression that we are considering moving to a place -// where it executes unconditionally. -static bool tooCostlyToRunUnconditionally(const PassOptions& passOptions, - Expression* curr) { - if (passOptions.shrinkLevel) { - return false; - } - return CostAnalyzer(curr).cost >= TooCostlyToRunUnconditionally; + return total >= TOO_MUCH; } struct RemoveUnusedBrs : public WalkerPass> { @@ -343,12 +300,13 @@ } void visitIf(If* curr) { + FeatureSet features = getModule()->features; if (!curr->ifFalse) { // if without an else. try to reduce // if (condition) br => br_if (condition) if (Break* br = curr->ifTrue->dynCast()) { if (canTurnIfIntoBrIf( - curr->condition, br->value, getPassOptions(), *getModule())) { + curr->condition, br->value, getPassOptions(), features)) { if (!br->condition) { br->condition = curr->condition; } else { @@ -373,7 +331,7 @@ } // Of course we can't do this if the br's condition has side // effects, as we would then execute those unconditionally. - if (EffectAnalyzer(getPassOptions(), *getModule(), br->condition) + if (EffectAnalyzer(getPassOptions(), features, br->condition) .hasSideEffects()) { return; } @@ -388,34 +346,6 @@ anotherCycle = true; } } - - // if (condition-A) { if (condition-B) .. } - // => - // if (condition-A ? condition-B : 0) { .. } - // - // This replaces an if, which is 3 bytes, with a select plus a zero, which - // is also 3 bytes. The benefit is that the select may be faster, and also - // further optimizations may be possible on the select. - if (auto* child = curr->ifTrue->dynCast()) { - if (child->ifFalse) { - return; - } - // If running the child's condition unconditionally is too expensive, - // give up. - if (tooCostlyToRunUnconditionally(getPassOptions(), child->condition)) { - return; - } - // Of course we can't do this if the inner if's condition has side - // effects, as we would then execute those unconditionally. - if (EffectAnalyzer(getPassOptions(), *getModule(), child->condition) - .hasSideEffects()) { - return; - } - Builder builder(*getModule()); - curr->condition = builder.makeSelect( - child->condition, curr->condition, builder.makeConst(int32_t(0))); - curr->ifTrue = child->ifTrue; - } } // TODO: if-else can be turned into a br_if as well, if one of the sides is // a dead end we handle the case of a returned value to a local.set @@ -501,7 +431,7 @@ // we need the ifTrue to break, so it cannot reach the code we want to // move if (iff->ifTrue->type == Type::unreachable) { - iff->ifFalse = stealSlice(builder, block, i + 1, list.size()); + iff->ifFalse = builder.stealSlice(block, i + 1, list.size()); iff->finalize(); block->finalize(); return true; @@ -546,13 +476,13 @@ if (iff->ifTrue->type == Type::unreachable) { iff->ifFalse = blockifyMerge( - iff->ifFalse, stealSlice(builder, block, i + 1, list.size())); + iff->ifFalse, builder.stealSlice(block, i + 1, list.size())); iff->finalize(); block->finalize(); return true; } else if (iff->ifFalse->type == Type::unreachable) { iff->ifTrue = blockifyMerge( - iff->ifTrue, stealSlice(builder, block, i + 1, list.size())); + iff->ifTrue, builder.stealSlice(block, i + 1, list.size())); iff->finalize(); block->finalize(); return true; @@ -587,8 +517,7 @@ list[i] = builder.makeIf(brIf->condition, builder.makeBreak(brIf->name), - stealSlice(builder, block, i + 1, list.size())); - block->finalize(); + builder.stealSlice(block, i + 1, list.size())); return true; } } @@ -596,7 +525,7 @@ return false; } // if there is control flow, we must stop looking - if (EffectAnalyzer(getPassOptions(), *getModule(), curr) + if (EffectAnalyzer(getPassOptions(), getModule()->features, curr) .transfersControlFlow()) { return false; } @@ -683,82 +612,6 @@ return false; } - // GC-specific optimizations. These are split out from the main code to keep - // things as simple as possible. - bool optimizeGC(Function* func) { - if (!getModule()->features.hasGC()) { - return false; - } - - struct Optimizer : public PostWalker { - bool worked = false; - - void visitBrOn(BrOn* curr) { - // Ignore unreachable BrOns which we cannot improve anyhow. Note that - // we must check the ref field manually, as we may be changing types as - // we go here. (Another option would be to use a TypeUpdater here - // instead of calling ReFinalize at the very end, but that would be more - // complex and slower.) - if (curr->type == Type::unreachable || - curr->ref->type == Type::unreachable) { - return; - } - - // First, check for a possible null which would prevent all other - // optimizations. - // TODO: Look into using BrOnNonNull here, to replace a br_on_func whose - // input is (ref null func) with br_on_non_null (as only the null check - // would be needed). - auto refType = curr->ref->type; - if (refType.isNullable()) { - return; - } - - if (curr->op == BrOnNull) { - // This cannot be null, so the br is never taken, and the non-null - // value flows through. - replaceCurrent(curr->ref); - worked = true; - return; - } - if (curr->op == BrOnNonNull) { - // This cannot be null, so the br is always taken. - replaceCurrent( - Builder(*getModule()).makeBreak(curr->name, curr->ref)); - worked = true; - return; - } - - // Check if the type is the kind we are checking for. - auto result = GCTypeUtils::evaluateKindCheck(curr); - - if (result == GCTypeUtils::Success) { - // The type is what we are looking for, so we can switch from BrOn to - // a simple br which is always taken. - replaceCurrent( - Builder(*getModule()).makeBreak(curr->name, curr->ref)); - worked = true; - } else if (result == GCTypeUtils::Failure) { - // The type is not what we are looking for, so the branch is never - // taken, and the value just flows through. - replaceCurrent(curr->ref); - worked = true; - } - } - } optimizer; - - optimizer.setModule(getModule()); - optimizer.doWalkFunction(func); - - // If we removed any BrOn instructions, that might affect the reachability - // of the things they used to break to, so update types. - if (optimizer.worked) { - ReFinalize().walkFunctionInModule(func, getModule()); - return true; - } - return false; - } - void doWalkFunction(Function* func) { // multiple cycles may be needed do { @@ -775,11 +628,12 @@ if (!flow->value) { // return => nop ExpressionManipulator::nop(flow); + anotherCycle = true; } else { // return with value => value *flows[i] = flow->value; + anotherCycle = true; } - anotherCycle = true; } flows.clear(); // optimize loops (we don't do it while tracking flows, as they can @@ -791,12 +645,10 @@ if (anotherCycle) { ReFinalize().walkFunctionInModule(func, getModule()); } + // sink blocks if (sinkBlocks(func)) { anotherCycle = true; } - if (optimizeGC(func)) { - anotherCycle = true; - } } while (anotherCycle); // thread trivial jumps @@ -897,6 +749,7 @@ // the if is dead // * note that we do this at the end, because un-conditionalizing can // interfere with optimizeLoop()ing. + FeatureSet features = getModule()->features; auto& list = curr->list; for (Index i = 0; i < list.size(); i++) { auto* iff = list[i]->dynCast(); @@ -907,10 +760,8 @@ } auto* ifTrueBreak = iff->ifTrue->dynCast(); if (ifTrueBreak && !ifTrueBreak->condition && - canTurnIfIntoBrIf(iff->condition, - ifTrueBreak->value, - passOptions, - *getModule())) { + canTurnIfIntoBrIf( + iff->condition, ifTrueBreak->value, passOptions, features)) { // we are an if-else where the ifTrue is a break without a // condition, so we can do this ifTrueBreak->condition = iff->condition; @@ -922,10 +773,8 @@ // otherwise, perhaps we can flip the if auto* ifFalseBreak = iff->ifFalse->dynCast(); if (ifFalseBreak && !ifFalseBreak->condition && - canTurnIfIntoBrIf(iff->condition, - ifFalseBreak->value, - passOptions, - *getModule())) { + canTurnIfIntoBrIf( + iff->condition, ifFalseBreak->value, passOptions, features)) { ifFalseBreak->condition = Builder(*getModule()).makeUnary(EqZInt32, iff->condition); ifFalseBreak->finalize(); @@ -954,7 +803,7 @@ if (shrink && br2->type != Type::unreachable) { // Join adjacent br_ifs to the same target, making one br_if // with a "selectified" condition that executes both. - if (!EffectAnalyzer(passOptions, *getModule(), br2->condition) + if (!EffectAnalyzer(passOptions, features, br2->condition) .hasSideEffects()) { // it's ok to execute them both, do it Builder builder(*getModule()); @@ -982,9 +831,10 @@ // This switch has just one target no matter what; replace with a br // if we can (to do so, we must put the condition before a possible // value). - if (!curr->value || - EffectAnalyzer::canReorder( - passOptions, *getModule(), curr->condition, curr->value)) { + if (!curr->value || EffectAnalyzer::canReorder(passOptions, + getModule()->features, + curr->condition, + curr->value)) { Builder builder(*getModule()); replaceCurrent(builder.makeSequence( builder.makeDrop(curr->condition), // might have side effects @@ -995,7 +845,7 @@ // Restructuring of ifs: if we have // (block $x - // (drop (br_if $x (cond))) + // (br_if $x (cond)) // .., no other references to $x // ) // then we can turn that into (if (!cond) ..). @@ -1005,7 +855,7 @@ // If the block has a return value, we can do something similar, removing // the drop from the br_if and putting the if on the outside, // (block $x - // (drop (br_if $x (value) (cond))) + // (br_if $x (value) (cond)) // .., no other references to $x // ..final element.. // ) @@ -1036,73 +886,30 @@ // not have a value, depending on if it was dropped or not. If the // type is unreachable that means it is not actually reached, which we // can ignore. - Builder builder(*getModule()); if (br && br->condition && br->name == curr->name && br->type != Type::unreachable) { if (BranchUtils::BranchSeeker::count(curr, curr->name) == 1) { // no other breaks to that name, so we can do this if (!drop) { assert(!br->value); + Builder builder(*getModule()); replaceCurrent(builder.makeIf( builder.makeUnary(EqZInt32, br->condition), curr)); ExpressionManipulator::nop(br); curr->finalize(curr->type); } else { - // To use an if, the value must have no side effects, as in the - // if it may not execute. - if (!EffectAnalyzer(passOptions, *getModule(), br->value) + // If the items we move around have side effects, we can't do + // this. + // TODO: we could use a select, in some cases..? + FeatureSet features = getModule()->features; + if (!EffectAnalyzer(passOptions, features, br->value) + .hasSideEffects() && + !EffectAnalyzer(passOptions, features, br->condition) .hasSideEffects()) { - // We also need to reorder the condition and the value. - if (EffectAnalyzer::canReorder( - passOptions, *getModule(), br->condition, br->value)) { - ExpressionManipulator::nop(list[0]); - replaceCurrent( - builder.makeIf(br->condition, br->value, curr)); - } - } else { - // The value has side effects, so it must always execute. We - // may still be able to optimize this, however, by using a - // select: - // (block $x - // (drop (br_if $x (value) (cond))) - // ..., no other references to $x - // ..final element.. - // ) - // => - // (select - // (value) - // (block $x - // ..., no other references to $x - // ..final element.. - // ) - // (cond) - // ) - // To do this we must be able to reorder the condition with - // the rest of the block (but not the value), and we must be - // able to make the rest of the block always execute, so it - // must not have side effects. - // TODO: we can do this when there *are* other refs to $x, - // with a larger refactoring here. - - // Test for the conditions with a temporary nop instead of the - // br_if. - Expression* old = list[0]; - Nop nop; - // After this assignment, curr is what is left in the block - // after ignoring the br_if. - list[0] = &nop; - auto canReorder = EffectAnalyzer::canReorder( - passOptions, *getModule(), br->condition, curr); - auto hasSideEffects = - EffectAnalyzer(passOptions, *getModule(), curr) - .hasSideEffects(); - list[0] = old; - if (canReorder && !hasSideEffects && - Properties::canEmitSelectWithArms(br->value, curr)) { - ExpressionManipulator::nop(list[0]); - replaceCurrent( - builder.makeSelect(br->condition, br->value, curr)); - } + ExpressionManipulator::nop(list[0]); + Builder builder(*getModule()); + replaceCurrent( + builder.makeIf(br->condition, br->value, curr)); } } } @@ -1119,11 +926,8 @@ // Convert an if into a select, if possible and beneficial to do so. Select* selectify(If* iff) { - // Only an if-else can be turned into a select. - if (!iff->ifFalse) { - return nullptr; - } - if (!Properties::canEmitSelectWithArms(iff->ifTrue, iff->ifFalse)) { + if (!iff->ifFalse || !iff->ifTrue->type.isSingle() || + !iff->ifFalse->type.isSingle()) { return nullptr; } if (iff->condition->type == Type::unreachable) { @@ -1146,20 +950,21 @@ } // Check if side effects allow this: we need to execute the two arms // unconditionally, and also to make the condition run last. - EffectAnalyzer ifTrue(passOptions, *getModule(), iff->ifTrue); + FeatureSet features = getModule()->features; + EffectAnalyzer ifTrue(passOptions, features, iff->ifTrue); if (ifTrue.hasSideEffects()) { return nullptr; } - EffectAnalyzer ifFalse(passOptions, *getModule(), iff->ifFalse); + EffectAnalyzer ifFalse(passOptions, features, iff->ifFalse); if (ifFalse.hasSideEffects()) { return nullptr; } - EffectAnalyzer condition(passOptions, *getModule(), iff->condition); + EffectAnalyzer condition(passOptions, features, iff->condition); if (condition.invalidates(ifTrue) || condition.invalidates(ifFalse)) { return nullptr; } return Builder(*getModule()) - .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse, iff->type); + .makeSelect(iff->condition, iff->ifTrue, iff->ifFalse); } void visitLocalSet(LocalSet* curr) { @@ -1363,15 +1168,7 @@ // dce will clean it up return nullptr; } - auto* condition = br->condition; - // Also support eqz, which is the same as == 0. - if (auto* unary = condition->dynCast()) { - if (unary->op == EqZInt32) { - return br; - } - return nullptr; - } - auto* binary = condition->dynCast(); + auto* binary = br->condition->dynCast(); if (!binary) { return nullptr; } @@ -1397,29 +1194,16 @@ if (!br) { return nullptr; } - auto* condition = br->condition; - if (auto* binary = condition->dynCast()) { - return binary->left; - } else if (auto* unary = condition->dynCast()) { - assert(unary->op == EqZInt32); - return unary->value; - } else { - WASM_UNREACHABLE("invalid br_if condition"); - } + return br->condition->cast()->left; }; // returns the constant value, as a uint32_t auto getProperBrIfConstant = [&getProperBrIf](Expression* curr) -> uint32_t { - auto* condition = getProperBrIf(curr)->condition; - if (auto* binary = condition->dynCast()) { - return binary->right->cast()->value.geti32(); - } else if (auto* unary = condition->dynCast()) { - assert(unary->op == EqZInt32); - return 0; - } else { - WASM_UNREACHABLE("invalid br_if condition"); - } + return getProperBrIf(curr) + ->condition->cast() + ->right->cast() + ->value.geti32(); }; Index start = 0; while (start < list.size() - 1) { @@ -1428,17 +1212,9 @@ start++; continue; } - // If the first condition value is a tee, that is ok, so long as the - // others afterwards are gets of the value that is tee'd. - LocalGet get; - if (auto* tee = conditionValue->dynCast()) { - get.index = tee->index; - get.type = getFunction()->getLocalType(get.index); - conditionValue = &get; - } // if the condition has side effects, we can't replace many // appearances of it with a single one - if (EffectAnalyzer(passOptions, *getModule(), conditionValue) + if (EffectAnalyzer(passOptions, getModule()->features, conditionValue) .hasSideEffects()) { start++; continue; @@ -1503,15 +1279,13 @@ } Builder builder(*getModule()); // the table and condition are offset by the min - auto* newCondition = getProperBrIfConditionValue(list[start]); - if (min != 0) { - newCondition = builder.makeBinary( - SubInt32, newCondition, builder.makeConst(int32_t(min))); + conditionValue = builder.makeBinary( + SubInt32, conditionValue, builder.makeConst(int32_t(min))); } list[end - 1] = builder.makeBlock( defaultName, - builder.makeSwitch(table, defaultName, newCondition)); + builder.makeSwitch(table, defaultName, conditionValue)); for (Index i = start; i < end - 1; i++) { ExpressionManipulator::nop(list[i]); } diff -Nru binaryen-108/src/passes/RemoveUnusedModuleElements.cpp binaryen-99/src/passes/RemoveUnusedModuleElements.cpp --- binaryen-108/src/passes/RemoveUnusedModuleElements.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RemoveUnusedModuleElements.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -16,23 +16,20 @@ // // Removes module elements that are are never used: functions, globals, and -// tags, which may be imported or not, and function types (which we merge and +// events, which may be imported or not, and function types (which we merge and // remove if unneeded) // #include -#include "ir/element-utils.h" -#include "ir/intrinsics.h" #include "ir/module-utils.h" #include "ir/utils.h" #include "pass.h" -#include "wasm-builder.h" #include "wasm.h" namespace wasm { -enum class ModuleElementKind { Function, Global, Tag, Table, ElementSegment }; +enum class ModuleElementKind { Function, Global, Event }; typedef std::pair ModuleElement; @@ -44,27 +41,7 @@ std::vector queue; std::set reachable; bool usesMemory = false; - - // The signatures that we have seen a call_ref for. When we see a RefFunc of a - // signature in here, we know it is reachable. - std::unordered_set calledSignatures; - - // All the RefFuncs we've seen, grouped by heap type. When we see a CallRef of - // one of the types here, we know all the RefFuncs corresponding to it are - // reachable. This is the reverse side of calledSignatures: for a function to - // be reached via a reference, we need the combination of a RefFunc of it as - // well as a CallRef of that, and we may see them in any order. (Or, if the - // RefFunc is in a table, we need a CallIndirect, which is handled in the - // table logic.) - // - // After we see a call for a type, we can clear out the entry here for it, as - // we'll have that type in calledSignatures, and so this contains only - // RefFuncs that we have not seen a call for yet, hence "uncalledRefFuncMap." - // - // TODO: We assume a closed world in the GC space atm, but eventually should - // have a flag for that, and when the world is not closed we'd need to - // check for RefFuncs that flow out to exports or imports - std::unordered_map> uncalledRefFuncMap; + bool usesTable = false; ReachabilityAnalyzer(Module* module, const std::vector& roots) : module(module) { @@ -75,113 +52,51 @@ walk(segment.offset); } } - for (auto& segment : module->elementSegments) { - if (segment->table.is()) { - walk(segment->offset); - } + for (auto& segment : module->table.segments) { + walk(segment.offset); } - // main loop while (queue.size()) { - auto curr = queue.back(); + auto& curr = queue.back(); queue.pop_back(); - if (reachable.emplace(curr).second) { - auto& [kind, value] = curr; - if (kind == ModuleElementKind::Function) { + if (reachable.count(curr) == 0) { + reachable.insert(curr); + if (curr.first == ModuleElementKind::Function) { // if not an import, walk it - auto* func = module->getFunction(value); + auto* func = module->getFunction(curr.second); if (!func->imported()) { walk(func->body); } - } else if (kind == ModuleElementKind::Global) { + } else if (curr.first == ModuleElementKind::Global) { // if not imported, it has an init expression we need to walk - auto* global = module->getGlobal(value); + auto* global = module->getGlobal(curr.second); if (!global->imported()) { walk(global->init); } - } else if (kind == ModuleElementKind::Table) { - ModuleUtils::iterTableSegments( - *module, curr.second, [&](ElementSegment* segment) { - walk(segment->offset); - }); } } } } - void maybeAdd(ModuleElement element) { - if (reachable.count(element) == 0) { - queue.emplace_back(element); - } - } - - // Add a reference to a table and all its segments and elements. - void maybeAddTable(Name name) { - maybeAdd(ModuleElement(ModuleElementKind::Table, name)); - ModuleUtils::iterTableSegments(*module, name, [&](ElementSegment* segment) { - maybeAdd(ModuleElement(ModuleElementKind::ElementSegment, segment->name)); - }); - } - void visitCall(Call* curr) { - maybeAdd(ModuleElement(ModuleElementKind::Function, curr->target)); - - if (Intrinsics(*module).isCallWithoutEffects(curr)) { - // A call-without-effects receives a function reference and calls it, the - // same as a CallRef. When we have a flag for non-closed-world, we should - // handle this automatically by the reference flowing out to an import, - // which is what binaryen intrinsics look like. For now, to support use - // cases of a closed world but that also use this intrinsic, handle the - // intrinsic specifically here. - auto* target = curr->operands.back(); - if (auto* refFunc = target->dynCast()) { - // We can see exactly where this goes. - Call call(module->allocator); - call.target = refFunc->func; - visitCall(&call); - } else { - // All we can see is the type, so do a CallRef of that. - CallRef callRef(module->allocator); - callRef.target = target; - visitCallRef(&callRef); - } + if (reachable.count( + ModuleElement(ModuleElementKind::Function, curr->target)) == 0) { + queue.emplace_back(ModuleElementKind::Function, curr->target); } } - - void visitCallIndirect(CallIndirect* curr) { maybeAddTable(curr->table); } - - void visitCallRef(CallRef* curr) { - // Ignore unreachable code. - if (!curr->target->type.isRef()) { - return; - } - - auto type = curr->target->type.getHeapType(); - - // Call all the functions of that signature. We can then forget about - // them, as this signature will be marked as called. - auto iter = uncalledRefFuncMap.find(type); - if (iter != uncalledRefFuncMap.end()) { - // We must not have a type in both calledSignatures and - // uncalledRefFuncMap: once it is called, we do not track RefFuncs for - // it any more. - assert(calledSignatures.count(type) == 0); - - for (Name target : iter->second) { - maybeAdd(ModuleElement(ModuleElementKind::Function, target)); - } - - uncalledRefFuncMap.erase(iter); - } - - calledSignatures.insert(type); - } + void visitCallIndirect(CallIndirect* curr) { usesTable = true; } void visitGlobalGet(GlobalGet* curr) { - maybeAdd(ModuleElement(ModuleElementKind::Global, curr->name)); + if (reachable.count(ModuleElement(ModuleElementKind::Global, curr->name)) == + 0) { + queue.emplace_back(ModuleElementKind::Global, curr->name); + } } void visitGlobalSet(GlobalSet* curr) { - maybeAdd(ModuleElement(ModuleElementKind::Global, curr->name)); + if (reachable.count(ModuleElement(ModuleElementKind::Global, curr->name)) == + 0) { + queue.emplace_back(ModuleElementKind::Global, curr->name); + } } void visitLoad(Load* curr) { usesMemory = true; } @@ -198,30 +113,21 @@ void visitMemorySize(MemorySize* curr) { usesMemory = true; } void visitMemoryGrow(MemoryGrow* curr) { usesMemory = true; } void visitRefFunc(RefFunc* curr) { - auto type = curr->type.getHeapType(); - if (calledSignatures.count(type)) { - // We must not have a type in both calledSignatures and - // uncalledRefFuncMap: once it is called, we do not track RefFuncs for it - // any more. - assert(uncalledRefFuncMap.count(type) == 0); - - // We've seen a RefFunc for this, so it is reachable. - maybeAdd(ModuleElement(ModuleElementKind::Function, curr->func)); - } else { - // We've never seen a CallRef for this, but might see one later. - uncalledRefFuncMap[type].insert(curr->func); + if (reachable.count( + ModuleElement(ModuleElementKind::Function, curr->func)) == 0) { + queue.emplace_back(ModuleElementKind::Function, curr->func); } } - void visitTableGet(TableGet* curr) { maybeAddTable(curr->table); } - void visitTableSet(TableSet* curr) { maybeAddTable(curr->table); } - void visitTableSize(TableSize* curr) { maybeAddTable(curr->table); } - void visitTableGrow(TableGrow* curr) { maybeAddTable(curr->table); } void visitThrow(Throw* curr) { - maybeAdd(ModuleElement(ModuleElementKind::Tag, curr->tag)); + if (reachable.count(ModuleElement(ModuleElementKind::Event, curr->event)) == + 0) { + queue.emplace_back(ModuleElementKind::Event, curr->event); + } } - void visitTry(Try* curr) { - for (auto tag : curr->catchTags) { - maybeAdd(ModuleElement(ModuleElementKind::Tag, tag)); + void visitBrOnExn(BrOnExn* curr) { + if (reachable.count(ModuleElement(ModuleElementKind::Event, curr->event)) == + 0) { + queue.emplace_back(ModuleElementKind::Event, curr->event); } } }; @@ -238,7 +144,7 @@ if (module->start.is()) { auto startFunction = module->getFunction(module->start); // Can be skipped if the start function is empty. - if (!startFunction->imported() && startFunction->body->is()) { + if (startFunction->body->is()) { module->start.clear(); } else { roots.emplace_back(ModuleElementKind::Function, module->start); @@ -250,117 +156,53 @@ roots.emplace_back(ModuleElementKind::Function, func->name); }); } - ModuleUtils::iterActiveElementSegments( - *module, [&](ElementSegment* segment) { - auto table = module->getTable(segment->table); - if (table->imported() && !segment->data.empty()) { - roots.emplace_back(ModuleElementKind::ElementSegment, segment->name); - } - }); // Exports are roots. bool exportsMemory = false; + bool exportsTable = false; for (auto& curr : module->exports) { if (curr->kind == ExternalKind::Function) { roots.emplace_back(ModuleElementKind::Function, curr->value); } else if (curr->kind == ExternalKind::Global) { roots.emplace_back(ModuleElementKind::Global, curr->value); - } else if (curr->kind == ExternalKind::Tag) { - roots.emplace_back(ModuleElementKind::Tag, curr->value); - } else if (curr->kind == ExternalKind::Table) { - roots.emplace_back(ModuleElementKind::Table, curr->value); - ModuleUtils::iterTableSegments( - *module, curr->value, [&](ElementSegment* segment) { - roots.emplace_back(ModuleElementKind::ElementSegment, - segment->name); - }); + } else if (curr->kind == ExternalKind::Event) { + roots.emplace_back(ModuleElementKind::Event, curr->value); } else if (curr->kind == ExternalKind::Memory) { exportsMemory = true; + } else if (curr->kind == ExternalKind::Table) { + exportsTable = true; } } // Check for special imports, which are roots. bool importsMemory = false; + bool importsTable = false; if (module->memory.imported()) { importsMemory = true; } + if (module->table.imported()) { + importsTable = true; + } // For now, all functions that can be called indirectly are marked as roots. - // TODO: Compute this based on which ElementSegments are actually reachable, - // and which functions have a call_indirect of the proper type. - ElementUtils::iterAllElementFunctionNames(module, [&](Name& name) { - roots.emplace_back(ModuleElementKind::Function, name); - }); - // Compute reachability starting from the root set. - ReachabilityAnalyzer analyzer(module, roots); - - // RefFuncs that are never called are a special case: We cannot remove the - // function, since then (ref.func $foo) would not validate. But if we know - // it is never called, at least the contents do not matter, so we can - // empty it out. - std::unordered_set uncalledRefFuncs; - for (auto& [type, targets] : analyzer.uncalledRefFuncMap) { - for (auto target : targets) { - uncalledRefFuncs.insert(target); + for (auto& segment : module->table.segments) { + for (auto& curr : segment.data) { + roots.emplace_back(ModuleElementKind::Function, curr); } - - // We cannot have a type in both this map and calledSignatures. - assert(analyzer.calledSignatures.count(type) == 0); - } - -#ifndef NDEBUG - for (auto type : analyzer.calledSignatures) { - assert(analyzer.uncalledRefFuncMap.count(type) == 0); } -#endif - + // Compute reachability starting from the root set. + ReachabilityAnalyzer analyzer(module, roots); // Remove unreachable elements. module->removeFunctions([&](Function* curr) { - if (analyzer.reachable.count( - ModuleElement(ModuleElementKind::Function, curr->name))) { - // This is reached. - return false; - } - - if (uncalledRefFuncs.count(curr->name)) { - // This is not reached, but has a reference. See comment above on - // uncalledRefFuncs. - if (!curr->imported()) { - curr->body = Builder(*module).makeUnreachable(); - } - return false; - } - - // The function is not reached and has no reference; remove it. - return true; + return analyzer.reachable.count( + ModuleElement(ModuleElementKind::Function, curr->name)) == 0; }); module->removeGlobals([&](Global* curr) { return analyzer.reachable.count( ModuleElement(ModuleElementKind::Global, curr->name)) == 0; }); - module->removeTags([&](Tag* curr) { + module->removeEvents([&](Event* curr) { return analyzer.reachable.count( - ModuleElement(ModuleElementKind::Tag, curr->name)) == 0; - }); - module->removeElementSegments([&](ElementSegment* curr) { - return curr->data.empty() || - analyzer.reachable.count(ModuleElement( - ModuleElementKind::ElementSegment, curr->name)) == 0; - }); - // Since we've removed all empty element segments, here we mark all tables - // that have a segment left. - std::unordered_set nonemptyTables; - ModuleUtils::iterActiveElementSegments( - *module, - [&](ElementSegment* segment) { nonemptyTables.insert(segment->table); }); - module->removeTables([&](Table* curr) { - return (nonemptyTables.count(curr->name) == 0 || !curr->imported()) && - analyzer.reachable.count( - ModuleElement(ModuleElementKind::Table, curr->name)) == 0; + ModuleElement(ModuleElementKind::Event, curr->name)) == 0; }); - // TODO: After removing elements, we may be able to remove more things, and - // should continue to work. (For example, after removing a reference - // to a function from an element segment, we may be able to remove - // that function, etc.) - - // Handle the memory + // Handle the memory and table if (!exportsMemory && !analyzer.usesMemory) { if (!importsMemory) { // The memory is unobservable to the outside, we can remove the @@ -374,6 +216,18 @@ module->memory.max = 0; } } + if (!exportsTable && !analyzer.usesTable) { + if (!importsTable) { + // The table is unobservable to the outside, we can remove the contents. + module->table.segments.clear(); + } + if (module->table.segments.empty()) { + module->table.exists = false; + module->table.module = module->table.base = Name(); + module->table.initial = 0; + module->table.max = 0; + } + } } }; diff -Nru binaryen-108/src/passes/RemoveUnusedNames.cpp binaryen-99/src/passes/RemoveUnusedNames.cpp --- binaryen-108/src/passes/RemoveUnusedNames.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RemoveUnusedNames.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -21,7 +21,6 @@ #include #include -#include #include namespace wasm { @@ -38,11 +37,16 @@ std::map> branchesSeen; void visitExpression(Expression* curr) { - BranchUtils::operateOnScopeNameUses(curr, [&](Name& name) { - if (name.is()) { - branchesSeen[name].insert(curr); - } - }); + if (auto* block = curr->dynCast()) { + visitBlock(block); + return; + } + if (auto* loop = curr->dynCast()) { + visitLoop(loop); + return; + } + BranchUtils::operateOnScopeNameUses( + curr, [&](Name& name) { branchesSeen[name].insert(curr); }); } void handleBreakTarget(Name& name) { @@ -79,18 +83,7 @@ } } - void visitTry(Try* curr) { - handleBreakTarget(curr->name); - // Try has not just a break target but also an optional delegate with a - // target name, so call the generic visitor as well to handle that. - visitExpression(curr); - } - - void visitFunction(Function* curr) { - // When we reach the function body we can erase delegations to the caller. - branchesSeen.erase(DELEGATE_CALLER_TARGET); - assert(branchesSeen.empty()); - } + void visitFunction(Function* curr) { assert(branchesSeen.empty()); } }; Pass* createRemoveUnusedNamesPass() { return new RemoveUnusedNames(); } diff -Nru binaryen-108/src/passes/ReorderFunctions.cpp binaryen-99/src/passes/ReorderFunctions.cpp --- binaryen-108/src/passes/ReorderFunctions.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/ReorderFunctions.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -24,12 +24,11 @@ // a less beneficial position for compression, that is, mutually-compressible // functions are no longer together (when they were before, in the original // order, the has some natural tendency one way or the other). TODO: investigate -// similarity ordering here (see #4322) +// similarity ordering here. // #include -#include #include #include @@ -71,8 +70,11 @@ for (auto& curr : module->exports) { counts[curr->value]++; } - ElementUtils::iterAllElementFunctionNames( - module, [&](Name& name) { counts[name]++; }); + for (auto& segment : module->table.segments) { + for (auto& curr : segment.data) { + counts[curr]++; + } + } // sort std::sort(module->functions.begin(), module->functions.end(), diff -Nru binaryen-108/src/passes/ReorderLocals.cpp binaryen-99/src/passes/ReorderLocals.cpp --- binaryen-108/src/passes/ReorderLocals.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/ReorderLocals.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -50,10 +50,10 @@ return; // nothing to do. All locals are parameters } Index num = curr->getNumLocals(); - counts.clear(); counts.resize(num); - firstUses.clear(); - firstUses.resize(num, Unseen); + std::fill(counts.begin(), counts.end(), 0); + firstUses.resize(num); + std::fill(firstUses.begin(), firstUses.end(), Unseen); // Gather information about local usages. walk(curr->body); // Use the information about local usages. @@ -82,7 +82,7 @@ return counts[a] > counts[b]; }); // sorting left params in front, perhaps slightly reordered. verify and fix. - size_t numParams = curr->getParams().size(); + size_t numParams = curr->sig.params.size(); for (size_t i = 0; i < numParams; i++) { assert(newToOld[i] < numParams); newToOld[i] = i; diff -Nru binaryen-108/src/passes/ReReloop.cpp binaryen-99/src/passes/ReReloop.cpp --- binaryen-108/src/passes/ReReloop.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/ReReloop.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -94,7 +94,6 @@ // we work using a stack of control flow tasks struct Task { - virtual ~Task() = default; ReReloop& parent; Task(ReReloop& parent) : parent(parent) {} virtual void run() { WASM_UNREACHABLE("unimpl"); } @@ -228,8 +227,9 @@ for (Index i = 0; i < num; i++) { targetValues[targets[i]].insert(i); } - for (auto& [name, indices] : targetValues) { - parent.addSwitchBranch(before, parent.getBreakTarget(name), indices); + for (auto& iter : targetValues) { + parent.addSwitchBranch( + before, parent.getBreakTarget(iter.first), iter.second); } // the default may be among the targets, in which case, we can't add it // simply as it would be a duplicate, so create a temp block @@ -278,7 +278,8 @@ ReturnTask::handle(*this, ret); } else if (auto* un = curr->dynCast()) { UnreachableTask::handle(*this, un); - } else if (curr->is() || curr->is() || curr->is()) { + } else if (curr->is() || curr->is() || curr->is() || + curr->is()) { Fatal() << "ReReloop does not support EH instructions yet"; } else { // not control flow, so just a simple element @@ -317,7 +318,7 @@ for (auto& cfgBlock : relooper->Blocks) { auto* block = cfgBlock->Code->cast(); if (cfgBlock->BranchesOut.empty() && block->type != Type::unreachable) { - block->list.push_back(function->getResults() == Type::none + block->list.push_back(function->sig.results == Type::none ? (Expression*)builder->makeReturn() : (Expression*)builder->makeUnreachable()); block->finalize(); @@ -327,7 +328,9 @@ std::cout << "rerelooping " << function->name << '\n'; for (auto* block : relooper->Blocks) { std::cout << block << " block:\n" << block->Code << '\n'; - for (auto& [target, branch] : block->BranchesOut) { + for (auto& pair : block->BranchesOut) { + auto* target = pair.first; + auto* branch = pair.second; std::cout << "branch to " << target << "\n"; if (branch->Condition) { std::cout << " with condition\n" << branch->Condition << '\n'; @@ -348,7 +351,7 @@ // because of the relooper's boilerplate switch-handling // code, for example, which could be optimized out later // but isn't yet), then make sure it has a proper type - if (function->getResults() != Type::none && + if (function->sig.results != Type::none && function->body->type == Type::none) { function->body = builder.makeSequence(function->body, builder.makeUnreachable()); diff -Nru binaryen-108/src/passes/RoundTrip.cpp binaryen-99/src/passes/RoundTrip.cpp --- binaryen-108/src/passes/RoundTrip.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/RoundTrip.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -25,28 +25,25 @@ #include "wasm-binary.h" #include "wasm.h" +using namespace std; + namespace wasm { struct RoundTrip : public Pass { void run(PassRunner* runner, Module* module) override { BufferWithRandomAccess buffer; // Save features, which would not otherwise make it through a round trip if - // the target features section has been stripped. We also need them in order - // to tell the builder which features to build with. + // the target features section has been stripped. auto features = module->features; // Write, clear, and read the module WasmBinaryWriter(module, buffer).write(); ModuleUtils::clearModule(*module); auto input = buffer.getAsChars(); - WasmBinaryBuilder parser(*module, features, input); + WasmBinaryBuilder parser(*module, input); parser.setDWARF(runner->options.debugInfo); - try { - parser.read(); - } catch (ParseException& p) { - p.dump(std::cerr); - std::cerr << '\n'; - Fatal() << "error in parsing wasm binary"; - } + parser.read(); + // Reapply features + module->features = features; } }; diff -Nru binaryen-108/src/passes/SafeHeap.cpp binaryen-99/src/passes/SafeHeap.cpp --- binaryen-108/src/passes/SafeHeap.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SafeHeap.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,6 @@ #include "asmjs/shared-constants.h" #include "ir/bits.h" -#include "ir/find_all.h" #include "ir/import-utils.h" #include "ir/load-utils.h" #include "pass.h" @@ -64,21 +63,30 @@ } struct AccessInstrumenter : public WalkerPass> { - // A set of function that we should ignore (not instrument). - std::set ignoreFunctions; + // If the getSbrkPtr function is implemented in the wasm, we must not + // instrument that, as it would lead to infinite recursion of it calling + // SAFE_HEAP_LOAD that calls it and so forth. + // As well as the getSbrkPtr function we also avoid instrumenting the + // module start function. This is because this function is used in + // shared memory builds to load the passive memory segments, which in + // turn means that value of sbrk() is not available. + Name getSbrkPtr; bool isFunctionParallel() override { return true; } AccessInstrumenter* create() override { - return new AccessInstrumenter(ignoreFunctions); + return new AccessInstrumenter(getSbrkPtr); } - AccessInstrumenter(std::set ignoreFunctions) - : ignoreFunctions(ignoreFunctions) {} + AccessInstrumenter(Name getSbrkPtr) : getSbrkPtr(getSbrkPtr) {} void visitLoad(Load* curr) { - if (ignoreFunctions.count(getFunction()->name) != 0 || - curr->type == Type::unreachable) { + // As well as the getSbrkPtr function we also avoid insturmenting the + // module start function. This is because this function is used in + // shared memory builds to load the passive memory segments, which in + // turn means that value of sbrk() is not available. + if (getFunction()->name == getModule()->start || + getFunction()->name == getSbrkPtr || curr->type == Type::unreachable) { return; } Builder builder(*getModule()); @@ -89,8 +97,8 @@ } void visitStore(Store* curr) { - if (ignoreFunctions.count(getFunction()->name) != 0 || - curr->type == Type::unreachable) { + if (getFunction()->name == getModule()->start || + getFunction()->name == getSbrkPtr || curr->type == Type::unreachable) { return; } Builder builder(*getModule()); @@ -101,31 +109,6 @@ } }; -static std::set findCalledFunctions(Module* module, Name startFunc) { - std::set called; - std::vector toVisit; - - auto addFunction = [&](Name name) { - if (called.insert(name).second) { - toVisit.push_back(name); - } - }; - - if (startFunc.is()) { - addFunction(startFunc); - while (!toVisit.empty()) { - auto next = toVisit.back(); - toVisit.pop_back(); - auto* func = module->getFunction(next); - for (auto* call : FindAll(func->body).list) { - addFunction(call->target); - } - } - } - - return called; -} - struct SafeHeap : public Pass { PassOptions options; @@ -134,20 +117,12 @@ // add imports addImports(module); // instrument loads and stores - // We avoid instrumenting the module start function of any function that it - // directly calls. This is because in some cases the linker generates - // `__wasm_init_memory` (either as the start function or a function directly - // called from it) and this function is used in shared memory builds to load - // the passive memory segments, which in turn means that value of sbrk() is - // not available until after it has run. - std::set ignoreFunctions = findCalledFunctions(module, module->start); - ignoreFunctions.insert(getSbrkPtr); - AccessInstrumenter(ignoreFunctions).run(runner, module); + AccessInstrumenter(getSbrkPtr).run(runner, module); // add helper checking funcs and imports addGlobals(module, module->features); } - Name getSbrkPtr, dynamicTopPtr, sbrk, segfault, alignfault; + Name dynamicTopPtr, getSbrkPtr, sbrk, segfault, alignfault; void addImports(Module* module) { ImportInfo info(*module); @@ -159,33 +134,32 @@ } else if (auto* existing = info.getImportedFunction(ENV, SBRK)) { sbrk = existing->name; } else { - auto import = Builder::makeFunction( - GET_SBRK_PTR, Signature(Type::none, indexType), {}); - getSbrkPtr = GET_SBRK_PTR; + auto* import = new Function; + import->name = getSbrkPtr = GET_SBRK_PTR; import->module = ENV; import->base = GET_SBRK_PTR; - module->addFunction(std::move(import)); + import->sig = Signature(Type::none, indexType); + module->addFunction(import); } if (auto* existing = info.getImportedFunction(ENV, SEGFAULT_IMPORT)) { segfault = existing->name; } else { - auto import = Builder::makeFunction( - SEGFAULT_IMPORT, Signature(Type::none, Type::none), {}); - segfault = SEGFAULT_IMPORT; + auto* import = new Function; + import->name = segfault = SEGFAULT_IMPORT; import->module = ENV; import->base = SEGFAULT_IMPORT; - module->addFunction(std::move(import)); + import->sig = Signature(Type::none, Type::none); + module->addFunction(import); } if (auto* existing = info.getImportedFunction(ENV, ALIGNFAULT_IMPORT)) { alignfault = existing->name; } else { - auto import = Builder::makeFunction( - ALIGNFAULT_IMPORT, Signature(Type::none, Type::none), {}); - - alignfault = ALIGNFAULT_IMPORT; + auto* import = new Function; + import->name = alignfault = ALIGNFAULT_IMPORT; import->module = ENV; import->base = ALIGNFAULT_IMPORT; - module->addFunction(std::move(import)); + import->sig = Signature(Type::none, Type::none); + module->addFunction(import); } } @@ -272,10 +246,12 @@ if (module->getFunctionOrNull(name)) { return; } + auto* func = new Function; + func->name = name; // pointer, offset auto indexType = module->memory.indexType; - auto funcSig = Signature({indexType, indexType}, style.type); - auto func = Builder::makeFunction(name, funcSig, {indexType}); + func->sig = Signature({indexType, indexType}, style.type); + func->vars.push_back(indexType); // pointer + offset Builder builder(*module); auto* block = builder.makeBlock(); block->list.push_back(builder.makeLocalSet( @@ -303,7 +279,7 @@ block->list.push_back(last); block->finalize(style.type); func->body = block; - module->addFunction(std::move(func)); + module->addFunction(func); } // creates a function for a particular type of store @@ -312,11 +288,12 @@ if (module->getFunctionOrNull(name)) { return; } - auto indexType = module->memory.indexType; + auto* func = new Function; + func->name = name; // pointer, offset, value - auto funcSig = - Signature({indexType, indexType, style.valueType}, Type::none); - auto func = Builder::makeFunction(name, funcSig, {indexType}); + auto indexType = module->memory.indexType; + func->sig = Signature({indexType, indexType, style.valueType}, Type::none); + func->vars.push_back(indexType); // pointer + offset Builder builder(*module); auto* block = builder.makeBlock(); block->list.push_back(builder.makeLocalSet( @@ -339,7 +316,7 @@ block->list.push_back(store); block->finalize(Type::none); func->body = block; - module->addFunction(std::move(func)); + module->addFunction(func); } Expression* diff -Nru binaryen-108/src/passes/SetGlobals.cpp binaryen-99/src/passes/SetGlobals.cpp --- binaryen-108/src/passes/SetGlobals.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SetGlobals.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Assigns values to specified globals. This can be useful to perform a minor -// customization of an existing wasm file. - -#include "pass.h" -#include "support/string.h" -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm { - -struct SetGlobals : public Pass { - void run(PassRunner* runner, Module* module) override { - Name input = runner->options.getArgument( - "set-globals", - "SetGlobals usage: wasm-opt --pass-arg=set-globals@x=y,z=w"); - - // The input is a set of X=Y pairs separated by commas. - String::Split pairs(input.str, ","); - for (auto& pair : pairs) { - String::Split nameAndValue(pair, "="); - auto name = nameAndValue[0]; - auto value = nameAndValue[1]; - auto* glob = module->getGlobalOrNull(name); - if (!glob) { - std::cerr << "warning: could not find global: " << name << '\n'; - } - // Parse the input. - Literal lit; - if (glob->type == Type::i32) { - lit = Literal(int32_t(stoi(value))); - } else if (glob->type == Type::i64) { - lit = Literal(int64_t(stoll(value))); - } else { - Fatal() << "global's type is not supported: " << name; - } - // The global now has a value, and is not imported. - glob->init = Builder(*module).makeConst(lit); - glob->module = glob->base = Name(); - } - } -}; - -// declare pass - -Pass* createSetGlobalsPass() { return new SetGlobals(); } - -} // namespace wasm diff -Nru binaryen-108/src/passes/SignaturePruning.cpp binaryen-99/src/passes/SignaturePruning.cpp --- binaryen-108/src/passes/SignaturePruning.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SignaturePruning.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,230 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Remove params from signature/function types where possible. -// -// This differs from DeadArgumentElimination in that DAE will look at each -// function by itself, and cannot handle indirectly-called functions. This pass -// looks at each heap type at a time, and if all functions with a heap type do -// not use a particular param, will remove the param. -// -// Like in DAE, as part of pruning parameters this will find parameters that are -// always sent the same constant value. We can then apply that value in the -// function, making the parameter's value unused, which means we can prune it. -// - -#include "ir/find_all.h" -#include "ir/lubs.h" -#include "ir/module-utils.h" -#include "ir/type-updating.h" -#include "param-utils.h" -#include "pass.h" -#include "support/sorted_vector.h" -#include "wasm-type.h" -#include "wasm.h" - -namespace wasm { - -namespace { - -struct SignaturePruning : public Pass { - // Maps each heap type to the possible pruned heap type. We will fill this - // during analysis and then use it while doing an update of the types. If a - // type has no improvement that we can find, it will not appear in this map. - std::unordered_map newSignatures; - - void run(PassRunner* runner, Module* module) override { - if (getTypeSystem() != TypeSystem::Nominal) { - Fatal() << "SignaturePruning requires nominal typing"; - } - - if (!module->tables.empty()) { - // When there are tables we must also take their types into account, which - // would require us to take call_indirect, element segments, etc. into - // account. For now, do nothing if there are tables. - // TODO - return; - } - - // First, find all the information we need. Start by collecting inside each - // function in parallel. - - struct Info { - std::vector calls; - std::vector callRefs; - - std::unordered_set usedParams; - - // If we set this to false, we may not attempt to perform any optimization - // whatsoever on this data. - bool optimizable = true; - }; - - ModuleUtils::ParallelFunctionAnalysis analysis( - *module, [&](Function* func, Info& info) { - if (func->imported()) { - // Imports cannot be modified. - info.optimizable = false; - return; - } - - info.calls = std::move(FindAll(func->body).list); - info.callRefs = std::move(FindAll(func->body).list); - info.usedParams = ParamUtils::getUsedParams(func); - }); - - // A map of types to all the information combined over all the functions - // with that type. - std::unordered_map allInfo; - - // Map heap types to all functions with that type. - std::unordered_map> sigFuncs; - - // Combine all the information we gathered into that map. - for (auto& [func, info] : analysis.map) { - // For direct calls, add each call to the type of the function being - // called. - for (auto* call : info.calls) { - allInfo[module->getFunction(call->target)->type].calls.push_back(call); - } - - // For indirect calls, add each call_ref to the type the call_ref uses. - for (auto* callRef : info.callRefs) { - auto calledType = callRef->target->type; - if (calledType != Type::unreachable) { - allInfo[calledType.getHeapType()].callRefs.push_back(callRef); - } - } - - // A parameter used in this function is used in the heap type - just one - // function is enough to prevent the parameter from being removed. - auto& allUsedParams = allInfo[func->type].usedParams; - for (auto index : info.usedParams) { - allUsedParams.insert(index); - } - - if (!info.optimizable) { - allInfo[func->type].optimizable = false; - } - - sigFuncs[func->type].push_back(func); - } - - // Exported functions cannot be modified. - for (auto& exp : module->exports) { - if (exp->kind == ExternalKind::Function) { - auto* func = module->getFunction(exp->value); - allInfo[func->type].optimizable = false; - } - } - - // Find parameters to prune. - for (auto& [type, funcs] : sigFuncs) { - auto sig = type.getSignature(); - auto& info = allInfo[type]; - auto& usedParams = info.usedParams; - auto numParams = sig.params.size(); - - if (!info.optimizable) { - continue; - } - - // A type with a signature supertype cannot be optimized: we'd need to - // remove the field from the super as well, which atm we don't attempt to - // do. TODO - if (auto super = type.getSuperType()) { - if (super->isSignature()) { - continue; - } - } - - // Apply constant indexes: find the parameters that are always sent a - // constant value, and apply that value in the function. That then makes - // the parameter unused (since the applied value makes us ignore the value - // arriving in the parameter). - auto optimizedIndexes = ParamUtils::applyConstantValues( - funcs, info.calls, info.callRefs, module); - for (auto i : optimizedIndexes) { - usedParams.erase(i); - } - - if (usedParams.size() == numParams) { - // All parameters are used, give up on this one. - continue; - } - - // We found possible work! Find the specific params that are unused & try - // to prune them. - SortedVector unusedParams; - for (Index i = 0; i < numParams; i++) { - if (usedParams.count(i) == 0) { - unusedParams.insert(i); - } - } - - auto oldParams = sig.params; - auto removedIndexes = ParamUtils::removeParameters( - funcs, unusedParams, info.calls, info.callRefs, module, runner); - if (removedIndexes.empty()) { - continue; - } - - // Success! Update the types. - std::vector newParams; - for (Index i = 0; i < numParams; i++) { - if (!removedIndexes.has(i)) { - newParams.push_back(oldParams[i]); - } - } - - // Create a new signature. When the TypeRewriter operates below it will - // modify the existing heap type in place to change its signature to this - // one (which preserves identity, that is, even if after pruning the new - // signature is structurally identical to another one, it will remain - // nominally different from those). - newSignatures[type] = Signature(Type(newParams), sig.results); - - // removeParameters() updates the type as it goes, but in this pass we - // need the type to match the other locations, nominally. That is, we need - // all the functions of a particular type to still have the same type - // after this operation, and that must be the exact same type at the - // relevant call_refs and so forth. The TypeRewriter below will do the - // right thing as it rewrites everything all at once, so we do not want - // the type to be modified by removeParameters(), and so we undo the type - // it made. - // - // Note that we cannot just ask removeParameters() to not update the type, - // as it adds a new local there, whose index depends on the type (which - // contains the # of parameters, and that determine where non-parameter - // local indexes begin). Rather than have it update the type and then undo - // that, which would add more complexity in that method, undo the change - // here. - for (auto* func : funcs) { - func->type = type; - } - } - - // Rewrite the types. - GlobalTypeRewriter::updateSignatures(newSignatures, *module); - } -}; - -} // anonymous namespace - -Pass* createSignaturePruningPass() { return new SignaturePruning(); } - -} // namespace wasm diff -Nru binaryen-108/src/passes/SignatureRefining.cpp binaryen-99/src/passes/SignatureRefining.cpp --- binaryen-108/src/passes/SignatureRefining.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SignatureRefining.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,267 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Apply more specific subtypes to signature/function types where possible. -// -// This differs from DeadArgumentElimination's refineArgumentTypes() etc. in -// that DAE will modify the type of a function. It can only do that if the -// function's type is not observable, which means it is not taken by reference. -// On the other hand, this pass will modify the signature types themselves, -// which means it can optimize functions whose reference is taken, and it does -// so while considering all users of the type (across all functions sharing that -// type, and all call_refs using it). -// - -#include "ir/export-utils.h" -#include "ir/find_all.h" -#include "ir/lubs.h" -#include "ir/module-utils.h" -#include "ir/type-updating.h" -#include "ir/utils.h" -#include "pass.h" -#include "wasm-type.h" -#include "wasm.h" - -namespace wasm { - -namespace { - -struct SignatureRefining : public Pass { - // Maps each heap type to the possible refinement of the types in their - // signatures. We will fill this during analysis and then use it while doing - // an update of the types. If a type has no improvement that we can find, it - // will not appear in this map. - std::unordered_map newSignatures; - - void run(PassRunner* runner, Module* module) override { - if (getTypeSystem() != TypeSystem::Nominal) { - Fatal() << "SignatureRefining requires nominal typing"; - } - - if (!module->tables.empty()) { - // When there are tables we must also take their types into account, which - // would require us to take call_indirect, element segments, etc. into - // account. For now, do nothing if there are tables. - // TODO - return; - } - - // First, find all the information we need. Start by collecting inside each - // function in parallel. - - struct Info { - // The calls and call_refs. - std::vector calls; - std::vector callRefs; - - // A possibly improved LUB for the results. - LUBFinder resultsLUB; - - // Normally we can optimize, but some cases prevent a particular signature - // type from being changed at all, see below. - bool canModify = true; - }; - - // This analysis also modifies the wasm as it goes, as the getResultsLUB() - // operation has side effects (see comment on header declaration). - ModuleUtils::ParallelFunctionAnalysis analysis( - *module, [&](Function* func, Info& info) { - if (func->imported()) { - return; - } - info.calls = std::move(FindAll(func->body).list); - info.callRefs = std::move(FindAll(func->body).list); - info.resultsLUB = LUB::getResultsLUB(func, *module); - }); - - // A map of types to all the information combined over all the functions - // with that type. - std::unordered_map allInfo; - - // Combine all the information we gathered into that map. - for (auto& [func, info] : analysis.map) { - // For direct calls, add each call to the type of the function being - // called. - for (auto* call : info.calls) { - allInfo[module->getFunction(call->target)->type].calls.push_back(call); - } - - // For indirect calls, add each call_ref to the type the call_ref uses. - for (auto* callRef : info.callRefs) { - auto calledType = callRef->target->type; - if (calledType != Type::unreachable) { - allInfo[calledType.getHeapType()].callRefs.push_back(callRef); - } - } - - // Add the function's return LUB to the one for the heap type of that - // function. - allInfo[func->type].resultsLUB.combine(info.resultsLUB); - } - - // We cannot alter the signature of an exported function, as the outside may - // notice us doing so. For example, if we turn a parameter from nullable - // into non-nullable then callers sending a null will break. Put another - // way, we need to see all callers to refine types, and for exports we - // cannot do so. - // TODO If a function type is passed we should also mark the types used - // there, etc., recursively. For now this code just handles the top- - // level type, which is enough to keep the fuzzer from erroring. More - // generally, we need to decide about adding a "closed-world" flag of - // some kind. - for (auto* exportedFunc : ExportUtils::getExportedFunctions(*module)) { - allInfo[exportedFunc->type].canModify = false; - } - - bool refinedResults = false; - - // Compute optimal LUBs. - std::unordered_set seen; - for (auto& func : module->functions) { - auto type = func->type; - if (!seen.insert(type).second) { - continue; - } - - auto& info = allInfo[type]; - if (!info.canModify) { - continue; - } - - auto sig = type.getSignature(); - - auto numParams = sig.params.size(); - std::vector paramLUBs(numParams); - - auto updateLUBs = [&](const ExpressionList& operands) { - for (Index i = 0; i < numParams; i++) { - paramLUBs[i].noteUpdatableExpression(operands[i]); - } - }; - - for (auto* call : info.calls) { - updateLUBs(call->operands); - } - for (auto* callRef : info.callRefs) { - updateLUBs(callRef->operands); - } - - // Find the final LUBs, and see if we found an improvement. - std::vector newParamsTypes; - for (auto& lub : paramLUBs) { - if (!lub.noted()) { - break; - } - newParamsTypes.push_back(lub.getBestPossible()); - } - Type newParams; - if (newParamsTypes.size() < numParams) { - // We did not have type information to calculate a LUB (no calls, or - // some param is always unreachable), so there is nothing we can improve - // here. Other passes might remove the type entirely. - newParams = func->getParams(); - } else { - newParams = Type(newParamsTypes); - } - - auto& resultsLUB = info.resultsLUB; - Type newResults; - if (!resultsLUB.noted()) { - // We did not have type information to calculate a LUB (no returned - // value, or it can return a value but traps instead etc.). - newResults = func->getResults(); - } else { - newResults = resultsLUB.getBestPossible(); - } - - if (newParams == func->getParams() && newResults == func->getResults()) { - continue; - } - - // We found an improvement! - newSignatures[type] = Signature(newParams, newResults); - - // Update nulls as necessary, now that we are changing things. - if (newParams != func->getParams()) { - for (auto& lub : paramLUBs) { - lub.updateNulls(); - } - } - if (newResults != func->getResults()) { - resultsLUB.updateNulls(); - refinedResults = true; - - // Update the types of calls using the signature. - for (auto* call : info.calls) { - if (call->type != Type::unreachable) { - call->type = newResults; - } - } - for (auto* callRef : info.callRefs) { - if (callRef->type != Type::unreachable) { - callRef->type = newResults; - } - } - } - } - - if (newSignatures.empty()) { - // We found nothing to optimize. - return; - } - - // Update function contents for their new parameter types. - struct CodeUpdater : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - SignatureRefining& parent; - Module& wasm; - - CodeUpdater(SignatureRefining& parent, Module& wasm) - : parent(parent), wasm(wasm) {} - - CodeUpdater* create() override { return new CodeUpdater(parent, wasm); } - - void doWalkFunction(Function* func) { - auto iter = parent.newSignatures.find(func->type); - if (iter != parent.newSignatures.end()) { - std::vector newParamsTypes; - for (auto param : iter->second.params) { - newParamsTypes.push_back(param); - } - TypeUpdating::updateParamTypes(func, newParamsTypes, wasm); - } - } - }; - CodeUpdater(*this, *module).run(runner, module); - - // Rewrite the types. - GlobalTypeRewriter::updateSignatures(newSignatures, *module); - - if (refinedResults) { - // After return types change we need to propagate. - // TODO: we could do this only in relevant functions perhaps - ReFinalize().run(runner, module); - } - } -}; - -} // anonymous namespace - -Pass* createSignatureRefiningPass() { return new SignatureRefining(); } - -} // namespace wasm diff -Nru binaryen-108/src/passes/SimplifyGlobals.cpp binaryen-99/src/passes/SimplifyGlobals.cpp --- binaryen-108/src/passes/SimplifyGlobals.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SimplifyGlobals.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -24,10 +24,6 @@ // * Apply the constant values of immutable globals. // * Apply the constant values of previous global.sets, in a linear // execution trace. -// * Remove writes to globals that are never read from. -// * Remove writes to globals that are always assigned the same value. -// * Remove writes to globals that are only read from in order to write (see -// below, "readOnlyToWrite"). // // Some globals may not have uses after these changes, which we leave // to other passes to optimize. @@ -41,7 +37,6 @@ #include #include "ir/effects.h" -#include "ir/linear-execution.h" #include "ir/properties.h" #include "ir/utils.h" #include "pass.h" @@ -53,41 +48,10 @@ namespace { struct GlobalInfo { - // Whether the global is imported and exported. bool imported = false; bool exported = false; - - // How many times the global is written and read. - std::atomic written{0}; - std::atomic read{0}; - - // Whether the global is written a value different from its initial value. - std::atomic nonInitWritten{false}; - - // How many times the global is "read, but only to write", that is, is used in - // something like this pattern: - // - // if (global == X) { global = Y } - // - // The if's condition only uses |global| in order to decide to write to that - // same global, so it is "read, but only to write." If all we have are such - // reads only to write then the global is really not necessary, even though - // there are both reads and writes of it, and regardless of what the written - // values are etc. - // - // This pattern can show up in global initialization code, where in the block - // alongside "global = Y" there was some useful code, but the optimizer - // managed to remove it. For example, - // - // if (global == 0) { global = 1; sideEffect(); } - // - // If the global's initial value is the default 0, and there are no other uses - // of this global, then this code will run sideEffect() the very first time we - // reach here. We therefore need to keep this global and its reads and writes. - // However, if sideEffect() were removed, then we read the global only to - // write it - and nothing else - and so we can optimize away that global - // entirely. - std::atomic readOnlyToWrite{0}; + std::atomic written; + std::atomic read; }; using GlobalInfoMap = std::map; @@ -99,200 +63,9 @@ GlobalUseScanner* create() override { return new GlobalUseScanner(infos); } - void visitGlobalSet(GlobalSet* curr) { - (*infos)[curr->name].written++; - - // Check if there is a write of a value that may differ from the initial - // one. If there is anything but identical constants in both the initial - // value and the written value then we must assume that. - auto* global = getModule()->getGlobal(curr->name); - if (global->imported() || !Properties::isConstantExpression(curr->value) || - !Properties::isConstantExpression(global->init) || - Properties::getLiterals(curr->value) != - Properties::getLiterals(global->init)) { - (*infos)[curr->name].nonInitWritten = true; - } - } - - void visitGlobalGet(GlobalGet* curr) { (*infos)[curr->name].read++; } - - void visitIf(If* curr) { - // We are looking for - // - // if (global == X) { global = Y } - // - // Ignore an if-else, which cannot be that. - if (curr->ifFalse) { - return; - } - - auto global = readsGlobalOnlyToWriteIt(curr->condition, curr->ifTrue); - if (global.is()) { - // This is exactly the pattern we sought! - (*infos)[global].readOnlyToWrite++; - } - } - - // Given a condition and some code that is executed based on the condition, - // check if the condition reads from some global in order to make the decision - // whether to run that code, and that code only writes to that global, which - // means the global is "read, but only to be written." - // - // The condition may also do other things than read from that global - it may - // compare it to a value, or negate it, or anything else, so long as the value - // of the global is only used to decide to run the code, like this: - // - // if (global % 17 < 4) { global = 1 } - // - // What we want to disallow is using the global to actually do something that - // is noticeeable *aside* from writing the global, like this: - // - // if (global ? foo() : bar()) { .. } - // - // Here ? : is another nested if, and we end up running different code based - // on global, which is noticeable: the global is *not* only read in order to - // write that global, but also for other reasons. - // - // Returns the global name if things like up, or a null name otherwise. - Name readsGlobalOnlyToWriteIt(Expression* condition, Expression* code) { - // See if writing a global is the only effect the code has. (Note that we - // don't need to care about the case where the code has no effects at - // all - other passes would handle that trivial situation.) - EffectAnalyzer codeEffects(getPassOptions(), *getModule(), code); - if (codeEffects.globalsWritten.size() != 1) { - return Name(); - } - auto writtenGlobal = *codeEffects.globalsWritten.begin(); - codeEffects.globalsWritten.clear(); - if (codeEffects.hasAnything()) { - return Name(); - } - - // See if we read that global in the condition expression. - EffectAnalyzer conditionEffects(getPassOptions(), *getModule(), condition); - if (!conditionEffects.mutableGlobalsRead.count(writtenGlobal)) { - return Name(); - } - - // If the condition has no other (non-removable) effects other than reading - // that global then we have found what we looked for. - if (!conditionEffects.hasUnremovableSideEffects()) { - return writtenGlobal; - } - - // There are unremovable side effects of some form. However, they may not - // be related to the reading of the global, that is, the global's value may - // not flow to anything that uses it in a dangerous way. It *would* be - // dangerous for the global's value to flow into a nested if condition, as - // mentioned in the comment earlier, but if it flows into an if arm for - // example then that is safe, so long as the final place it flows out to is - // the condition. - // - // To check this, find the get of the global in the condition, and look up - // through its parents to see how the global's value is used. - struct FlowScanner - : public ExpressionStackWalker> { - GlobalUseScanner& globalUseScanner; - Name writtenGlobal; - PassOptions& passOptions; - Module& wasm; - - FlowScanner(GlobalUseScanner& globalUseScanner, - Name writtenGlobal, - PassOptions& passOptions, - Module& wasm) - : globalUseScanner(globalUseScanner), writtenGlobal(writtenGlobal), - passOptions(passOptions), wasm(wasm) {} - - bool ok = true; - - void visitExpression(Expression* curr) { - if (auto* get = curr->dynCast()) { - if (get->name == writtenGlobal) { - // We found the get of the global. Check where its value flows to, - // and how it is used there. - assert(expressionStack.back() == get); - for (int i = int(expressionStack.size()) - 2; i >= 0; i--) { - // Consider one pair of parent->child, and check if the parent - // causes any problems when the child's value reaches it. - auto* parent = expressionStack[i]; - auto* child = expressionStack[i + 1]; - EffectAnalyzer parentEffects(passOptions, wasm); - parentEffects.visit(parent); - if (parentEffects.hasUnremovableSideEffects()) { - // The parent has some side effect, and the child's value may - // be used to determine its manner, so this is dangerous. - ok = false; - break; - } - - if (auto* iff = parent->dynCast()) { - if (iff->condition == child) { - // The child is used to decide what code to run, which is - // dangerous: check what effects it causes. If it is a nested - // appearance of the pattern, that is one case that we know is - // actually safe. - if (!iff->ifFalse && - globalUseScanner.readsGlobalOnlyToWriteIt( - iff->condition, iff->ifTrue) == writtenGlobal) { - // This is safe, and we can stop here: the value does not - // flow any further. - break; - } - - // Otherwise, we found a problem, and can stop. - ok = false; - break; - } - } - } - } - } - } - }; - - FlowScanner scanner(*this, writtenGlobal, getPassOptions(), *getModule()); - scanner.walk(condition); - return scanner.ok ? writtenGlobal : Name(); - } - - void visitFunction(Function* curr) { - // We are looking for a function body like this: - // - // if (global == X) return; - // global = Y; - // - // And nothing else at all. Note that this does not overlap with the if - // pattern above (the assignment is in the if body) so we will never have - // overlapping matchings (which would each count as 1, leading to a - // miscount). - - if (curr->body->type != Type::none) { - return; - } - - auto* block = curr->body->dynCast(); - if (!block) { - return; - } - - auto& list = block->list; - if (list.size() != 2) { - return; - } - - auto* iff = list[0]->dynCast(); - if (!iff || iff->ifFalse || !iff->ifTrue->is()) { - return; - } + void visitGlobalSet(GlobalSet* curr) { (*infos)[curr->name].written = true; } - auto global = readsGlobalOnlyToWriteIt(iff->condition, list[1]); - if (global.is()) { - // This is exactly the pattern we sought! - (*infos)[global].readOnlyToWrite++; - } - } + void visitGlobalGet(GlobalGet* curr) { (*infos)[curr->name].read = true; } private: GlobalInfoMap* infos; @@ -363,7 +136,7 @@ return; } // Otherwise, invalidate if we need to. - EffectAnalyzer effects(getPassOptions(), *getModule()); + EffectAnalyzer effects(getPassOptions(), getModule()->features); effects.visit(curr); assert(effects.globalsWritten.empty()); // handled above if (effects.calls) { @@ -440,29 +213,18 @@ runner = runner_; module = module_; - while (iteration()) { - } - } - - bool iteration() { analyze(); - // Removing unneeded writes can in some cases lead to more optimizations - // that we need an entire additional iteration to perform, see below. - bool more = removeUnneededWrites(); + removeWritesToUnreadGlobals(); preferEarlierImports(); propagateConstantsToGlobals(); propagateConstantsToCode(); - - return more; } void analyze() { - map.clear(); - // First, find out all the relevant info. for (auto& global : module->globals) { auto& info = map[global->name]; @@ -486,87 +248,21 @@ } } - // Removes writes from globals that will never do anything useful with the - // written value anyhow. Returns whether an addition iteration is necessary. - bool removeUnneededWrites() { - bool more = false; - - // Globals that are not exports and not read from do not need their sets. - // Likewise, globals that only write their initial value later also do not - // need those writes. And, globals that are only read from in order to write - // to themselves as well. First, find such globals. - NameSet globalsNotNeedingSets; + void removeWritesToUnreadGlobals() { + // Globals that are not exports and not read from can be eliminated + // (even if they are written to). + NameSet unreadGlobals; for (auto& global : module->globals) { auto& info = map[global->name]; - - if (!info.written) { - // No writes occur here, so there is nothing for us to remove. - continue; - } - - if (info.imported || info.exported) { - // If the global is observable from the outside, we can't do anythng - // here. - // - // TODO: optimize the case of an imported but immutable global, etc. - continue; - } - - // We only ever optimize read-only-to-write if all of our reads are done - // in places we identified as read-only-to-write. That is, we have - // eliminated the possibility of any other uses. (Technically, each - // read-to-write location might have more than one read since we did not - // count them, but only verified there was one read or more; but this is - // good enough as the common case has exactly one.) - // - // Note that there might be more writes, if there are additional writes - // besides those in the read-only-to-write locations. But we can ignore - // those, as whatever they write will not be read in order to do anything - // of value. - bool onlyReadOnlyToWrite = (info.read == info.readOnlyToWrite); - - // There is at least one write in each read-only-to-write location, unless - // our logic is wrong somewhere. - assert(info.written >= info.readOnlyToWrite); - - if (!info.read || !info.nonInitWritten || onlyReadOnlyToWrite) { - globalsNotNeedingSets.insert(global->name); - + if (!info.imported && !info.exported && !info.read) { + unreadGlobals.insert(global->name); // We can now mark this global as immutable, and un-written, since we - // are about to remove all the sets on it. + // are about to remove all the `.set` operations on it. global->mutable_ = false; - info.written = 0; - - // Nested only-read-to-write expressions require another full iteration - // to optimize, as we have: - // - // if (a) { - // a = 1; - // if (b) { - // b = 1; - // } - // } - // - // The first iteration can only optimize b, as the outer if's body has - // more effects than we understand. After finishing the first iteration, - // b will no longer exist, removing those effects. - // - // TODO: In principle other situations exist as well where more - // iterations help, like if we remove a set that turns something - // into a read-only-to-write. - if (onlyReadOnlyToWrite) { - more = true; - } + info.written = false; } } - - // Remove all the sets on the unnecessary globals. Later optimizations can - // then see that since the global has no writes, it is a constant, which - // will lead to removal of gets, and after removing them, the global itself - // will be removed as well. - GlobalSetRemover(&globalsNotNeedingSets, optimize).run(runner, module); - - return more; + GlobalSetRemover(&unreadGlobals, optimize).run(runner, module); } void preferEarlierImports() { diff -Nru binaryen-108/src/passes/SimplifyLocals.cpp binaryen-99/src/passes/SimplifyLocals.cpp --- binaryen-108/src/passes/SimplifyLocals.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SimplifyLocals.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -79,8 +78,10 @@ Expression** item; EffectAnalyzer effects; - SinkableInfo(Expression** item, PassOptions& passOptions, Module& module) - : item(item), effects(passOptions, module, *item) {} + SinkableInfo(Expression** item, + PassOptions& passOptions, + FeatureSet features) + : item(item), effects(passOptions, features, *item) {} }; // a list of sinkables in a linear execution trace @@ -138,15 +139,17 @@ } else if (curr->is()) { assert(!curr->cast() ->ifFalse); // if-elses are handled by doNoteIf* methods - } else { - // Not one of the recognized instructions, so do not optimize here: mark - // all the targets as unoptimizable. - // TODO optimize BrOn, Switch, etc. - auto targets = BranchUtils::getUniqueTargets(curr); + } else if (curr->is()) { + auto* sw = curr->cast(); + auto targets = BranchUtils::getUniqueTargets(sw); for (auto target : targets) { self->unoptimizableBlocks.insert(target); } // TODO: we could use this info to stop gathering data on these blocks + } else if (auto* br = curr->dynCast()) { + // We cannot optimize the block this targets to have a return value, as + // the br_on_exn doesn't support a change to the block's type + self->unoptimizableBlocks.insert(br->name); } self->sinkables.clear(); } @@ -280,9 +283,9 @@ void checkInvalidations(EffectAnalyzer& effects) { // TODO: this is O(bad) std::vector invalidated; - for (auto& [index, info] : sinkables) { - if (effects.invalidates(info.effects)) { - invalidated.push_back(index); + for (auto& sinkable : sinkables) { + if (effects.invalidates(sinkable.second.effects)) { + invalidated.push_back(sinkable.first); } } for (auto index : invalidated) { @@ -303,9 +306,9 @@ // 'try', we drop all sinkables that may throw. if (curr->is()) { std::vector invalidated; - for (auto& [index, info] : self->sinkables) { - if (info.effects.throws()) { - invalidated.push_back(index); + for (auto& sinkable : self->sinkables) { + if (sinkable.second.effects.throws) { + invalidated.push_back(sinkable.first); } } for (auto index : invalidated) { @@ -313,7 +316,7 @@ } } - EffectAnalyzer effects(self->getPassOptions(), *self->getModule()); + EffectAnalyzer effects(self->getPassOptions(), self->getModule()->features); if (effects.checkPre(curr)) { self->checkInvalidations(effects); } @@ -399,7 +402,8 @@ } } - EffectAnalyzer effects(self->getPassOptions(), *self->getModule()); + FeatureSet features = self->getModule()->features; + EffectAnalyzer effects(self->getPassOptions(), features); if (effects.checkPost(original)) { self->checkInvalidations(effects); } @@ -407,9 +411,8 @@ if (set && self->canSink(set)) { Index index = set->index; assert(self->sinkables.count(index) == 0); - self->sinkables.emplace(std::pair{ - index, - SinkableInfo(currp, self->getPassOptions(), *self->getModule())}); + self->sinkables.emplace(std::make_pair( + index, SinkableInfo(currp, self->getPassOptions(), features))); } if (!allowNesting) { @@ -422,11 +425,11 @@ if (set->isTee()) { return false; } - // We cannot move expressions containing pops that are not enclosed in - // 'catch', because 'pop' should follow right after 'catch'. + // We cannot move expressions containing exnref.pops that are not enclosed + // in 'catch', because 'exnref.pop' should follow right after 'catch'. FeatureSet features = this->getModule()->features; if (features.hasExceptionHandling() && - EffectAnalyzer(this->getPassOptions(), *this->getModule(), set->value) + EffectAnalyzer(this->getPassOptions(), features, set->value) .danglingPop) { return false; } @@ -493,7 +496,8 @@ // look for a local.set that is present in them all bool found = false; Index sharedIndex = -1; - for (auto& [index, _] : sinkables) { + for (auto& sinkable : sinkables) { + Index index = sinkable.first; bool inAll = true; for (size_t j = 0; j < breaks.size(); j++) { if (breaks[j].sinkables.count(index) == 0) { @@ -527,6 +531,7 @@ // ) // ) // so we must check for that. + FeatureSet features = this->getModule()->features; for (size_t j = 0; j < breaks.size(); j++) { // move break local.set's value to the break auto* breakLocalSetPointer = breaks[j].sinkables.at(sharedIndex).item; @@ -544,9 +549,8 @@ Nop nop; *breakLocalSetPointer = &nop; EffectAnalyzer condition( - this->getPassOptions(), *this->getModule(), br->condition); - EffectAnalyzer value( - this->getPassOptions(), *this->getModule(), set); + this->getPassOptions(), features, br->condition); + EffectAnalyzer value(this->getPassOptions(), features, set); *breakLocalSetPointer = set; if (condition.invalidates(value)) { // indeed, we can't do this, stop @@ -647,7 +651,8 @@ } } else { // Look for a shared index. - for (auto& [index, _] : ifTrue) { + for (auto& sinkable : ifTrue) { + Index index = sinkable.first; if (ifFalse.count(index) > 0) { goodIndex = index; found = true; @@ -1029,7 +1034,7 @@ // gotten there thanks to the EquivalentOptimizer. If there are such // locals, remove all their sets. UnneededSetRemover setRemover( - getCounter, func, this->getPassOptions(), *this->getModule()); + getCounter, func, this->getPassOptions(), this->getModule()->features); setRemover.setModule(this->getModule()); return eqOpter.anotherCycle || setRemover.removed; diff -Nru binaryen-108/src/passes/Souperify.cpp binaryen-99/src/passes/Souperify.cpp --- binaryen-108/src/passes/Souperify.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Souperify.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -86,9 +86,10 @@ LocalGraph& localGraph, std::vector& ret) { // If already handled, nothing to do here. - if (!seenSets.emplace(set).second) { + if (seenSets.count(set)) { return; } + seenSets.insert(set); // Find all the uses of that set. auto& gets = localGraph.setInfluences[set]; if (debug() >= 2) { diff -Nru binaryen-108/src/passes/SSAify.cpp binaryen-99/src/passes/SSAify.cpp --- binaryen-108/src/passes/SSAify.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/SSAify.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -53,7 +53,6 @@ #include "ir/find_all.h" #include "ir/literal-utils.h" #include "ir/local-graph.h" -#include "ir/type-updating.h" #include "pass.h" #include "support/permutations.h" #include "wasm-builder.h" @@ -70,10 +69,6 @@ struct SSAify : public Pass { bool isFunctionParallel() override { return true; } - // SSAify maps each original local to a number of new ones. - // FIXME DWARF updating does not handle local changes yet. - bool invalidatesDWARF() override { return true; } - Pass* create() override { return new SSAify(allowMerges); } SSAify(bool allowMerges) : allowMerges(allowMerges) {} @@ -90,7 +85,7 @@ module = module_; func = func_; LocalGraph graph(func); - graph.computeSetInfluences(); + graph.computeInfluences(); graph.computeSSAIndexes(); // create new local indexes, one for each set createNewIndexes(graph); @@ -99,8 +94,6 @@ computeGetsAndPhis(graph); // add prepends to function addPrepends(); - // Handle non-nullability in new locals we added. - TypeUpdating::handleNonDefaultableLocals(func, *module); } void createNewIndexes(LocalGraph& graph) { diff -Nru binaryen-108/src/passes/StackCheck.cpp binaryen-99/src/passes/StackCheck.cpp --- binaryen-108/src/passes/StackCheck.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/StackCheck.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -21,7 +21,6 @@ // #include "abi/js.h" -#include "ir/abstract.h" #include "ir/import-utils.h" #include "ir/names.h" #include "pass.h" @@ -36,15 +35,16 @@ // Exported function to set the base and the limit. static Name SET_STACK_LIMITS("__set_stack_limits"); -static void -importStackOverflowHandler(Module& module, Name name, Signature sig) { +static void importStackOverflowHandler(Module& module, Name name) { ImportInfo info(module); if (!info.getImportedFunction(ENV, name)) { - auto import = Builder::makeFunction(name, sig, {}); + auto* import = new Function; + import->name = name; import->module = ENV; import->base = name; - module.addFunction(std::move(import)); + import->sig = Signature(Type::none, Type::none); + module.addFunction(import); } } @@ -81,24 +81,20 @@ // Otherwise, just trap. Expression* handlerExpr; if (handler.is()) { - handlerExpr = - builder.makeCall(handler, - {builder.makeLocalGet(newSP, stackPointer->type)}, - stackPointer->type); + handlerExpr = builder.makeCall(handler, {}, Type::none); } else { handlerExpr = builder.makeUnreachable(); } - // If it is >= the base or <= the limit, then error. auto check = builder.makeIf( builder.makeBinary( BinaryOp::OrInt32, builder.makeBinary( - Abstract::getBinary(stackPointer->type, Abstract::GtU), + BinaryOp::GtUInt32, builder.makeLocalTee(newSP, value, stackPointer->type), builder.makeGlobalGet(stackBase->name, stackBase->type)), builder.makeBinary( - Abstract::getBinary(stackPointer->type, Abstract::LtU), + BinaryOp::LtUInt32, builder.makeLocalGet(newSP, stackPointer->type), builder.makeGlobalGet(stackLimit->name, stackLimit->type))), handlerExpr); @@ -139,8 +135,7 @@ runner->options.getArgumentOrDefault("stack-check-handler", ""); if (handlerName != "") { handler = handlerName; - importStackOverflowHandler( - *module, handler, Signature({stackPointer->type}, Type::none)); + importStackOverflowHandler(*module, handler); } Builder builder(*module); @@ -149,12 +144,12 @@ auto stackBase = module->addGlobal(builder.makeGlobal(stackBaseName, stackPointer->type, - builder.makeConstPtr(0), + builder.makeConst(int32_t(0)), Builder::Mutable)); auto stackLimit = module->addGlobal(builder.makeGlobal(stackLimitName, stackPointer->type, - builder.makeConstPtr(0), + builder.makeConst(int32_t(0)), Builder::Mutable)); // Instrument all the code. @@ -164,12 +159,10 @@ // Generate the exported function. auto limitsFunc = builder.makeFunction( - SET_STACK_LIMITS, - Signature({stackPointer->type, stackPointer->type}, Type::none), - {}); - auto* getBase = builder.makeLocalGet(0, stackPointer->type); + SET_STACK_LIMITS, Signature({Type::i32, Type::i32}, Type::none), {}); + auto* getBase = builder.makeLocalGet(0, Type::i32); auto* storeBase = builder.makeGlobalSet(stackBaseName, getBase); - auto* getLimit = builder.makeLocalGet(1, stackPointer->type); + auto* getLimit = builder.makeLocalGet(1, Type::i32); auto* storeLimit = builder.makeGlobalSet(stackLimitName, getLimit); limitsFunc->body = builder.makeBlock({storeBase, storeLimit}); addExportedFunction(*module, std::move(limitsFunc)); diff -Nru binaryen-108/src/passes/StackIR.cpp binaryen-99/src/passes/StackIR.cpp --- binaryen-108/src/passes/StackIR.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/StackIR.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -51,14 +51,10 @@ Function* func; PassOptions& passOptions; StackIR& insts; - FeatureSet features; public: - StackIROptimizer(Function* func, - PassOptions& passOptions, - FeatureSet features) - : func(func), passOptions(passOptions), insts(*func->stackIR.get()), - features(features) { + StackIROptimizer(Function* func, PassOptions& passOptions) + : func(func), passOptions(passOptions), insts(*func->stackIR.get()) { assert(func->stackIR); } @@ -69,39 +65,7 @@ if (passOptions.optimizeLevel >= 3 || passOptions.shrinkLevel >= 1) { local2Stack(); } - // Removing unneeded blocks is dangerous with GC, as if we do this: - // - // (call - // (rtt) - // (block - // (nop) - // (i32) - // ) - // ) - // === remove inner block ==> - // (call - // (rtt) - // (nop) - // (i32) - // ) - // - // Then we end up with a nop that forces us to emit this during load: - // - // (call - // (block - // (local.set - // (rtt) - // ) - // (nop) - // (local.get) - // ) - // (i32) - // ) - // - // However, that is not valid as an rtt cannot be set to a local. - if (!features.hasGC()) { - removeUnneededBlocks(); - } + removeUnneededBlocks(); dce(); } @@ -148,7 +112,7 @@ // TODO: we can do this a lot faster, as we just care about linear // control flow. LocalGraph localGraph(func); - localGraph.computeSetInfluences(); + localGraph.computeInfluences(); // We maintain a stack of relevant values. This contains: // * a null for each actual value that the value stack would have // * an index of each LocalSet that *could* be on the value @@ -293,8 +257,6 @@ case StackInst::IfEnd: case StackInst::LoopEnd: case StackInst::Catch: - case StackInst::CatchAll: - case StackInst::Delegate: case StackInst::TryEnd: { return true; } @@ -321,8 +283,7 @@ case StackInst::BlockEnd: case StackInst::IfEnd: case StackInst::LoopEnd: - case StackInst::TryEnd: - case StackInst::Delegate: { + case StackInst::TryEnd: { return true; } default: { return false; } @@ -376,7 +337,7 @@ if (!func->stackIR) { return; } - StackIROptimizer(func, getPassOptions(), getModule()->features).run(); + StackIROptimizer(func, getPassOptions()).run(); } }; diff -Nru binaryen-108/src/passes/Strip.cpp binaryen-99/src/passes/Strip.cpp --- binaryen-108/src/passes/Strip.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Strip.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -25,6 +25,8 @@ #include "wasm-binary.h" #include "wasm.h" +using namespace std; + namespace wasm { struct Strip : public Pass { diff -Nru binaryen-108/src/passes/test_passes.cpp binaryen-99/src/passes/test_passes.cpp --- binaryen-108/src/passes/test_passes.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/test_passes.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// This file contains passes used for internal testing. This file can be used to -// test utility functions separately. -// - -#include "ir/eh-utils.h" -#include "pass.h" -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm { - -namespace { - -// Pass to test EHUtil::handleBlockNestedPops function -struct CatchPopFixup : public WalkerPass> { - bool isFunctionParallel() override { return true; } - Pass* create() override { return new CatchPopFixup; } - - void doWalkFunction(Function* func) { - EHUtils::handleBlockNestedPops(func, *getModule()); - } - void run(PassRunner* runner, Module* module) override {} -}; - -} // anonymous namespace - -Pass* createCatchPopFixupPass() { return new CatchPopFixup(); } - -} // namespace wasm diff -Nru binaryen-108/src/passes/TrapMode.cpp binaryen-99/src/passes/TrapMode.cpp --- binaryen-108/src/passes/TrapMode.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/TrapMode.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -132,14 +132,14 @@ builder.makeConst(zeroLit), result); } - auto funcSig = Signature({type, type}, type); - auto func = Builder::makeFunction(getBinaryFuncName(curr), funcSig, {}); + auto func = new Function; + func->name = getBinaryFuncName(curr); + func->sig = Signature({type, type}, type); func->body = builder.makeIf(builder.makeUnary(eqZOp, builder.makeLocalGet(1, type)), builder.makeConst(zeroLit), result); - // TODO: use unique_ptr properly and do not release ownership. - return func.release(); + return func; } template @@ -193,8 +193,9 @@ WASM_UNREACHABLE("unexpected op"); } - auto func = - Builder::makeFunction(getUnaryFuncName(curr), Signature(type, retType), {}); + auto func = new Function; + func->name = getUnaryFuncName(curr); + func->sig = Signature(type, retType); func->body = builder.makeUnary(truncOp, builder.makeLocalGet(0, type)); // too small XXX this is different than asm.js, which does frem. here we // clamp, which is much simpler/faster, and similar to native builds @@ -217,8 +218,7 @@ // NB: min here as well. anything invalid => to the min builder.makeConst(iMin), func->body); - // TODO: use unique_ptr properly and do not release ownership. - return func.release(); + return func; } void ensureBinaryFunc(Binary* curr, @@ -251,7 +251,7 @@ import->name = F64_TO_INT; import->module = ASM2WASM; import->base = F64_TO_INT; - import->type = Signature(Type::f64, Type::i32); + import->sig = Signature(Type::f64, Type::i32); trappingFunctions.addImport(import); } diff -Nru binaryen-108/src/passes/TypeRefining.cpp binaryen-99/src/passes/TypeRefining.cpp --- binaryen-108/src/passes/TypeRefining.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/TypeRefining.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,286 +0,0 @@ -/* - * Copyright 2021 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Apply more specific subtypes to type fields where possible, where all the -// writes to that field in the entire program allow doing so. -// - -#include "ir/lubs.h" -#include "ir/struct-utils.h" -#include "ir/type-updating.h" -#include "ir/utils.h" -#include "pass.h" -#include "support/unique_deferring_queue.h" -#include "wasm-type.h" -#include "wasm.h" - -namespace wasm { - -namespace { - -// We use a LUBFinder to track field info, which includes the best LUB possible -// as well as relevant nulls (nulls force us to keep the type nullable). -using FieldInfo = LUBFinder; - -struct FieldInfoScanner - : public StructUtils::StructScanner { - Pass* create() override { - return new FieldInfoScanner(functionNewInfos, functionSetGetInfos); - } - - FieldInfoScanner( - StructUtils::FunctionStructValuesMap& functionNewInfos, - StructUtils::FunctionStructValuesMap& functionSetGetInfos) - : StructUtils::StructScanner( - functionNewInfos, functionSetGetInfos) {} - - void noteExpression(Expression* expr, - HeapType type, - Index index, - FieldInfo& info) { - info.noteUpdatableExpression(expr); - } - - void - noteDefault(Type fieldType, HeapType type, Index index, FieldInfo& info) { - // Default values do not affect what the heap type of a field can be turned - // into. Note them, however, as they force us to keep the type nullable. - if (fieldType.isRef()) { - info.noteNullDefault(); - } - } - - void noteCopy(HeapType type, Index index, FieldInfo& info) { - // Copies do not add any type requirements at all: the type will always be - // read and written to a place with the same type. - } - - void noteRead(HeapType type, Index index, FieldInfo& info) { - // Nothing to do for a read, we just care about written values. - } -}; - -struct TypeRefining : public Pass { - StructUtils::StructValuesMap finalInfos; - - void run(PassRunner* runner, Module* module) override { - if (getTypeSystem() != TypeSystem::Nominal) { - Fatal() << "TypeRefining requires nominal typing"; - } - - // Find and analyze struct operations inside each function. - StructUtils::FunctionStructValuesMap functionNewInfos(*module), - functionSetGetInfos(*module); - FieldInfoScanner scanner(functionNewInfos, functionSetGetInfos); - scanner.run(runner, module); - scanner.runOnModuleCode(runner, module); - - // Combine the data from the functions. - StructUtils::StructValuesMap combinedNewInfos; - StructUtils::StructValuesMap combinedSetGetInfos; - functionNewInfos.combineInto(combinedNewInfos); - functionSetGetInfos.combineInto(combinedSetGetInfos); - - // Propagate things written during new to supertypes, as they must also be - // able to contain that type. Propagate things written using set to subtypes - // as well, as the reference might be to a supertype if the field is present - // there. - StructUtils::TypeHierarchyPropagator propagator(*module); - propagator.propagateToSuperTypes(combinedNewInfos); - propagator.propagateToSuperAndSubTypes(combinedSetGetInfos); - - // Combine everything together. - combinedNewInfos.combineInto(finalInfos); - combinedSetGetInfos.combineInto(finalInfos); - - // While we do the following work, see if we have anything to optimize, so - // that we can avoid wasteful work later if not. - bool canOptimize = false; - - // We have combined all the information we have about writes to the fields, - // but we still need to make sure that the new types makes sense. In - // particular, subtyping cares about things like mutability, and we also - // need to handle the case where we have no writes to a type but do have - // them to subtypes or supertypes; in all these cases, we must preserve - // that a field is always a subtype of the parent field. To do so, we go - // through all the types downward from supertypes to subtypes, ensuring the - // subtypes are suitable. - auto& subTypes = propagator.subTypes; - UniqueDeferredQueue work; - for (auto type : subTypes.types) { - if (type.isStruct() && !type.getSuperType()) { - work.push(type); - } - } - while (!work.empty()) { - auto type = work.pop(); - - // First, find fields that have nothing written to them at all, and set - // their value to their old type. We must pick some type for the field, - // and we have nothing better to go on. (If we have a super, and it does - // have writes, then we may further update this type later, see the - // isSubType check in the loop after this.) - auto& fields = type.getStruct().fields; - for (Index i = 0; i < fields.size(); i++) { - auto oldType = fields[i].type; - auto& info = finalInfos[type][i]; - if (!info.noted()) { - info = LUBFinder(oldType); - } - } - - // Next ensure proper subtyping of this struct's fields versus its super. - if (auto super = type.getSuperType()) { - auto& superFields = super->getStruct().fields; - for (Index i = 0; i < superFields.size(); i++) { - auto newSuperType = finalInfos[*super][i].getBestPossible(); - auto& info = finalInfos[type][i]; - auto newType = info.getBestPossible(); - if (!Type::isSubType(newType, newSuperType)) { - // To ensure we are a subtype of the super's field, simply copy that - // value, which is more specific than us. - // - // This situation cannot happen normally, but if a type is not used - // then it can. For example, imagine that $B and $C are subtypes of - // $A, and that $C is never created anywhere. A struct.new of $B - // propagates info to $A (forcing $A's type to take it into account - // and not be more specific than it), but that does not reach $C - // (struct.new propagates only up, not down; if it propagated down - // then we could never specialize a subtype more than its super). If - // $C had some value written to it then that value would force the - // LUB of $A to take it into account, but as here $C is never even - // created, that does not happen. And then if we update $A's type - // to something more specific than $C's old type, we end up with the - // problem that this code path fixes: we just need to get $C's type - // to be identical to its super so that validation works. - info = LUBFinder(newSuperType); - } else if (fields[i].mutable_ == Mutable) { - // Mutable fields must have identical types, so we cannot - // specialize. - // TODO: Perhaps we should be using a new Field::isSubType() method - // here? This entire analysis might be done on fields, and not - // types, which would also handle more things added to fields - // in the future. - info = LUBFinder(newSuperType); - } - } - } - - // After all those decisions, see if we found anything to optimize. - for (Index i = 0; i < fields.size(); i++) { - auto oldType = fields[i].type; - auto& lub = finalInfos[type][i]; - auto newType = lub.getBestPossible(); - if (newType != oldType) { - canOptimize = true; - lub.updateNulls(); - } - } - - for (auto subType : subTypes.getSubTypes(type)) { - work.push(subType); - } - } - - if (canOptimize) { - updateInstructions(*module, runner); - updateTypes(*module, runner); - } - } - - // If we change types then some instructions may need to be modified. - // Specifically, we assume that reads from structs impose no constraints on - // us, so that we can optimize maximally. If a struct is never created nor - // written to, but only read from, then we have literally no constraints on it - // at all, and we can end up with a situation where we alter the type to - // something that is invalid for that read. To ensure the code still - // validates, simply remove such reads. - void updateInstructions(Module& wasm, PassRunner* runner) { - struct ReadUpdater : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - TypeRefining& parent; - - ReadUpdater(TypeRefining& parent) : parent(parent) {} - - ReadUpdater* create() override { return new ReadUpdater(parent); } - - void visitStructGet(StructGet* curr) { - if (curr->ref->type == Type::unreachable) { - return; - } - - auto oldType = curr->ref->type.getHeapType(); - auto newFieldType = - parent.finalInfos[oldType][curr->index].getBestPossible(); - if (!Type::isSubType(newFieldType, curr->type)) { - // This instruction is invalid, so it must be the result of the - // situation described above: we ignored the read during our - // inference, and optimized accordingly, and so now we must remove it - // to keep the module validating. It doesn't matter what we emit here, - // since there are no struct.new or struct.sets for this type, so this - // code is logically unreachable. - // - // Note that we emit an unreachable here, which changes the type, and - // so we should refinalize. However, we will be refinalizing later - // anyhow in updateTypes, so there is no need. - Builder builder(*getModule()); - replaceCurrent(builder.makeSequence(builder.makeDrop(curr->ref), - builder.makeUnreachable())); - } - } - }; - - ReadUpdater updater(*this); - updater.run(runner, &wasm); - updater.runOnModuleCode(runner, &wasm); - } - - void updateTypes(Module& wasm, PassRunner* runner) { - class TypeRewriter : public GlobalTypeRewriter { - TypeRefining& parent; - - public: - TypeRewriter(Module& wasm, TypeRefining& parent) - : GlobalTypeRewriter(wasm), parent(parent) {} - - void modifyStruct(HeapType oldStructType, Struct& struct_) override { - const auto& oldFields = oldStructType.getStruct().fields; - auto& newFields = struct_.fields; - - for (Index i = 0; i < newFields.size(); i++) { - auto oldType = oldFields[i].type; - if (!oldType.isRef()) { - continue; - } - auto newType = parent.finalInfos[oldStructType][i].getBestPossible(); - newFields[i].type = getTempType(newType); - } - } - }; - - TypeRewriter(wasm, *this).update(); - - ReFinalize().run(runner, &wasm); - } -}; - -} // anonymous namespace - -Pass* createTypeRefiningPass() { return new TypeRefining(); } - -} // namespace wasm diff -Nru binaryen-108/src/passes/Vacuum.cpp binaryen-99/src/passes/Vacuum.cpp --- binaryen-108/src/passes/Vacuum.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/Vacuum.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -69,6 +69,7 @@ // i32.eqz returns the same type as it receives. But for an expression that // returns a different type, if the type matters then we cannot replace it. Expression* optimize(Expression* curr, bool resultUsed, bool typeMatters) { + FeatureSet features = getModule()->features; auto type = curr->type; // If the type is none, then we can never replace it with another type. if (type == Type::none) { @@ -101,17 +102,17 @@ return curr; } // Check if this expression itself has side effects, ignoring children. - EffectAnalyzer self(getPassOptions(), *getModule()); + EffectAnalyzer self(getPassOptions(), features); self.visit(curr); - if (self.hasUnremovableSideEffects()) { + if (self.hasSideEffects()) { return curr; } // The result isn't used, and this has no side effects itself, so we can // get rid of it. However, the children may have side effects. SmallVector childrenWithEffects; for (auto* child : ChildIterator(curr)) { - if (EffectAnalyzer(getPassOptions(), *getModule(), child) - .hasUnremovableSideEffects()) { + if (EffectAnalyzer(getPassOptions(), features, child) + .hasSideEffects()) { childrenWithEffects.push_back(child); } } @@ -144,19 +145,13 @@ ExpressionAnalyzer::isResultUsed(expressionStack, getFunction()); auto* optimized = optimize(child, used, true); if (!optimized) { - auto childType = child->type; - if (childType.isConcrete()) { - if (LiteralUtils::canMakeZero(childType)) { - // We can't just skip a final concrete element, even if it isn't - // used. Instead, replace it with something that's easy to optimize - // out (for example, code-folding can merge out identical zeros at - // the end of if arms). - optimized = LiteralUtils::makeZero(childType, *getModule()); - } else { - // Don't optimize it out. - optimized = child; - } - } else if (childType == Type::unreachable) { + if (child->type.isConcrete()) { + // We can't just skip a final concrete element, even if it isn't used. + // Instead, replace it with something that's easy to optimize out (for + // example, code-folding can merge out identical zeros at the end of + // if arms). + optimized = LiteralUtils::makeZero(child->type, *getModule()); + } else if (child->type == Type::unreachable) { // Don't try to optimize out an unreachable child (dce can do that // properly). optimized = child; @@ -252,8 +247,9 @@ } } } else { - // This is an if without an else. If the body is empty, we do not need it. + // no else if (curr->ifTrue->is()) { + // no nothing replaceCurrent(Builder(*getModule()).makeDrop(curr->condition)); } } @@ -279,24 +275,6 @@ replaceCurrent(set); return; } - - // If the value has no side effects, or it has side effects we can remove, - // do so. This basically means that if noTrapsHappen is set then we can - // use that assumption (that no trap actually happens at runtime) and remove - // a trapping value. - // - // TODO: A complete CFG analysis for noTrapsHappen mode, removing all code - // that definitely reaches a trap, *even if* it has side effects. - // - // Note that we check the type here to avoid removing unreachable code - we - // leave that for DCE. - if (curr->type == Type::none && - !EffectAnalyzer(getPassOptions(), *getModule(), curr) - .hasUnremovableSideEffects()) { - ExpressionManipulator::nop(curr); - return; - } - // if we are dropping a block's return value, we might be able to remove it // entirely if (auto* block = curr->value->dynCast()) { @@ -313,7 +291,7 @@ BranchUtils::BranchSeeker seeker(block->name); Expression* temp = block; seeker.walk(temp); - if (seeker.found && Type::hasLeastUpperBound(seeker.types)) { + if (seeker.found && seeker.valueType != Type::none) { canPop = false; } } @@ -360,25 +338,24 @@ void visitTry(Try* curr) { // If try's body does not throw, the whole try-catch can be replaced with // the try's body. - if (!EffectAnalyzer(getPassOptions(), *getModule(), curr->body).throws()) { + if (!EffectAnalyzer(getPassOptions(), getModule()->features, curr->body) + .throws) { replaceCurrent(curr->body); - for (auto* catchBody : curr->catchBodies) { - typeUpdater.noteRecursiveRemoval(catchBody); - } + typeUpdater.noteRecursiveRemoval(curr->catchBody); } } void visitFunction(Function* curr) { auto* optimized = - optimize(curr->body, curr->getResults() != Type::none, true); + optimize(curr->body, curr->sig.results != Type::none, true); if (optimized) { curr->body = optimized; } else { ExpressionManipulator::nop(curr->body); } - if (curr->getResults() == Type::none && - !EffectAnalyzer(getPassOptions(), *getModule(), curr->body) - .hasUnremovableSideEffects()) { + if (curr->sig.results == Type::none && + !EffectAnalyzer(getPassOptions(), getModule()->features, curr->body) + .hasSideEffects()) { ExpressionManipulator::nop(curr->body); } } diff -Nru binaryen-108/src/passes/WasmIntrinsics.cpp.in binaryen-99/src/passes/WasmIntrinsics.cpp.in --- binaryen-108/src/passes/WasmIntrinsics.cpp.in 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/passes/WasmIntrinsics.cpp.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -#include "passes/intrinsics-module.h" - -static const char theModule[@WASM_INTRINSICS_SIZE@] = { -@WASM_INTRINSICS_EMBED@ -}; - -namespace wasm { -const char* IntrinsicsModuleWast = theModule; -} diff -Nru binaryen-108/src/pass.h binaryen-99/src/pass.h --- binaryen-108/src/pass.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/pass.h 2021-01-07 20:01:06.000000000 +0000 @@ -39,14 +39,9 @@ typedef std::function Creator; void registerPass(const char* name, const char* description, Creator create); - // Register a pass that's used for internal testing. These passes do not show - // up in --help. - void - registerTestPass(const char* name, const char* description, Creator create); std::unique_ptr createPass(std::string name); std::vector getRegisteredNames(); std::string getPassDescription(std::string name); - bool isPassHidden(std::string name); private: void registerPasses(); @@ -54,10 +49,9 @@ struct PassInfo { std::string description; Creator create; - bool hidden; PassInfo() = default; - PassInfo(std::string description, Creator create, bool hidden = false) - : description(description), create(create), hidden(hidden) {} + PassInfo(std::string description, Creator create) + : description(description), create(create) {} }; std::map passInfos; }; @@ -75,10 +69,9 @@ // More generally, with 2 items we may have a local.get, but no way to // require it to be saved instead of directly consumed. Index alwaysInlineMaxSize = 2; - // Function size which we inline when there is only one caller. By default we - // inline all such functions (as after inlining we can remove the original - // function). - Index oneCallerInlineMaxSize = -1; + // Function size which we inline when there is only one caller. + // FIXME: this should logically be higher than flexibleInlineMaxSize. + Index oneCallerInlineMaxSize = 15; // Function size above which we never inline, ignoring the various flexible // factors (like whether we are optimizing for size or speed) that could // influence us. @@ -88,11 +81,6 @@ // Loops usually mean the function does heavy work, so the call overhead // is not significant and we do not inline such functions by default. bool allowFunctionsWithLoops = false; - // The number of ifs to allow partial inlining of their conditions. A value of - // zero disables partial inlining. - // TODO: Investigate enabling this. Locally 4 appears useful on real-world - // code, but reports of regressions have arrived. - Index partialInliningIfs = 0; }; struct PassOptions { @@ -109,38 +97,7 @@ // Tweak thresholds for the Inlining pass. InliningOptions inlining; // Optimize assuming things like div by 0, bad load/store, will not trap. - // This is deprecated in favor of trapsNeverHappen. bool ignoreImplicitTraps = false; - // Optimize assuming a trap will never happen at runtime. This is similar to - // ignoreImplicitTraps, but different: - // - // * ignoreImplicitTraps simply ignores the side effect of trapping when it - // computes side effects, and then passes work with that data. - // * trapsNeverHappen assumes that if an instruction with a possible trap is - // reached, then it does not trap, and an (unreachable) - that always - // traps - is never reached. - // - // The main difference is that in trapsNeverHappen mode we will not move - // around code that might trap, like this: - // - // (if (condition) (code)) - // - // If (code) might trap, ignoreImplicitTraps ignores that trap, and it might - // end up moving (code) to happen before the (condition), that is, - // unconditionally. trapsNeverHappen, on the other hand, does not ignore the - // side effect of the trap; instead, it will potentially remove the trapping - // instruction, if it can - it is always safe to remove a trap in this mode, - // as the traps are assumed to not happen. Where it cannot remove the side - // effect, it will at least not move code around. - // - // A consequence of this difference is that code that puts a possible trap - // behind a condition is unsafe in ignoreImplicitTraps, but safe in - // trapsNeverHappen. In general, trapsNeverHappen is safe on production code - // where traps are either fatal errors or assertions, and it is assumed - // neither of those can happen (and it is undefined behavior if they do). - // - // TODO: deprecate and remove ignoreImplicitTraps. - bool trapsNeverHappen = false; // Optimize assuming that the low 1K of memory is not valid memory for the // application to use. In that case, we can optimize load/store offsets in // many cases. @@ -166,13 +123,10 @@ // passes. std::map arguments; - // -Os is our default - static constexpr const int DEFAULT_OPTIMIZE_LEVEL = 2; - static constexpr const int DEFAULT_SHRINK_LEVEL = 1; - void setDefaultOptimizationOptions() { - optimizeLevel = DEFAULT_OPTIMIZE_LEVEL; - shrinkLevel = DEFAULT_SHRINK_LEVEL; + // -Os is our default + optimizeLevel = 2; + shrinkLevel = 1; } static PassOptions getWithDefaultOptimizationOptions() { @@ -217,12 +171,6 @@ PassRunner(const PassRunner&) = delete; PassRunner& operator=(const PassRunner&) = delete; - // But we can make it easy to create a nested runner - // TODO: Go through and use this in more places - explicit PassRunner(const PassRunner* runner) - : wasm(runner->wasm), allocator(runner->allocator), - options(runner->options), isNested(true) {} - void setDebug(bool debug) { options.debug = debug; // validate everything by default if debugging @@ -235,7 +183,11 @@ // Add a pass using its name. void add(std::string passName) { - doAdd(PassRegistry::get()->createPass(passName)); + auto pass = PassRegistry::get()->createPass(passName); + if (!pass) { + Fatal() << "Could not find pass: " << passName << "\n"; + } + doAdd(std::move(pass)); } // Add a pass given an instance. @@ -243,16 +195,6 @@ doAdd(std::move(pass)); } - // Adds the pass if there are no DWARF-related issues. There is an issue if - // there is DWARF and if the pass does not support DWARF (as defined by the - // pass returning true from invalidatesDWARF); otherwise, if there is no - // DWARF, or the pass supports it, the pass is added. - // In contrast to add(), add() will always add the pass, and it will print a - // warning if there is an issue with DWARF. This method is useful for a pass - // that is optional, to avoid adding it and therefore avoid getting the - // warning. - void addIfNoDWARFIssues(std::string passName); - // Adds the default set of optimization passes; this is // what -O does. void addDefaultOptimizationPasses(); @@ -301,20 +243,10 @@ // 3: like 1, and also dumps out byn-* files for each pass as it is run. static int getPassDebug(); - // Returns whether a pass by that name will remove debug info. - static bool passRemovesDebugInfo(const std::string& name); - -private: - // Whether this is a nested pass runner. +protected: bool isNested = false; - // Whether the passes we have added so far to be run (but not necessarily run - // yet) have removed DWARF. - bool addedPassesRemovedDWARF = false; - - // Whether this pass runner has run. A pass runner should only be run once. - bool ran = false; - +private: void doAdd(std::unique_ptr pass); void runPass(Pass* pass); @@ -327,8 +259,6 @@ // If a function is passed, we operate just on that function; // otherwise, the whole module. void handleAfterEffects(Pass* pass, Function* func = nullptr); - - bool shouldPreserveDWARF(); }; // @@ -382,10 +312,6 @@ // out any Stack IR - it would need to be regenerated and optimized. virtual bool modifiesBinaryenIR() { return true; } - // Some passes modify the wasm in a way that we cannot update DWARF properly - // for. This is used to issue a proper warning about that. - virtual bool invalidatesDWARF() { return false; } - std::string name; protected: @@ -400,7 +326,7 @@ // template class WalkerPass : public Pass, public WalkerType { - PassRunner* runner = nullptr; + PassRunner* runner; protected: typedef WalkerPass super; @@ -430,12 +356,6 @@ WalkerType::walkFunction(func); } - void runOnModuleCode(PassRunner* runner, Module* module) { - setPassRunner(runner); - WalkerType::setModule(module); - WalkerType::walkModuleCode(module); - } - PassRunner* getPassRunner() { return runner; } PassOptions& getPassOptions() { return runner->options; } diff -Nru binaryen-108/src/pretty_printing.h binaryen-99/src/pretty_printing.h --- binaryen-108/src/pretty_printing.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/pretty_printing.h 2021-01-07 20:01:06.000000000 +0000 @@ -62,14 +62,16 @@ return o << '"'; } -inline std::ostream& printMajor(std::ostream& o, const char* str) { +inline std::ostream& +printMajor(std::ostream& o, const char* str, bool major = false) { prepareMajorColor(o); o << str; restoreNormalColor(o); return o; } -inline std::ostream& printMedium(std::ostream& o, const char* str) { +inline std::ostream& +printMedium(std::ostream& o, const char* str, bool major = false) { prepareColor(o); o << str; restoreNormalColor(o); diff -Nru binaryen-108/src/shared-constants.h binaryen-99/src/shared-constants.h --- binaryen-108/src/shared-constants.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/shared-constants.h 2021-01-07 20:01:06.000000000 +0000 @@ -21,6 +21,7 @@ namespace wasm { +extern Name WASM_CALL_CTORS; extern Name MEMORY_BASE; extern Name TABLE_BASE; extern Name STACK_POINTER; @@ -59,13 +60,13 @@ extern Name BR; extern Name FUNCREF; extern Name FAKE_RETURN; -extern Name DELEGATE_CALLER_TARGET; extern Name MUT; extern Name SPECTEST; extern Name PRINT; extern Name EXIT; extern Name SHARED; -extern Name TAG; +extern Name EVENT; +extern Name ATTR; } // namespace wasm diff -Nru binaryen-108/src/shell-interface.h binaryen-99/src/shell-interface.h --- binaryen-108/src/shell-interface.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/shell-interface.h 2021-01-07 20:01:06.000000000 +0000 @@ -25,24 +25,15 @@ #include "ir/module-utils.h" #include "shared-constants.h" #include "support/name.h" -#include "support/utilities.h" #include "wasm-interpreter.h" #include "wasm.h" namespace wasm { -// An exception emitted when exit() is called. struct ExitException {}; - -// An exception emitted when a wasm trap occurs. struct TrapException {}; -// An exception emitted when a host limitation is hit. (These are not wasm traps -// as they are not in the spec; for example, the spec has no limit on how much -// GC memory may be allocated, but hosts have limits.) -struct HostLimitException {}; - -struct ShellExternalInterface : ModuleRunner::ExternalInterface { +struct ShellExternalInterface : ModuleInstance::ExternalInterface { // The underlying memory can be accessed through unaligned pointers which // isn't well-behaved in C++. WebAssembly nonetheless expects it to behave // properly. Avoid emitting unaligned load/store by checking for alignment @@ -94,46 +85,60 @@ } } memory; - std::unordered_map> tables; - std::map> linkedInstances; + std::vector table; - ShellExternalInterface( - std::map> linkedInstances_ = {}) - : memory() { - linkedInstances.swap(linkedInstances_); - } + ShellExternalInterface() : memory() {} virtual ~ShellExternalInterface() = default; - ModuleRunner* getImportInstance(Importable* import) { - auto it = linkedInstances.find(import->module); - if (it == linkedInstances.end()) { - Fatal() << "importGlobals: unknown import: " << import->module.str << "." - << import->base.str; - } - return it->second.get(); - } - - void init(Module& wasm, ModuleRunner& instance) override { - if (wasm.memory.exists && !wasm.memory.imported()) { - memory.resize(wasm.memory.initial * wasm::Memory::kPageSize); - } - ModuleUtils::iterDefinedTables( - wasm, [&](Table* table) { tables[table->name].resize(table->initial); }); + void init(Module& wasm, ModuleInstance& instance) override { + memory.resize(wasm.memory.initial * wasm::Memory::kPageSize); + table.resize(wasm.table.initial); } void importGlobals(std::map& globals, Module& wasm) override { + // add spectest globals ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) { - auto inst = getImportInstance(import); - auto* exportedGlobal = inst->wasm.getExportOrNull(import->base); - if (!exportedGlobal) { - Fatal() << "importGlobals: unknown import: " << import->module.str - << "." << import->name.str; + if (import->module == SPECTEST && import->base.startsWith("global_")) { + TODO_SINGLE_COMPOUND(import->type); + switch (import->type.getBasic()) { + case Type::i32: + globals[import->name] = {Literal(int32_t(666))}; + break; + case Type::i64: + globals[import->name] = {Literal(int64_t(666))}; + break; + case Type::f32: + globals[import->name] = {Literal(float(666.6))}; + break; + case Type::f64: + globals[import->name] = {Literal(double(666.6))}; + break; + case Type::v128: + assert(false && "v128 not implemented yet"); + case Type::funcref: + case Type::externref: + case Type::exnref: + case Type::anyref: + case Type::eqref: + globals[import->name] = {Literal::makeNull(import->type)}; + break; + case Type::i31ref: + WASM_UNREACHABLE("TODO: i31ref"); + case Type::none: + case Type::unreachable: + WASM_UNREACHABLE("unexpected type"); + } } - globals[import->name] = inst->globals[exportedGlobal->value]; }); + if (wasm.memory.imported() && wasm.memory.module == SPECTEST && + wasm.memory.base == MEMORY) { + // imported memory has initial 1 and max 2 + wasm.memory.initial = 1; + wasm.memory.max = 2; + } } - Literals callImport(Function* import, Literals& arguments) override { + Literals callImport(Function* import, LiteralList& arguments) override { if (import->module == SPECTEST && import->base.startsWith(PRINT)) { for (auto argument : arguments) { std::cout << argument << " : " << argument.type << '\n'; @@ -143,49 +148,36 @@ // XXX hack for torture tests std::cout << "exit()\n"; throw ExitException(); - } else if (auto* inst = getImportInstance(import)) { - return inst->callExport(import->base, arguments); } Fatal() << "callImport: unknown import: " << import->module.str << "." << import->name.str; } - Literals callTable(Name tableName, - Index index, - HeapType sig, - Literals& arguments, + Literals callTable(Index index, + Signature sig, + LiteralList& arguments, Type results, - ModuleRunner& instance) override { - - auto it = tables.find(tableName); - if (it == tables.end()) { - trap("callTable on non-existing table"); - } - - auto& table = it->second; + ModuleInstance& instance) override { if (index >= table.size()) { trap("callTable overflow"); } - Function* func = nullptr; - if (table[index].isFunction() && !table[index].isNull()) { - func = instance.wasm.getFunctionOrNull(table[index].getFunc()); - } + auto* func = instance.wasm.getFunctionOrNull(table[index]); if (!func) { trap("uninitialized table element"); } - if (sig != func->type) { - trap("callIndirect: function types don't match"); + if (sig != func->sig) { + trap("callIndirect: function signatures don't match"); } - if (func->getParams().size() != arguments.size()) { + if (func->sig.params.size() != arguments.size()) { trap("callIndirect: bad # of arguments"); } size_t i = 0; - for (const auto& param : func->getParams()) { + for (const auto& param : func->sig.params) { if (!Type::isSubType(arguments[i++].type, param)) { trap("callIndirect: bad argument type"); } } - if (func->getResults() != results) { + if (func->sig.results != results) { trap("callIndirect: bad result type"); } if (func->imported()) { @@ -223,32 +215,7 @@ memory.set>(addr, value); } - Index tableSize(Name tableName) override { - return (Index)tables[tableName].size(); - } - - void tableStore(Name tableName, Index index, const Literal& entry) override { - auto& table = tables[tableName]; - if (index >= table.size()) { - trap("out of bounds table access"); - } else { - table[index] = entry; - } - } - - Literal tableLoad(Name tableName, Index index) override { - auto it = tables.find(tableName); - if (it == tables.end()) { - trap("tableGet on non-existing table"); - } - - auto& table = it->second; - if (index >= table.size()) { - trap("out of bounds table access"); - } - - return table[index]; - } + void tableStore(Address addr, Name entry) override { table[addr] = entry; } bool growMemory(Address /*oldSize*/, Address newSize) override { // Apply a reasonable limit on memory size, 1GB, to avoid DOS on the @@ -260,30 +227,12 @@ return true; } - bool growTable(Name name, - const Literal& value, - Index /*oldSize*/, - Index newSize) override { - // Apply a reasonable limit on table size, 1GB, to avoid DOS on the - // interpreter. - if (newSize > 1024 * 1024 * 1024) { - return false; - } - tables[name].resize(newSize, value); - return true; - } - void trap(const char* why) override { std::cout << "[trap " << why << "]\n"; throw TrapException(); } - void hostLimit(const char* why) override { - std::cout << "[host limit " << why << "]\n"; - throw HostLimitException(); - } - - void throwException(const WasmException& exn) override { throw exn; } + void throwException(Literal exn) override { throw WasmException(exn); } }; } // namespace wasm diff -Nru binaryen-108/src/support/bits.cpp binaryen-99/src/support/bits.cpp --- binaryen-108/src/support/bits.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/support/bits.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -22,7 +22,9 @@ #include #endif -namespace wasm::Bits { +namespace wasm { + +namespace Bits { int popCount(uint8_t v) { // Small table lookup. @@ -196,4 +198,6 @@ uint32_t pow2(uint32_t v) { return v < 32 ? 1 << v : 0; } -} // namespace wasm::Bits +} // namespace Bits + +} // namespace wasm diff -Nru binaryen-108/src/support/bits.h binaryen-99/src/support/bits.h --- binaryen-108/src/support/bits.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/support/bits.h 2021-01-07 20:01:06.000000000 +0000 @@ -31,7 +31,9 @@ * avoiding implementations with large lookup tables. */ -namespace wasm::Bits { +namespace wasm { + +namespace Bits { int popCount(uint8_t); int popCount(uint16_t); @@ -94,6 +96,8 @@ uint32_t log2(uint32_t v); uint32_t pow2(uint32_t v); -} // namespace wasm::Bits +} // namespace Bits + +} // namespace wasm #endif // wasm_support_bits_h diff -Nru binaryen-108/src/support/colors.h binaryen-99/src/support/colors.h --- binaryen-108/src/support/colors.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/support/colors.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,7 +20,6 @@ #include namespace Colors { - void setEnabled(bool enabled); bool isEnabled(); @@ -59,7 +58,6 @@ inline void blue(std::ostream& stream) {} inline void bold(std::ostream& stream) {} #endif - } // namespace Colors #endif // wasm_support_color_h diff -Nru binaryen-108/src/support/command-line.cpp binaryen-99/src/support/command-line.cpp --- binaryen-108/src/support/command-line.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/support/command-line.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -53,67 +53,38 @@ Options::Options(const std::string& command, const std::string& description) : debug(false), positional(Arguments::Zero) { - std::string GeneralOption = "General options"; - add("--version", "", "Output version information and exit", - GeneralOption, Arguments::Zero, [command](Options*, const std::string&) { - std::cout << command << " version " << PROJECT_VERSION << '\n'; + std::cout << command << " version " << PROJECT_VERSION << "\n"; exit(0); }); add("--help", "-h", "Show this help message and exit", - GeneralOption, Arguments::Zero, [this, command, description](Options* o, const std::string&) { - for (size_t i = 0; i < SCREEN_WIDTH; i++) { - std::cout << '='; - } - std::cout << '\n'; std::cout << command; if (positional != Arguments::Zero) { std::cout << ' ' << positionalName; } std::cout << "\n\n"; printWrap(std::cout, 0, description); - std::cout << '\n'; - for (size_t i = 0; i < SCREEN_WIDTH; i++) { - std::cout << '='; - } - std::cout << '\n'; + std::cout << "\n\nOptions:\n"; size_t optionWidth = 0; for (const auto& o : options) { - if (o.hidden) { - continue; - } optionWidth = std::max(optionWidth, o.longName.size() + o.shortName.size()); } - for (int i = int(categories.size()) - 1; i >= 0; i--) { - auto& category = categories[i]; - std::cout << "\n\n" << category << ":\n"; - for (size_t i = 0; i < category.size() + 1; i++) { - std::cout << '-'; - } + for (const auto& o : options) { + bool long_n_short = o.longName.size() != 0 && o.shortName.size() != 0; + size_t pad = 1 + optionWidth - o.longName.size() - o.shortName.size(); + std::cout << " " << o.longName << (long_n_short ? ',' : ' ') + << o.shortName << std::string(pad, ' '); + printWrap(std::cout, optionWidth + 4, o.description); std::cout << '\n'; - for (const auto& o : options) { - if (o.hidden || o.category != category) { - continue; - } - std::cout << '\n'; - bool long_n_short = - o.longName.size() != 0 && o.shortName.size() != 0; - size_t pad = - 1 + optionWidth - o.longName.size() - o.shortName.size(); - std::cout << " " << o.longName << (long_n_short ? ',' : ' ') - << o.shortName << std::string(pad, ' '); - printWrap(std::cout, optionWidth + 4, o.description); - std::cout << '\n'; - } } std::cout << '\n'; exit(EXIT_SUCCESS); @@ -121,7 +92,6 @@ add("--debug", "-d", "Print debug information to stderr", - GeneralOption, Arguments::Optional, [&](Options* o, const std::string& arguments) { debug = true; @@ -134,18 +104,9 @@ Options& Options::add(const std::string& longName, const std::string& shortName, const std::string& description, - const std::string& category, Arguments arguments, - const Action& action, - bool hidden) { - options.push_back( - {longName, shortName, description, category, arguments, action, hidden, 0}); - - if (std::find(categories.begin(), categories.end(), category) == - categories.end()) { - categories.push_back(category); - } - + const Action& action) { + options.push_back({longName, shortName, description, arguments, action, 0}); return *this; } @@ -162,34 +123,30 @@ assert(argc > 0 && "expect at least program name as an argument"); size_t positionalsSeen = 0; auto dashes = [](const std::string& s) { - for (size_t i = 0; i < s.size(); ++i) { + for (size_t i = 0;; ++i) { if (s[i] != '-') { return i; } } - return s.size(); }; for (size_t i = 1, e = argc; i != e; ++i) { std::string currentOption = argv[i]; - // "-" alone is a positional option - if (dashes(currentOption) == 0 || currentOption == "-") { + if (dashes(currentOption) == 0) { // Positional. switch (positional) { case Arguments::Zero: - // Optional arguments must use --flag=A format, and not separated by - // spaces (which would be ambiguous). - case Arguments::Optional: std::cerr << "Unexpected positional argument '" << currentOption << "'\n"; exit(EXIT_FAILURE); case Arguments::One: + case Arguments::Optional: if (positionalsSeen) { std::cerr << "Unexpected second positional argument '" << currentOption << "' for " << positionalName << '\n'; exit(EXIT_FAILURE); } - [[fallthrough]]; + // Fallthrough. case Arguments::N: positionalAction(this, currentOption); ++positionalsSeen; @@ -229,7 +186,7 @@ << currentOption << "'\n"; exit(EXIT_FAILURE); } - [[fallthrough]]; + // Fallthrough. case Arguments::N: if (!argument.size()) { if (i + 1 == e) { @@ -241,6 +198,11 @@ } break; case Arguments::Optional: + if (!argument.size()) { + if (i + 1 != e) { + argument = argv[++i]; + } + } break; } option->action(this, argument); diff -Nru binaryen-108/src/support/command-line.h binaryen-99/src/support/command-line.h --- binaryen-108/src/support/command-line.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/support/command-line.h 2021-01-07 20:01:06.000000000 +0000 @@ -34,19 +34,7 @@ class Options { public: using Action = std::function; - - enum class Arguments { - // No arguments. - Zero, - // One argument, in the form --flag A or --flag=A - One, - // Multiple arguments, in the form --flag A B C - N, - // An optional single argument, in the form --flag=A (we disallow --flag A - // as that would be ambiguous regarding whether A is another flag, or an - // argument to us). - Optional - }; + enum class Arguments { Zero, One, N, Optional }; bool debug; std::map extra; @@ -56,10 +44,8 @@ Options& add(const std::string& longName, const std::string& shortName, const std::string& description, - const std::string& category, Arguments arguments, - const Action& action, - bool hidden = false); + const Action& action); Options& add_positional(const std::string& name, Arguments arguments, const Action& action); @@ -70,19 +56,14 @@ std::string longName; std::string shortName; std::string description; - std::string category; Arguments arguments; Action action; - bool hidden; size_t seen; }; std::vector
&& curr) { - return addModuleElement(tables, tablesMap, std::move(curr), "addTable"); -} - -ElementSegment* -Module::addElementSegment(std::unique_ptr&& curr) { - return addModuleElement( - elementSegments, elementSegmentsMap, std::move(curr), "addElementSegment"); -} - Global* Module::addGlobal(std::unique_ptr&& curr) { return addModuleElement(globals, globalsMap, std::move(curr), "addGlobal"); } -Tag* Module::addTag(std::unique_ptr&& curr) { - return addModuleElement(tags, tagsMap, std::move(curr), "addTag"); +Event* Module::addEvent(std::unique_ptr&& curr) { + return addModuleElement(events, eventsMap, std::move(curr), "addEvent"); } void Module::addStart(const Name& s) { start = s; } @@ -1410,16 +1351,12 @@ void Module::removeFunction(Name name) { removeModuleElement(functions, functionsMap, name); } -void Module::removeTable(Name name) { - removeModuleElement(tables, tablesMap, name); -} -void Module::removeElementSegment(Name name) { - removeModuleElement(elementSegments, elementSegmentsMap, name); -} void Module::removeGlobal(Name name) { removeModuleElement(globals, globalsMap, name); } -void Module::removeTag(Name name) { removeModuleElement(tags, tagsMap, name); } +void Module::removeEvent(Name name) { + removeModuleElement(events, eventsMap, name); +} template void removeModuleElements(Vector& v, @@ -1443,17 +1380,11 @@ void Module::removeFunctions(std::function pred) { removeModuleElements(functions, functionsMap, pred); } -void Module::removeTables(std::function pred) { - removeModuleElements(tables, tablesMap, pred); -} -void Module::removeElementSegments(std::function pred) { - removeModuleElements(elementSegments, elementSegmentsMap, pred); -} void Module::removeGlobals(std::function pred) { removeModuleElements(globals, globalsMap, pred); } -void Module::removeTags(std::function pred) { - removeModuleElements(tags, tagsMap, pred); +void Module::removeEvents(std::function pred) { + removeModuleElements(events, eventsMap, pred); } void Module::updateMaps() { @@ -1465,21 +1396,13 @@ for (auto& curr : exports) { exportsMap[curr->name] = curr.get(); } - tablesMap.clear(); - for (auto& curr : tables) { - tablesMap[curr->name] = curr.get(); - } - elementSegmentsMap.clear(); - for (auto& curr : elementSegments) { - elementSegmentsMap[curr->name] = curr.get(); - } globalsMap.clear(); for (auto& curr : globals) { globalsMap[curr->name] = curr.get(); } - tagsMap.clear(); - for (auto& curr : tags) { - tagsMap[curr->name] = curr.get(); + eventsMap.clear(); + for (auto& curr : events) { + eventsMap[curr->name] = curr.get(); } } diff -Nru binaryen-108/src/wasm/wasm-debug.cpp binaryen-99/src/wasm/wasm-debug.cpp --- binaryen-108/src/wasm/wasm-debug.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-debug.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -29,7 +29,9 @@ #include "wasm-debug.h" #include "wasm.h" -namespace wasm::Debug { +namespace wasm { + +namespace Debug { bool isDWARFSection(Name name) { return name.startsWith(".debug_"); } @@ -84,10 +86,6 @@ info.context->dump(llvm::outs(), options); } -bool shouldPreserveDWARF(PassOptions& options, Module& wasm) { - return options.debugInfo && hasDWARFSections(wasm); -} - // // Big picture: We use a DWARFContext to read data, then DWARFYAML support // code to write it. That is not the main LLVM Dwarf code used for writing @@ -363,18 +361,18 @@ // bloat the common case which is represented in the earlier maps. struct DelimiterInfo { Expression* expr; - size_t id; + BinaryLocations::DelimiterId id; }; std::unordered_map delimiterMap; // Construct the map from the binaryLocations loaded from the wasm. AddrExprMap(const Module& wasm) { for (auto& func : wasm.functions) { - for (auto& [expr, span] : func->expressionLocations) { - add(expr, span); + for (auto pair : func->expressionLocations) { + add(pair.first, pair.second); } - for (auto& [expr, delim] : func->delimiterLocations) { - add(expr, delim); + for (auto pair : func->delimiterLocations) { + add(pair.first, pair.second); } } } @@ -416,7 +414,8 @@ for (Index i = 0; i < delimiter.size(); i++) { if (delimiter[i] != 0) { assert(delimiterMap.count(delimiter[i]) == 0); - delimiterMap[delimiter[i]] = DelimiterInfo{expr, i}; + delimiterMap[delimiter[i]] = + DelimiterInfo{expr, BinaryLocations::DelimiterId(i)}; } } } @@ -627,11 +626,6 @@ // Given an offset in .debug_loc, get the old and new compile unit bases. OldToNew getCompileUnitBasesForLoc(size_t offset) const { - if (locToUnitMap.count(offset) == 0) { - // There is no compile unit for this loc. It doesn't matter what we set - // here. - return OldToNew{0, 0}; - } auto index = locToUnitMap.at(offset); auto iter = compileUnitBases.find(index); if (iter != compileUnitBases.end()) { @@ -757,12 +751,11 @@ // debug_line section. std::vector computedLengths; llvm::DWARFYAML::ComputeDebugLine(data, computedLengths); - BinaryLocation newLocation = 0; + BinaryLocation oldLocation = 0, newLocation = 0; for (size_t i = 0; i < data.DebugLines.size(); i++) { auto& table = data.DebugLines[i]; - auto oldLocation = table.Position; locationUpdater.debugLineMap[oldLocation] = newLocation; - table.Position = newLocation; + oldLocation += table.Length.getLength() + AddressSize; newLocation += computedLengths[i] + AddressSize; table.Length.setLength(computedLengths[i]); } @@ -1099,8 +1092,8 @@ std::cerr << "warning: no DWARF updating support present\n"; } -bool shouldPreserveDWARF(PassOptions& options, Module& wasm) { return false; } - #endif // BUILD_LLVM_DWARF -} // namespace wasm::Debug +} // namespace Debug + +} // namespace wasm diff -Nru binaryen-108/src/wasm/wasm-emscripten.cpp binaryen-99/src/wasm/wasm-emscripten.cpp --- binaryen-108/src/wasm/wasm-emscripten.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-emscripten.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -23,6 +23,7 @@ #include "ir/import-utils.h" #include "ir/literal-utils.h" #include "ir/module-utils.h" +#include "ir/table-utils.h" #include "shared-constants.h" #include "support/debug.h" #include "wasm-builder.h" @@ -33,8 +34,11 @@ namespace wasm { +cashew::IString EM_ASM_PREFIX("emscripten_asm_const"); cashew::IString EM_JS_PREFIX("__em_js__"); +static Name STACK_INIT("stack$init"); + void addExportedFunction(Module& wasm, Function* function) { wasm.addFunction(function); auto export_ = new Export; @@ -55,16 +59,15 @@ Global* getStackPointerGlobal(Module& wasm) { // Assumption: The stack pointer is either imported as __stack_pointer or - // we just assume it's the first non-imported global. + // its the first non-imported and non-exported global. // TODO(sbc): Find a better way to discover the stack pointer. Perhaps the // linker could export it by name? for (auto& g : wasm.globals) { - if (g->imported() && g->base == STACK_POINTER) { - return g.get(); - } - } - for (auto& g : wasm.globals) { - if (!g->imported()) { + if (g->imported()) { + if (g->base == STACK_POINTER) { + return g.get(); + } + } else if (!isExported(wasm, g->name)) { return g.get(); } } @@ -73,18 +76,70 @@ const Address UNKNOWN_OFFSET(uint32_t(-1)); -std::string escape(std::string code) { +std::vector
getSegmentOffsets(Module& wasm) { + std::unordered_map passiveOffsets; + if (wasm.features.hasBulkMemory()) { + // Fetch passive segment offsets out of memory.init instructions + struct OffsetSearcher : PostWalker { + std::unordered_map& offsets; + OffsetSearcher(std::unordered_map& offsets) + : offsets(offsets) {} + void visitMemoryInit(MemoryInit* curr) { + // The desitination of the memory.init is either a constant + // or the result of an addition with __memory_base in the + // case of PIC code. + auto* dest = curr->dest->dynCast(); + if (!dest) { + auto* add = curr->dest->dynCast(); + if (!add) { + return; + } + dest = add->left->dynCast(); + if (!dest) { + return; + } + } + auto it = offsets.find(curr->segment); + if (it != offsets.end()) { + Fatal() << "Cannot get offset of passive segment initialized " + "multiple times"; + } + offsets[curr->segment] = dest->value.geti32(); + } + } searcher(passiveOffsets); + searcher.walkModule(&wasm); + } + std::vector
segmentOffsets; + for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { + auto& segment = wasm.memory.segments[i]; + if (segment.isPassive) { + auto it = passiveOffsets.find(i); + if (it != passiveOffsets.end()) { + segmentOffsets.push_back(it->second); + } else { + // This was a non-constant offset (perhaps TLS) + segmentOffsets.push_back(UNKNOWN_OFFSET); + } + } else if (auto* addrConst = segment.offset->dynCast()) { + auto address = addrConst->value.geti32(); + segmentOffsets.push_back(address); + } else { + // TODO(sbc): Wasm shared libraries have data segments with non-const + // offset. + segmentOffsets.push_back(0); + } + } + return segmentOffsets; +} + +std::string escape(const char* input) { + std::string code = input; // replace newlines quotes with escaped newlines size_t curr = 0; while ((curr = code.find("\\n", curr)) != std::string::npos) { code = code.replace(curr, 2, "\\\\n"); curr += 3; // skip this one } - curr = 0; - while ((curr = code.find("\\t", curr)) != std::string::npos) { - code = code.replace(curr, 2, "\\\\t"); - curr += 3; // skip this one - } // replace double quotes with escaped single quotes curr = 0; while ((curr = code.find('"', curr)) != std::string::npos) { @@ -106,263 +161,281 @@ return code; } -class StringConstantTracker { -public: - StringConstantTracker(Module& wasm) : wasm(wasm) { calcSegmentOffsets(); } - - const char* stringAtAddr(Address address) { - for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { - Memory::Segment& segment = wasm.memory.segments[i]; - Address offset = segmentOffsets[i]; - if (offset != UNKNOWN_OFFSET && address >= offset && - address < offset + segment.data.size()) { - return &segment.data[address - offset]; - } +const char* stringAtAddr(Module& wasm, + std::vector
const& segmentOffsets, + Address address) { + for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { + Memory::Segment& segment = wasm.memory.segments[i]; + Address offset = segmentOffsets[i]; + if (offset != UNKNOWN_OFFSET && address >= offset && + address < offset + segment.data.size()) { + return &segment.data[address - offset]; } + } + return nullptr; +} + +std::string codeForConstAddr(Module& wasm, + std::vector
const& segmentOffsets, + int64_t address) { + const char* str = stringAtAddr(wasm, segmentOffsets, address); + if (!str) { Fatal() << "unable to find data for ASM/EM_JS const at: " << address; - return nullptr; } + return escape(str); +} - std::vector
segmentOffsets; // segment index => address offset +enum class Proxying { + None, + Sync, + Async, +}; -private: - void calcSegmentOffsets() { - std::unordered_map passiveOffsets; - if (wasm.features.hasBulkMemory()) { - // Fetch passive segment offsets out of memory.init instructions - struct OffsetSearcher : PostWalker { - std::unordered_map& offsets; - OffsetSearcher(std::unordered_map& offsets) - : offsets(offsets) {} - void visitMemoryInit(MemoryInit* curr) { - // The desitination of the memory.init is either a constant - // or the result of an addition with __memory_base in the - // case of PIC code. - auto* dest = curr->dest->dynCast(); - if (!dest) { - auto* add = curr->dest->dynCast(); - if (!add) { - return; - } - dest = add->left->dynCast(); - if (!dest) { - return; - } - } - auto it = offsets.find(curr->segment); - if (it != offsets.end()) { - Fatal() << "Cannot get offset of passive segment initialized " - "multiple times"; - } - offsets[curr->segment] = dest->value.getInteger(); - } - } searcher(passiveOffsets); - searcher.walkModule(&wasm); - } - for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { - auto& segment = wasm.memory.segments[i]; - if (segment.isPassive) { - auto it = passiveOffsets.find(i); - if (it != passiveOffsets.end()) { - segmentOffsets.push_back(it->second); - } else { - // This was a non-constant offset (perhaps TLS) - segmentOffsets.push_back(UNKNOWN_OFFSET); - } - } else if (auto* addrConst = segment.offset->dynCast()) { - auto address = addrConst->value.getUnsigned(); - segmentOffsets.push_back(address); - } else { - // TODO(sbc): Wasm shared libraries have data segments with non-const - // offset. - segmentOffsets.push_back(0); - } - } +std::string proxyingSuffix(Proxying proxy) { + switch (proxy) { + case Proxying::None: + return ""; + case Proxying::Sync: + return "sync_on_main_thread_"; + case Proxying::Async: + return "async_on_main_thread_"; } + WASM_UNREACHABLE("invalid prozy type"); +} +struct AsmConstWalker : public LinearExecutionWalker { Module& wasm; -}; + bool minimizeWasmChanges; + std::vector
segmentOffsets; // segment index => address offset + + struct AsmConst { + std::set sigs; + Address id; + std::string code; + Proxying proxy; + }; + + std::vector asmConsts; + std::set> allSigs; + // last sets in the current basic block, per index + std::map sets; + + AsmConstWalker(Module& _wasm, bool minimizeWasmChanges) + : wasm(_wasm), minimizeWasmChanges(minimizeWasmChanges), + segmentOffsets(getSegmentOffsets(wasm)) {} + + void noteNonLinear(Expression* curr); + + void visitLocalSet(LocalSet* curr); + void visitCall(Call* curr); + + void process(); -struct AsmConst { - Address id; - std::string code; +private: + void createAsmConst(uint64_t id, std::string code, Signature sig, Name name); + Signature asmConstSig(Signature baseSig); + Name nameForImportWithSig(Signature sig, Proxying proxy); + void addImports(); + Proxying proxyType(Name name); + + std::vector> queuedImports; }; -struct SegmentRemover : WalkerPass> { - SegmentRemover(Index segment) : segment(segment) {} +void AsmConstWalker::noteNonLinear(Expression* curr) { + // End of this basic block; clear sets. + sets.clear(); +} - bool isFunctionParallel() override { return true; } +void AsmConstWalker::visitLocalSet(LocalSet* curr) { sets[curr->index] = curr; } - Pass* create() override { return new SegmentRemover(segment); } +void AsmConstWalker::visitCall(Call* curr) { + auto* import = wasm.getFunction(curr->target); + // Find calls to emscripten_asm_const* functions whose first argument is + // is always a string constant. + if (!import->imported()) { + return; + } + auto importName = import->base; + if (!importName.hasSubstring(EM_ASM_PREFIX)) { + return; + } + + auto baseSig = wasm.getFunction(curr->target)->sig; + auto sig = asmConstSig(baseSig); + auto* arg = curr->operands[0]; + while (!arg->dynCast()) { + if (auto* get = arg->dynCast()) { + // The argument may be a local.get, in which case, the last set in this + // basic block has the value. + auto* set = sets[get->index]; + if (set) { + assert(set->index == get->index); + arg = set->value; + } else { + Fatal() << "local.get of unknown in arg0 of call to " << importName + << " (used by EM_ASM* macros) in function " + << getFunction()->name + << ".\nThis might be caused by aggressive compiler " + "transformations. Consider using EM_JS instead."; + } + continue; + } - void visitMemoryInit(MemoryInit* curr) { - if (segment == curr->segment) { - Builder builder(*getModule()); - replaceCurrent(builder.blockify(builder.makeDrop(curr->dest), - builder.makeDrop(curr->offset), - builder.makeDrop(curr->size))); + if (auto* setlocal = arg->dynCast()) { + // The argument may be a local.tee, in which case we take first child + // which is the value being copied into the local. + if (setlocal->isTee()) { + arg = setlocal->value; + continue; + } } - } - void visitDataDrop(DataDrop* curr) { - if (segment == curr->segment) { - Builder builder(*getModule()); - replaceCurrent(builder.makeNop()); + if (auto* bin = arg->dynCast()) { + if (bin->op == AddInt32 || bin->op == AddInt64) { + // In the dynamic linking case the address of the string constant + // is the result of adding its offset to __memory_base. + // In this case are only looking for the offset from __memory_base + // the RHS of the addition is just what we want. + arg = bin->right; + continue; + } } - } - Index segment; -}; + if (auto* unary = arg->dynCast()) { + if (unary->op == WrapInt64) { + // This cast may be inserted around the string constant in the + // Memory64Lowering pass. + arg = unary->value; + continue; + } + } -static void removeSegment(Module& wasm, Index segment) { - PassRunner runner(&wasm); - SegmentRemover(segment).run(&runner, &wasm); - // Resize the segment to zero. In theory we should completely remove it - // but that would mean re-numbering the segments that follow which is - // non-trivial. - wasm.memory.segments[segment].data.resize(0); -} - -static Address getExportedAddress(Module& wasm, Export* export_) { - Global* g = wasm.getGlobal(export_->value); - auto* addrConst = g->init->dynCast(); - return addrConst->value.getUnsigned(); -} - -static std::vector findEmAsmConsts(Module& wasm, - bool minimizeWasmChanges) { - // Newer version of emscripten/llvm export these symbols so we can use them to - // find all the EM_ASM constants. Sadly __start_em_asm and __stop_em_asm - // don't alwasy mark the start and end of segment because in dynamic linking - // we merge all data segments into one. - Export* start = wasm.getExportOrNull("__start_em_asm"); - Export* end = wasm.getExportOrNull("__stop_em_asm"); - if (!start && !end) { - BYN_TRACE("findEmAsmConsts: no start/stop symbols\n"); - return {}; + Fatal() << "Unexpected arg0 type (" << getExpressionName(arg) + << ") in call to: " << importName; } - if (!start || !end) { - Fatal() << "Found only one of __start_em_asm and __stop_em_asm"; + auto* value = arg->cast(); + int64_t address = value->value.getInteger(); + auto code = codeForConstAddr(wasm, segmentOffsets, address); + createAsmConst(address, code, sig, importName); +} + +Proxying AsmConstWalker::proxyType(Name name) { + if (name.hasSubstring("_sync_on_main_thread")) { + return Proxying::Sync; + } else if (name.hasSubstring("_async_on_main_thread")) { + return Proxying::Async; } + return Proxying::None; +} - std::vector asmConsts; - StringConstantTracker stringTracker(wasm); - Address startAddress = getExportedAddress(wasm, start); - Address endAddress = getExportedAddress(wasm, end); - for (Index i = 0; i < wasm.memory.segments.size(); i++) { - Address segmentStart = stringTracker.segmentOffsets[i]; - size_t segmentSize = wasm.memory.segments[i].data.size(); - if (segmentStart <= startAddress && - segmentStart + segmentSize >= endAddress) { - Address address = startAddress; - while (address < endAddress) { - auto code = stringTracker.stringAtAddr(address); - asmConsts.push_back({address, code}); - address.addr += strlen(code) + 1; - } - - if (segmentStart == startAddress && - segmentStart + segmentSize == endAddress) { - removeSegment(wasm, i); - } else { - // If we can't remove the whole segment then just set the string - // data to zero. - size_t segmentOffset = startAddress - segmentStart; - char* startElem = &wasm.memory.segments[i].data[segmentOffset]; - memset(startElem, 0, endAddress - startAddress); - } - break; - } +void AsmConstWalker::process() { + // Find and queue necessary imports + walkModule(&wasm); + // Add them after the walk, to avoid iterator invalidation on + // the list of functions. + addImports(); +} + +void AsmConstWalker::createAsmConst(uint64_t id, + std::string code, + Signature sig, + Name name) { + AsmConst asmConst; + asmConst.id = id; + asmConst.code = code; + asmConst.sigs.insert(sig); + asmConst.proxy = proxyType(name); + asmConsts.push_back(asmConst); +} + +Signature AsmConstWalker::asmConstSig(Signature baseSig) { + assert(baseSig.params.size() >= 1); + // Omit the signature of the "code" parameter, taken as a string, as the + // first argument + return Signature( + Type(std::vector(baseSig.params.begin() + 1, baseSig.params.end())), + baseSig.results); +} + +void AsmConstWalker::addImports() { + for (auto& import : queuedImports) { + wasm.addFunction(import.release()); } +} - assert(asmConsts.size()); - wasm.removeExport("__start_em_asm"); - wasm.removeExport("__stop_em_asm"); - return asmConsts; +static AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm, + bool minimizeWasmChanges) { + AsmConstWalker walker(wasm, minimizeWasmChanges); + walker.process(); + return walker; } struct EmJsWalker : public PostWalker { Module& wasm; - StringConstantTracker stringTracker; - std::vector toRemove; + std::vector
segmentOffsets; // segment index => address offset std::map codeByName; - std::map codeAddresses; // map from address to string len - EmJsWalker(Module& _wasm) : wasm(_wasm), stringTracker(_wasm) {} + EmJsWalker(Module& _wasm) + : wasm(_wasm), segmentOffsets(getSegmentOffsets(wasm)) {} void visitExport(Export* curr) { - if (!curr->name.startsWith(EM_JS_PREFIX.str)) { + if (curr->kind != ExternalKind::Function) { return; } - - Address address; - if (curr->kind == ExternalKind::Global) { - auto* global = wasm.getGlobal(curr->value); - Const* const_ = global->init->cast(); - address = const_->value.getUnsigned(); - } else if (curr->kind == ExternalKind::Function) { - auto* func = wasm.getFunction(curr->value); - // An EM_JS has a single const in the body. Typically it is just returned, - // but in unoptimized code it might be stored to a local and loaded from - // there, and in relocatable code it might get added to __memory_base etc. - FindAll consts(func->body); - if (consts.list.size() != 1) { - Fatal() << "Unexpected generated __em_js__ function body: " - << curr->name; - } - auto* addrConst = consts.list[0]; - address = addrConst->value.getUnsigned(); - } else { + if (!curr->name.startsWith(EM_JS_PREFIX.str)) { return; } - - toRemove.push_back(*curr); - auto code = stringTracker.stringAtAddr(address); + auto* func = wasm.getFunction(curr->value); auto funcName = std::string(curr->name.stripPrefix(EM_JS_PREFIX.str)); + // An EM_JS has a single const in the body. Typically it is just returned, + // but in unoptimized code it might be stored to a local and loaded from + // there, and in relocatable code it might get added to __memory_base etc. + FindAll consts(func->body); + if (consts.list.size() != 1) { + Fatal() << "Unexpected generated __em_js__ function body: " << curr->name; + } + auto* addrConst = consts.list[0]; + int64_t address = addrConst->value.getInteger(); + auto code = codeForConstAddr(wasm, segmentOffsets, address); codeByName[funcName] = code; - codeAddresses[address] = strlen(code) + 1; } }; -EmJsWalker findEmJsFuncsAndReturnWalker(Module& wasm) { +EmJsWalker fixEmJsFuncsAndReturnWalker(Module& wasm) { EmJsWalker walker(wasm); walker.walkModule(&wasm); - for (const Export& exp : walker.toRemove) { - if (exp.kind == ExternalKind::Function) { - wasm.removeFunction(exp.value); - } else { - wasm.removeGlobal(exp.value); + std::vector toRemove; + for (auto& func : wasm.functions) { + if (func->name.startsWith(EM_JS_PREFIX.str)) { + toRemove.push_back(func->name); } - wasm.removeExport(exp.name); } + for (auto funcName : toRemove) { + wasm.removeFunction(funcName); + wasm.removeExport(funcName); + } + return walker; +} - // With newer versions of emscripten/llvm we pack all EM_JS strings into - // single segment. - // We can detect this by checking for segments that contain only JS strings. - // When we find such segements we remove them from the final binary. - for (Index i = 0; i < wasm.memory.segments.size(); i++) { - Address start = walker.stringTracker.segmentOffsets[i]; - Address cur = start; - - while (cur < start + wasm.memory.segments[i].data.size()) { - if (walker.codeAddresses.count(cur) == 0) { - break; - } - cur.addr += walker.codeAddresses[cur]; - } - - if (cur == start + wasm.memory.segments[i].data.size()) { - // Entire segment is contains JS strings. Remove it. - removeSegment(wasm, i); +void printSignatures(std::ostream& o, const std::set& c) { + o << "["; + bool first = true; + for (auto& sig : c) { + if (first) { + first = false; + } else { + o << ","; } + o << '"' << getSig(sig.results, sig.params) << '"'; } - return walker; + o << "]"; } -std::string EmscriptenGlueGenerator::generateEmscriptenMetadata() { +std::string +EmscriptenGlueGenerator::generateEmscriptenMetadata(Name initializer) { bool commaFirst; auto nextElement = [&commaFirst]() { if (commaFirst) { @@ -376,30 +449,45 @@ std::stringstream meta; meta << "{\n"; - std::vector asmConsts = findEmAsmConsts(wasm, minimizeWasmChanges); + AsmConstWalker emAsmWalker = + fixEmAsmConstsAndReturnWalker(wasm, minimizeWasmChanges); // print commaFirst = true; - if (!asmConsts.empty()) { + if (!emAsmWalker.asmConsts.empty()) { meta << " \"asmConsts\": {"; - for (auto& asmConst : asmConsts) { + for (auto& asmConst : emAsmWalker.asmConsts) { meta << nextElement(); - meta << '"' << asmConst.id << "\": \"" << escape(asmConst.code) << "\""; + meta << '"' << asmConst.id << "\": [\"" << asmConst.code << "\", "; + printSignatures(meta, asmConst.sigs); + meta << ", [\"" << proxyingSuffix(asmConst.proxy) << "\"]"; + + meta << "]"; } meta << "\n },\n"; } - EmJsWalker emJsWalker = findEmJsFuncsAndReturnWalker(wasm); + EmJsWalker emJsWalker = fixEmJsFuncsAndReturnWalker(wasm); if (!emJsWalker.codeByName.empty()) { meta << " \"emJsFuncs\": {"; commaFirst = true; - for (auto& [name, code] : emJsWalker.codeByName) { + for (auto& pair : emJsWalker.codeByName) { + auto& name = pair.first; + auto& code = pair.second; meta << nextElement(); - meta << '"' << name << "\": \"" << escape(code) << '"'; + meta << '"' << name << "\": \"" << code << '"'; } meta << "\n },\n"; } + meta << " \"tableSize\": " << wasm.table.initial.addr << ",\n"; + + if (initializer.is()) { + meta << " \"initializers\": ["; + meta << "\n \"" << initializer.c_str() << "\""; + meta << "\n ],\n"; + } + // Avoid adding duplicate imports to `declares' or `invokeFuncs`. Even // though we might import the same function multiple times (i.e. with // different sigs) we only need to list is in the metadata once. @@ -421,10 +509,12 @@ }); meta << "\n ],\n"; - meta << " \"globalImports\": ["; + meta << " \"externs\": ["; commaFirst = true; ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) { - meta << nextElement() << '"' << import->base.str << '"'; + if (!(import->module == ENV && import->name == STACK_INIT)) { + meta << nextElement() << "\"_" << import->base.str << '"'; + } }); meta << "\n ],\n"; @@ -443,9 +533,9 @@ for (const auto& ex : wasm.exports) { if (ex->kind == ExternalKind::Global) { const Global* g = wasm.getGlobal(ex->value); - assert(g->type == Type::i32 || g->type == Type::i64); + assert(g->type == Type::i32); Const* init = g->init->cast(); - uint64_t addr = init->value.getInteger(); + uint32_t addr = init->value.geti32(); meta << nextElement() << '"' << ex->name.str << "\" : \"" << addr << '"'; } @@ -512,7 +602,7 @@ if (!seg.offset->is()) { Fatal() << "separating relocatable segments not implemented"; } - size_t offset = seg.offset->cast()->value.getInteger(); + size_t offset = seg.offset->cast()->value.geti32(); offset -= base; size_t fill = offset - lastEnd; if (fill > 0) { diff -Nru binaryen-108/src/wasm/wasm-interpreter.cpp binaryen-99/src/wasm/wasm-interpreter.cpp --- binaryen-108/src/wasm/wasm-interpreter.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-interpreter.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -19,8 +19,4 @@ } #endif // WASM_INTERPRETER_DEBUG -std::ostream& operator<<(std::ostream& o, const WasmException& exn) { - return o << exn.tag << " " << exn.values; -} - } // namespace wasm diff -Nru binaryen-108/src/wasm/wasm-io.cpp binaryen-99/src/wasm/wasm-io.cpp --- binaryen-108/src/wasm/wasm-io.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-io.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -49,12 +49,8 @@ Module& wasm, std::string sourceMapFilename) { std::unique_ptr sourceMapStream; - // Assume that the wasm has had its initial features applied, and use those - // while parsing. - WasmBinaryBuilder parser(wasm, wasm.features, input); - parser.setDebugInfo(debugInfo); + WasmBinaryBuilder parser(wasm, input); parser.setDWARF(DWARF); - parser.setSkipFunctionBodies(skipFunctionBodies); if (sourceMapFilename.size()) { sourceMapStream = make_unique(); sourceMapStream->open(sourceMapFilename); @@ -88,8 +84,8 @@ void ModuleReader::read(std::string filename, Module& wasm, std::string sourceMapFilename) { - // empty filename or "-" means read from stdin - if (!filename.size() || filename == "-") { + // empty filename means read from stdin + if (!filename.size()) { readStdin(wasm, sourceMapFilename); return; } @@ -139,9 +135,6 @@ WasmBinaryWriter writer(&wasm, buffer); // if debug info is used, then we want to emit the names section writer.setNamesSection(debugInfo); - if (emitModuleName) { - writer.setEmitModuleName(true); - } std::unique_ptr sourceMapStream; if (sourceMapFilename.size()) { sourceMapStream = make_unique(); diff -Nru binaryen-108/src/wasm/wasm-s-parser.cpp binaryen-99/src/wasm/wasm-s-parser.cpp --- binaryen-108/src/wasm/wasm-s-parser.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-s-parser.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -21,7 +21,6 @@ #include #include "ir/branch-utils.h" -#include "ir/table-utils.h" #include "shared-constants.h" #include "support/string.h" #include "wasm-binary.h" @@ -51,10 +50,8 @@ namespace wasm { -static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), - FUNC_SUBTYPE("func_subtype"), STRUCT_SUBTYPE("struct_subtype"), - ARRAY_SUBTYPE("array_subtype"), EXTENDS("extends"), REC("rec"), I8("i8"), - I16("i16"), RTT("rtt"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); +static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), I8("i8"), + I16("i16"), RTT("rtt"); static Address getAddress(const Element* s) { return atoll(s->c_str()); } @@ -128,9 +125,6 @@ } o << " )"; } else { - if (e.dollared()) { - o << '$'; - } o << e.str_.str; } return o; @@ -342,19 +336,8 @@ Index i = 1; if (module[i]->dollared()) { wasm.name = module[i]->str(); - if (module.size() == 2) { - return; - } i++; } - - // spec tests have a `binary` keyword after the optional module name. Skip it - Name BINARY("binary"); - if (module[i]->isStr() && module[i]->str() == BINARY && - !module[i]->quoted()) { - i++; - } - if (i < module.size() && module[i]->isStr()) { // these s-expressions contain a binary module, actually std::vector data; @@ -364,14 +347,10 @@ stringToBinary(str, size, data); } } - // TODO: support applying features here - WasmBinaryBuilder binaryBuilder(wasm, FeatureSet::MVP, data); + WasmBinaryBuilder binaryBuilder(wasm, data); binaryBuilder.read(); return; } - - preParseHeapTypes(module); - Index implementedFunctions = 0; functionCounter = 0; for (unsigned j = i; j < module.size(); j++) { @@ -414,8 +393,8 @@ parseTable(curr, true /* preParseImport */); } else if (id == MEMORY) { parseMemory(curr, true /* preParseImport */); - } else if (id == TAG) { - parseTag(curr, true /* preParseImport */); + } else if (id == EVENT) { + parseEvent(curr, true /* preParseImport */); } else { throw ParseException( "fancy import we don't support yet", curr.line, curr.col); @@ -458,11 +437,8 @@ if (id == TYPE) { return; // already done } - if (id == REC) { - return; // already done - } - if (id == TAG) { - return parseTag(curr); + if (id == EVENT) { + return parseEvent(curr); } std::cerr << "bad module element " << id.str << '\n'; throw ParseException("unknown module element", curr.line, curr.col); @@ -482,19 +458,6 @@ } } -Name SExpressionWasmBuilder::getTableName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = atoi(s.str().c_str()); - if (offset >= tableNames.size()) { - throw ParseException("unknown table in getTableName", s.line, s.col); - } - return tableNames[offset]; - } -} - Name SExpressionWasmBuilder::getGlobalName(Element& s) { if (s.dollared()) { return s.str(); @@ -508,16 +471,16 @@ } } -Name SExpressionWasmBuilder::getTagName(Element& s) { +Name SExpressionWasmBuilder::getEventName(Element& s) { if (s.dollared()) { return s.str(); } else { // index size_t offset = atoi(s.str().c_str()); - if (offset >= tagNames.size()) { - throw ParseException("unknown tag in getTagName", s.line, s.col); + if (offset >= eventNames.size()) { + throw ParseException("unknown event in getEventName", s.line, s.col); } - return tagNames[offset]; + return eventNames[offset]; } } @@ -586,7 +549,7 @@ // Parses an element that references an entry in the type section. The element // should be in the form of (type name) or (type index). // (e.g. (type $a), (type 0)) -HeapType SExpressionWasmBuilder::parseTypeRef(Element& s) { +Signature SExpressionWasmBuilder::parseTypeRef(Element& s) { assert(elementStartsWith(s, TYPE)); if (s.size() != 2) { throw ParseException("invalid type reference", s.line, s.col); @@ -595,10 +558,10 @@ if (!heapType.isSignature()) { throw ParseException("expected signature type", s.line, s.col); } - return heapType; + return heapType.getSignature(); } -// Parses typeuse, a reference to a type definition. It is in the form of either +// Prases typeuse, a reference to a type definition. It is in the form of either // (type index) or (type name), possibly augmented by inlined (param) and // (result) nodes. (type) node can be omitted as well. Outputs are returned by // parameter references. @@ -608,7 +571,7 @@ size_t SExpressionWasmBuilder::parseTypeUse(Element& s, size_t startPos, - HeapType& functionType, + Signature& functionSignature, std::vector& namedParams) { std::vector params, results; size_t i = startPos; @@ -616,7 +579,7 @@ bool typeExists = false, paramsOrResultsExist = false; if (i < s.size() && elementStartsWith(*s[i], TYPE)) { typeExists = true; - functionType = parseTypeRef(*s[i++]); + functionSignature = parseTypeRef(*s[i++]); } size_t paramPos = i; @@ -646,10 +609,10 @@ } if (!typeExists) { - functionType = inlineSig; + functionSignature = inlineSig; } else if (paramsOrResultsExist) { // verify that (type) and (params)/(result) match - if (inlineSig != functionType.getSignature()) { + if (inlineSig != functionSignature) { throw ParseException("type and param/result don't match", s[paramPos]->line, s[paramPos]->col); @@ -657,16 +620,15 @@ } // Add implicitly defined type to global list so it has an index - if (std::find(types.begin(), types.end(), functionType) == types.end()) { - types.push_back(functionType); + auto heapType = HeapType(functionSignature); + if (std::find(types.begin(), types.end(), heapType) == types.end()) { + types.push_back(heapType); } // If only (type) is specified, populate `namedParams` if (!paramsOrResultsExist) { size_t index = 0; - assert(functionType.isSignature()); - Signature sig = functionType.getSignature(); - for (const auto& param : sig.params) { + for (const auto& param : functionSignature.params) { namedParams.emplace_back(Name::fromInt(index++), param); } } @@ -677,296 +639,16 @@ // Parses a typeuse. Use this when only FunctionType* is needed. size_t SExpressionWasmBuilder::parseTypeUse(Element& s, size_t startPos, - HeapType& functionType) { + Signature& functionSignature) { std::vector params; - return parseTypeUse(s, startPos, functionType, params); -} - -void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { - // Iterate through each individual type definition, calling `f` with the - // definition and its recursion group number. - auto forEachType = [&](auto f) { - size_t groupNumber = 0; - for (auto* elemPtr : module) { - auto& elem = *elemPtr; - if (elementStartsWith(elem, TYPE)) { - f(elem, groupNumber++); - } else if (elementStartsWith(elem, REC)) { - for (auto* innerPtr : elem) { - auto& inner = *innerPtr; - if (elementStartsWith(inner, TYPE)) { - f(inner, groupNumber); - } - } - ++groupNumber; - } - } - }; - - // Map type names to indices - size_t numTypes = 0; - forEachType([&](Element& elem, size_t) { - if (elem[1]->dollared()) { - std::string name = elem[1]->c_str(); - if (!typeIndices.insert({name, numTypes}).second) { - throw ParseException("duplicate function type", elem.line, elem.col); - } - } - ++numTypes; - }); - - TypeBuilder builder(numTypes); - - // Create recursion groups - size_t currGroup = 0, groupStart = 0, groupLength = 0; - auto finishGroup = [&]() { - builder.createRecGroup(groupStart, groupLength); - groupStart = groupStart + groupLength; - groupLength = 0; - }; - forEachType([&](Element&, size_t group) { - if (group != currGroup) { - finishGroup(); - currGroup = group; - } - ++groupLength; - }); - finishGroup(); - - auto parseRefType = [&](Element& elem) -> Type { - // '(' 'ref' 'null'? ht ')' - auto nullable = - elem[1]->isStr() && *elem[1] == NULL_ ? Nullable : NonNullable; - auto& referent = nullable ? *elem[2] : *elem[1]; - const char* name = referent.c_str(); - if (referent.dollared()) { - return builder.getTempRefType(builder[typeIndices[name]], nullable); - } else if (String::isNumber(name)) { - size_t index = atoi(name); - if (index >= numTypes) { - throw ParseException("invalid type index", elem.line, elem.col); - } - return builder.getTempRefType(builder[index], nullable); - } else { - return Type(stringToHeapType(name), nullable); - } - }; - - auto parseRttType = [&](Element& elem) -> Type { - // '(' 'rtt' depth? typeidx ')' - uint32_t depth; - Element* idx; - switch (elem.size()) { - default: - throw ParseException( - "unexpected number of rtt parameters", elem.line, elem.col); - case 2: - depth = Rtt::NoDepth; - idx = elem[1]; - break; - case 3: - if (!String::isNumber(elem[1]->c_str())) { - throw ParseException( - "invalid rtt depth", elem[1]->line, elem[1]->col); - } - depth = atoi(elem[1]->c_str()); - idx = elem[2]; - break; - } - if (idx->dollared()) { - HeapType type = builder[typeIndices[idx->c_str()]]; - return builder.getTempRttType(Rtt(depth, type)); - } else if (String::isNumber(idx->c_str())) { - size_t index = atoi(idx->c_str()); - if (index < numTypes) { - return builder.getTempRttType(Rtt(depth, builder[index])); - } - } - throw ParseException("invalid type index", idx->line, idx->col); - }; - - auto parseValType = [&](Element& elem) { - if (elem.isStr()) { - return stringToType(elem.c_str()); - } else if (*elem[0] == REF) { - return parseRefType(elem); - } else if (*elem[0] == RTT) { - return parseRttType(elem); - } else { - throw ParseException("unknown valtype kind", elem[0]->line, elem[0]->col); - } - }; - - auto parseParams = [&](Element& elem) { - auto it = ++elem.begin(); - if (it != elem.end() && (*it)->dollared()) { - ++it; - } - std::vector params; - for (auto end = elem.end(); it != end; ++it) { - params.push_back(parseValType(**it)); - } - return params; - }; - - auto parseResults = [&](Element& elem) { - std::vector results; - for (auto it = ++elem.begin(); it != elem.end(); ++it) { - results.push_back(parseValType(**it)); - } - return results; - }; - - auto parseSignatureDef = [&](Element& elem, bool nominal) { - // '(' 'func' vec(param) vec(result) ')' - // param ::= '(' 'param' id? valtype ')' - // result ::= '(' 'result' valtype ')' - std::vector params, results; - auto end = elem.end() - (nominal ? 1 : 0); - for (auto it = ++elem.begin(); it != end; ++it) { - Element& curr = **it; - if (elementStartsWith(curr, PARAM)) { - auto newParams = parseParams(curr); - params.insert(params.end(), newParams.begin(), newParams.end()); - } else if (elementStartsWith(curr, RESULT)) { - auto newResults = parseResults(curr); - results.insert(results.end(), newResults.begin(), newResults.end()); - } - } - return Signature(builder.getTempTupleType(params), - builder.getTempTupleType(results)); - }; - - // Parses a field, and notes the name if one is found. - auto parseField = [&](Element* elem, Name& name) { - Mutability mutable_ = Immutable; - // elem is a list, containing either - // TYPE - // or - // (field TYPE) - // or - // (field $name TYPE) - if (elementStartsWith(elem, FIELD)) { - if (elem->size() == 3) { - name = (*elem)[1]->str(); - } - elem = (*elem)[elem->size() - 1]; - } - // The element may also be (mut (..)). - if (elementStartsWith(elem, MUT)) { - mutable_ = Mutable; - elem = (*elem)[1]; - } - if (elem->isStr()) { - // elem is a simple string name like "i32". It can be a normal wasm - // type, or one of the special types only available in fields. - if (*elem == I8) { - return Field(Field::i8, mutable_); - } else if (*elem == I16) { - return Field(Field::i16, mutable_); - } - } - // Otherwise it's an arbitrary type. - return Field(parseValType(*elem), mutable_); - }; - - auto parseStructDef = [&](Element& elem, size_t typeIndex, bool nominal) { - FieldList fields; - Index end = elem.size() - (nominal ? 1 : 0); - for (Index i = 1; i < end; i++) { - Name name; - fields.emplace_back(parseField(elem[i], name)); - if (name.is()) { - // Only add the name to the map if it exists. - fieldNames[typeIndex][i - 1] = name; - } - } - return Struct(fields); - }; - - auto parseArrayDef = [&](Element& elem) { - Name unused; - return Array(parseField(elem[1], unused)); - }; - - size_t index = 0; - forEachType([&](Element& elem, size_t) { - Element& def = elem[1]->dollared() ? *elem[2] : *elem[1]; - Element& kind = *def[0]; - bool hasSupertype = - kind == FUNC_SUBTYPE || kind == STRUCT_SUBTYPE || kind == ARRAY_SUBTYPE; - if (kind == FUNC || kind == FUNC_SUBTYPE) { - builder[index] = parseSignatureDef(def, hasSupertype); - } else if (kind == STRUCT || kind == STRUCT_SUBTYPE) { - builder[index] = parseStructDef(def, index, hasSupertype); - } else if (kind == ARRAY || kind == ARRAY_SUBTYPE) { - builder[index] = parseArrayDef(def); - } else { - throw ParseException("unknown heaptype kind", kind.line, kind.col); - } - Element* super = nullptr; - if (hasSupertype) { - super = def[def.size() - 1]; - if (super->dollared()) { - // OK - } else if (kind == FUNC_SUBTYPE && super->str() == FUNC) { - // OK; no supertype - super = nullptr; - } else if ((kind == STRUCT_SUBTYPE || kind == ARRAY_SUBTYPE) && - super->str() == DATA) { - // OK; no supertype - super = nullptr; - } else { - throw ParseException("unknown supertype", super->line, super->col); - } - } else if (elementStartsWith(elem[elem.size() - 1], EXTENDS)) { - // '(' 'extends' $supertype ')' - Element& extends = *elem[elem.size() - 1]; - super = extends[1]; - } - if (super) { - auto it = typeIndices.find(super->c_str()); - if (it == typeIndices.end()) { - throw ParseException("unknown supertype", super->line, super->col); - } - builder[index].subTypeOf(builder[it->second]); - } - ++index; - }); - - auto result = builder.build(); - if (auto* err = result.getError()) { - // Find the name to provide a better error message. - std::stringstream msg; - msg << "Invalid type: " << err->reason; - for (auto& [name, index] : typeIndices) { - if (index == err->index) { - Fatal() << msg.str() << " at type $" << name; - } - } - // No name, just report the index. - Fatal() << msg.str() << " at index " << err->index; - } - types = *result; - - for (auto& [name, index] : typeIndices) { - auto type = types[index]; - // A type may appear in the type section more than once, but we canonicalize - // types internally, so there will be a single name chosen for that type. Do - // so determistically. - if (wasm.typeNames.count(type) && wasm.typeNames[type].name.str < name) { - continue; - } - auto& currTypeNames = wasm.typeNames[type]; - currTypeNames.name = name; - if (type.isStruct()) { - currTypeNames.fieldNames = fieldNames[index]; - } - } + return parseTypeUse(s, startPos, functionSignature, params); } void SExpressionWasmBuilder::preParseFunctionType(Element& s) { IString id = s[0]->str(); + if (id == TYPE) { + return parseType(s); + } if (id != FUNC) { return; } @@ -979,7 +661,9 @@ } functionNames.push_back(name); functionCounter++; - parseTypeUse(s, i, functionTypes[name]); + Signature sig; + parseTypeUse(s, i, sig); + functionSignatures[name] = sig; } size_t SExpressionWasmBuilder::parseFunctionNames(Element& s, @@ -1053,9 +737,9 @@ } // parse typeuse: type/param/result - HeapType type; + Signature sig; std::vector params; - i = parseTypeUse(s, i, type, params); + i = parseTypeUse(s, i, sig, params); // when (import) is inside a (func) element, this is not a function definition // but an import. @@ -1070,12 +754,12 @@ im->setName(name, hasExplicitName); im->module = importModule; im->base = importBase; - im->type = type; - functionTypes[name] = type; + im->sig = sig; + functionSignatures[name] = sig; if (wasm.getFunctionOrNull(im->name)) { throw ParseException("duplicate import", s.line, s.col); } - wasm.addFunction(std::move(im)); + wasm.addFunction(im.release()); if (currFunction) { throw ParseException("import module inside function dec", s.line, s.col); } @@ -1097,8 +781,8 @@ } // make a new function - currFunction = std::unique_ptr( - Builder(wasm).makeFunction(name, std::move(params), type, std::move(vars))); + currFunction = std::unique_ptr(Builder(wasm).makeFunction( + name, std::move(params), sig.results, std::move(vars))); currFunction->profile = profile; // parse body @@ -1125,7 +809,7 @@ autoBlock->name = FAKE_RETURN; } if (autoBlock) { - autoBlock->finalize(type.getSignature().results); + autoBlock->finalize(sig.results); } if (!currFunction->body) { currFunction->body = allocator.alloc(); @@ -1171,18 +855,21 @@ if (strncmp(str, "funcref", 7) == 0 && (prefix || str[7] == 0)) { return Type::funcref; } - if ((strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) || - (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0))) { + if (strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) { + return Type::externref; + } + if (strncmp(str, "exnref", 6) == 0 && (prefix || str[6] == 0)) { + return Type::exnref; + } + if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) { return Type::anyref; } if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) { return Type::eqref; } if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) { - return Type::i31ref; - } - if (strncmp(str, "dataref", 7) == 0 && (prefix || str[7] == 0)) { - return Type::dataref; + // FIXME: for now, force all inputs to be nullable + return Type(HeapType::BasicHeapType::i31, Nullable); } if (allowError) { return Type::none; @@ -1192,24 +879,23 @@ HeapType SExpressionWasmBuilder::stringToHeapType(const char* str, bool prefix) { - if (str[0] == 'f') { - if (str[1] == 'u' && str[2] == 'n' && str[3] == 'c' && - (prefix || str[4] == 0)) { - return HeapType::func; + if (str[0] == 'a') { + if (str[1] == 'n' && str[2] == 'y' && (prefix || str[3] == 0)) { + return HeapType::any; } } if (str[0] == 'e') { if (str[1] == 'q' && (prefix || str[2] == 0)) { return HeapType::eq; } - if (str[1] == 'x' && str[2] == 't' && str[3] == 'e' && str[4] == 'r' && - str[5] == 'n' && (prefix || str[6] == 0)) { - return HeapType::any; - } - } - if (str[0] == 'a') { - if (str[1] == 'n' && str[2] == 'y' && (prefix || str[3] == 0)) { - return HeapType::any; + if (str[1] == 'x') { + if (str[2] == 'n' && (prefix || str[3] == 0)) { + return HeapType::exn; + } + if (str[2] == 't' && str[3] == 'e' && str[4] == 'r' && str[5] == 'n' && + (prefix || str[6] == 0)) { + return HeapType::ext; + } } } if (str[0] == 'i') { @@ -1217,10 +903,10 @@ return HeapType::i31; } } - if (str[0] == 'd') { - if (str[1] == 'a' && str[2] == 't' && str[3] == 'a' && + if (str[0] == 'f') { + if (str[1] == 'u' && str[2] == 'n' && str[3] == 'c' && (prefix || str[4] == 0)) { - return HeapType::data; + return HeapType::func; } } throw ParseException(std::string("invalid wasm heap type: ") + str); @@ -1247,7 +933,8 @@ throw ParseException( std::string("invalid reference type qualifier"), s.line, s.col); } - Nullability nullable = NonNullable; + // FIXME: for now, force all inputs to be nullable + Nullability nullable = Nullable; size_t i = 1; if (size == 3) { nullable = Nullable; @@ -1297,15 +984,6 @@ return Type::none; } -HeapType SExpressionWasmBuilder::getFunctionType(Name name, Element& s) { - auto iter = functionTypes.find(name); - if (iter == functionTypes.end()) { - throw ParseException( - "invalid call target: " + std::string(name.str), s.line, s.col); - } - return iter->second; -} - Function::DebugLocation SExpressionWasmBuilder::getDebugLocation(const SourceLocation& loc) { IString file = loc.filename; @@ -1551,210 +1229,6 @@ return ret; } -static Expression* -parseConst(cashew::IString s, Type type, MixedArena& allocator) { - const char* str = s.str; - auto ret = allocator.alloc(); - ret->type = type; - if (type.isFloat()) { - if (s == _INFINITY) { - switch (type.getBasic()) { - case Type::f32: - ret->value = Literal(std::numeric_limits::infinity()); - break; - case Type::f64: - ret->value = Literal(std::numeric_limits::infinity()); - break; - default: - return nullptr; - } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; - return ret; - } - if (s == NEG_INFINITY) { - switch (type.getBasic()) { - case Type::f32: - ret->value = Literal(-std::numeric_limits::infinity()); - break; - case Type::f64: - ret->value = Literal(-std::numeric_limits::infinity()); - break; - default: - return nullptr; - } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; - return ret; - } - if (s == _NAN) { - switch (type.getBasic()) { - case Type::f32: - ret->value = Literal(float(std::nan(""))); - break; - case Type::f64: - ret->value = Literal(double(std::nan(""))); - break; - default: - return nullptr; - } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; - return ret; - } - bool negative = str[0] == '-'; - const char* positive = negative ? str + 1 : str; - if (!negative) { - if (positive[0] == '+') { - positive++; - } - } - if (positive[0] == 'n' && positive[1] == 'a' && positive[2] == 'n') { - const char* modifier = positive[3] == ':' ? positive + 4 : nullptr; - if (!(modifier ? positive[4] == '0' && positive[5] == 'x' : 1)) { - throw ParseException("bad nan input"); - } - switch (type.getBasic()) { - case Type::f32: { - uint32_t pattern; - if (modifier) { - std::istringstream istr(modifier); - istr >> std::hex >> pattern; - if (istr.fail()) { - throw ParseException("invalid f32 format"); - } - pattern |= 0x7f800000U; - } else { - pattern = 0x7fc00000U; - } - if (negative) { - pattern |= 0x80000000U; - } - if (!std::isnan(bit_cast(pattern))) { - pattern |= 1U; - } - ret->value = Literal(pattern).castToF32(); - break; - } - case Type::f64: { - uint64_t pattern; - if (modifier) { - std::istringstream istr(modifier); - istr >> std::hex >> pattern; - if (istr.fail()) { - throw ParseException("invalid f64 format"); - } - pattern |= 0x7ff0000000000000ULL; - } else { - pattern = 0x7ff8000000000000UL; - } - if (negative) { - pattern |= 0x8000000000000000ULL; - } - if (!std::isnan(bit_cast(pattern))) { - pattern |= 1ULL; - } - ret->value = Literal(pattern).castToF64(); - break; - } - default: - return nullptr; - } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; - return ret; - } - if (s == NEG_NAN) { - switch (type.getBasic()) { - case Type::f32: - ret->value = Literal(float(-std::nan(""))); - break; - case Type::f64: - ret->value = Literal(double(-std::nan(""))); - break; - default: - return nullptr; - } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; - return ret; - } - } - switch (type.getBasic()) { - case Type::i32: { - if ((str[0] == '0' && str[1] == 'x') || - (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { - bool negative = str[0] == '-'; - if (negative) { - str++; - } - std::istringstream istr(str); - uint32_t temp; - istr >> std::hex >> temp; - if (istr.fail()) { - throw ParseException("invalid i32 format"); - } - ret->value = Literal(negative ? -temp : temp); - } else { - std::istringstream istr(str[0] == '-' ? str + 1 : str); - uint32_t temp; - istr >> temp; - if (istr.fail()) { - throw ParseException("invalid i32 format"); - } - ret->value = Literal(str[0] == '-' ? -temp : temp); - } - break; - } - case Type::i64: { - if ((str[0] == '0' && str[1] == 'x') || - (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { - bool negative = str[0] == '-'; - if (negative) { - str++; - } - std::istringstream istr(str); - uint64_t temp; - istr >> std::hex >> temp; - if (istr.fail()) { - throw ParseException("invalid i64 format"); - } - ret->value = Literal(negative ? -temp : temp); - } else { - std::istringstream istr(str[0] == '-' ? str + 1 : str); - uint64_t temp; - istr >> temp; - if (istr.fail()) { - throw ParseException("invalid i64 format"); - } - ret->value = Literal(str[0] == '-' ? -temp : temp); - } - break; - } - case Type::f32: { - char* end; - ret->value = Literal(strtof(str, &end)); - break; - } - case Type::f64: { - char* end; - ret->value = Literal(strtod(str, &end)); - break; - } - case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: - WASM_UNREACHABLE("unexpected const type"); - case Type::none: - case Type::unreachable: { - return nullptr; - } - } - if (ret->value.type != type) { - throw ParseException("parsed type does not match expected type"); - } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; - return ret; -} - template static Literal makeLanes(Element& s, MixedArena& allocator, Type lane_t) { std::array lanes; @@ -2124,24 +1598,24 @@ ret->op = op; Address defaultAlign; switch (op) { - case Load8SplatVec128: + case LoadSplatVec8x16: defaultAlign = 1; break; - case Load16SplatVec128: + case LoadSplatVec16x8: defaultAlign = 2; break; - case Load32SplatVec128: - case Load32ZeroVec128: + case LoadSplatVec32x4: + case Load32Zero: defaultAlign = 4; break; - case Load64SplatVec128: - case Load8x8SVec128: - case Load8x8UVec128: - case Load16x4SVec128: - case Load16x4UVec128: - case Load32x2SVec128: - case Load32x2UVec128: - case Load64ZeroVec128: + case LoadSplatVec64x2: + case LoadExtSVec8x8ToVecI16x8: + case LoadExtUVec8x8ToVecI16x8: + case LoadExtSVec16x4ToVecI32x4: + case LoadExtUVec16x4ToVecI32x4: + case LoadExtSVec32x2ToVecI64x2: + case LoadExtUVec32x2ToVecI64x2: + case Load64Zero: defaultAlign = 8; break; } @@ -2159,23 +1633,23 @@ Address defaultAlign; size_t lanes; switch (op) { - case Load8LaneVec128: - case Store8LaneVec128: + case LoadLaneVec8x16: + case StoreLaneVec8x16: defaultAlign = 1; lanes = 16; break; - case Load16LaneVec128: - case Store16LaneVec128: + case LoadLaneVec16x8: + case StoreLaneVec16x8: defaultAlign = 2; lanes = 8; break; - case Load32LaneVec128: - case Store32LaneVec128: + case LoadLaneVec32x4: + case StoreLaneVec32x4: defaultAlign = 4; lanes = 4; break; - case Load64LaneVec128: - case Store64LaneVec128: + case LoadLaneVec64x2: + case StoreLaneVec64x2: defaultAlign = 8; lanes = 2; break; @@ -2190,6 +1664,12 @@ return ret; } +Expression* SExpressionWasmBuilder::makePrefetch(Element& s, PrefetchOp op) { + Address offset, align; + size_t i = parseMemAttributes(s, offset, align, /*defaultAlign*/ 1); + return Builder(wasm).makePrefetch(op, offset, align, parseExpression(s[i])); +} + Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) { auto ret = allocator.alloc(); ret->segment = atoi(s[1]->str().c_str()); @@ -2229,7 +1709,7 @@ auto ret = allocator.alloc(); std::vector types; for (size_t i = 1; i < s.size(); ++i) { - types.push_back(elementToType(*s[i])); + types.push_back(stringToType(s[i]->str())); } ret->type = Type(types); ret->finalize(); @@ -2328,7 +1808,7 @@ auto target = getFunctionName(*s[1]); auto ret = allocator.alloc(); ret->target = target; - ret->type = getFunctionType(ret->target, s).getSignature().results; + ret->type = functionSignatures[ret->target].results; parseCallOperands(s, 2, s.size(), ret); ret->isReturn = isReturn; ret->finalize(); @@ -2337,19 +1817,12 @@ Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s, bool isReturn) { - if (wasm.tables.empty()) { - throw ParseException("no tables", s.line, s.col); + if (!wasm.table.exists) { + throw ParseException("no table", s.line, s.col); } Index i = 1; auto ret = allocator.alloc(); - if (s[i]->isStr()) { - ret->table = s[i++]->str(); - } else { - ret->table = wasm.tables.front()->name; - } - HeapType callType; - i = parseTypeUse(s, i, callType); - ret->heapType = callType; + i = parseTypeUse(s, i, ret->sig); parseCallOperands(s, i, s.size() - 1, ret); ret->target = parseExpression(s[s.size() - 1]); ret->isReturn = isReturn; @@ -2357,7 +1830,7 @@ return ret; } -Name SExpressionWasmBuilder::getLabel(Element& s, LabelType labelType) { +Name SExpressionWasmBuilder::getLabel(Element& s) { if (s.dollared()) { return nameMapper.sourceToUnique(s.str()); } else { @@ -2374,14 +1847,10 @@ throw ParseException("invalid label", s.line, s.col); } if (offset == nameMapper.labelStack.size()) { - if (labelType == LabelType::Break) { - // a break to the function's scope. this means we need an automatic - // block, with a name - brokeToAutoBlock = true; - return FAKE_RETURN; - } - // This is a delegate that delegates to the caller - return DELEGATE_CALLER_TARGET; + // a break to the function's scope. this means we need an automatic block, + // with a name + brokeToAutoBlock = true; + return FAKE_RETURN; } return nameMapper.labelStack[nameMapper.labelStack.size() - 1 - offset]; } @@ -2451,9 +1920,8 @@ return ret; } -Expression* SExpressionWasmBuilder::makeRefIs(Element& s, RefIsOp op) { - auto ret = allocator.alloc(); - ret->op = op; +Expression* SExpressionWasmBuilder::makeRefIsNull(Element& s) { + auto ret = allocator.alloc(); ret->value = parseExpression(s[1]); ret->finalize(); return ret; @@ -2465,7 +1933,7 @@ ret->func = func; // To support typed function refs, we give the reference not just a general // funcref, but a specific subtype with the actual signature. - ret->finalize(Type(getFunctionType(func, s), NonNullable)); + ret->finalize(Type(HeapType(functionSignatures[func]), Nullable)); return ret; } @@ -2477,75 +1945,15 @@ return ret; } -Expression* SExpressionWasmBuilder::makeTableGet(Element& s) { - auto tableName = s[1]->str(); - auto* index = parseExpression(s[2]); - auto* table = wasm.getTableOrNull(tableName); - if (!table) { - throw ParseException("invalid table name in table.get", s.line, s.col); - } - return Builder(wasm).makeTableGet(tableName, index, table->type); -} - -Expression* SExpressionWasmBuilder::makeTableSet(Element& s) { - auto tableName = s[1]->str(); - auto* table = wasm.getTableOrNull(tableName); - if (!table) { - throw ParseException("invalid table name in table.set", s.line, s.col); - } - auto* index = parseExpression(s[2]); - auto* value = parseExpression(s[3]); - return Builder(wasm).makeTableSet(tableName, index, value); -} - -Expression* SExpressionWasmBuilder::makeTableSize(Element& s) { - auto tableName = s[1]->str(); - auto* table = wasm.getTableOrNull(tableName); - if (!table) { - throw ParseException("invalid table name in table.size", s.line, s.col); - } - return Builder(wasm).makeTableSize(tableName); -} - -Expression* SExpressionWasmBuilder::makeTableGrow(Element& s) { - auto tableName = s[1]->str(); - auto* table = wasm.getTableOrNull(tableName); - if (!table) { - throw ParseException("invalid table name in table.grow", s.line, s.col); - } - auto* value = parseExpression(s[2]); - if (!value->type.isRef()) { - throw ParseException("only reference types are valid for tables"); - } - auto* delta = parseExpression(s[3]); - return Builder(wasm).makeTableGrow(tableName, value, delta); -} - -// try can be either in the form of try-catch or try-delegate. -// try-catch is written in the folded wast format as -// (try -// (do -// ... -// ) -// (catch $e -// ... -// ) -// ... -// (catch_all -// ... -// ) -// ) -// Any number of catch blocks can exist, including none. Zero or one catch_all -// block can exist, and if it does, it should be at the end. There should be at -// least one catch or catch_all body per try. -// -// try-delegate is written in the folded format as +// try-catch-end is written in the folded wast format as // (try -// (do +// ... +// (catch // ... // ) -// (delegate $label) // ) +// The parenthesis wrapping 'catch' is just a syntax and does not affect nested +// depths of instructions within. Expression* SExpressionWasmBuilder::makeTry(Element& s) { auto ret = allocator.alloc(); Index i = 1; @@ -2556,74 +1964,59 @@ } else { sName = "try"; } - ret->name = nameMapper.pushLabelName(sName); + auto label = nameMapper.pushLabelName(sName); Type type = parseOptionalResultType(s, i); // signature - if (!elementStartsWith(*s[i], "do")) { throw ParseException( "try body should start with 'do'", s[i]->line, s[i]->col); } - ret->body = makeMaybeBlock(*s[i++], 1, type); - - while (i < s.size() && elementStartsWith(*s[i], "catch")) { - Element& inner = *s[i++]; - if (inner.size() < 2) { - throw ParseException("invalid catch block", inner.line, inner.col); - } - Name tag = getTagName(*inner[1]); - if (!wasm.getTagOrNull(tag)) { - throw ParseException("bad tag name", inner[1]->line, inner[1]->col); - } - ret->catchTags.push_back(getTagName(*inner[1])); - ret->catchBodies.push_back(makeMaybeBlock(inner, 2, type)); - } - - if (i < s.size() && elementStartsWith(*s[i], "catch_all")) { - ret->catchBodies.push_back(makeMaybeBlock(*s[i++], 1, type)); + ret->body = makeTryOrCatchBody(*s[i++], type, true); + if (!elementStartsWith(*s[i], "catch")) { + throw ParseException("catch clause does not exist", s[i]->line, s[i]->col); } - - // 'delegate' cannot target its own try. So we pop the name here. - nameMapper.popLabelName(ret->name); - - if (i < s.size() && elementStartsWith(*s[i], "delegate")) { - Element& inner = *s[i++]; - if (inner.size() != 2) { - throw ParseException("invalid delegate", inner.line, inner.col); - } - ret->delegateTarget = getLabel(*inner[1], LabelType::Exception); - } - - if (i != s.size()) { - throw ParseException( - "there should be at most one catch_all block at the end", s.line, s.col); - } - + ret->catchBody = makeTryOrCatchBody(*s[i++], type, false); ret->finalize(type); - + nameMapper.popLabelName(label); // create a break target if we must - if (BranchUtils::BranchSeeker::has(ret, ret->name)) { + if (BranchUtils::BranchSeeker::has(ret, label)) { auto* block = allocator.alloc(); - // We create a different name for the wrapping block, because try's name can - // be used by internal delegates - block->name = nameMapper.pushLabelName(sName); - // For simplicity, try's name can only be targeted by delegates and - // rethrows. Make the branches target the new wrapping block instead. - BranchUtils::replaceBranchTargets(ret, ret->name, block->name); + block->name = label; block->list.push_back(ret); - nameMapper.popLabelName(block->name); block->finalize(type); return block; } return ret; } +Expression* +SExpressionWasmBuilder::makeTryOrCatchBody(Element& s, Type type, bool isTry) { + if (isTry && !elementStartsWith(s, "do")) { + throw ParseException("invalid try do clause", s.line, s.col); + } + if (!isTry && !elementStartsWith(s, "catch")) { + throw ParseException("invalid catch clause", s.line, s.col); + } + if (s.size() == 1) { // (do) or (catch) without instructions + return makeNop(); + } + auto ret = allocator.alloc(); + for (size_t i = 1; i < s.size(); i++) { + ret->list.push_back(parseExpression(s[i])); + } + if (ret->list.size() == 1) { + return ret->list[0]; + } + ret->finalize(type); + return ret; +} + Expression* SExpressionWasmBuilder::makeThrow(Element& s) { auto ret = allocator.alloc(); Index i = 1; - ret->tag = getTagName(*s[i++]); - if (!wasm.getTagOrNull(ret->tag)) { - throw ParseException("bad tag name", s[1]->line, s[1]->col); + ret->event = getEventName(*s[i++]); + if (!wasm.getEventOrNull(ret->event)) { + throw ParseException("bad event name", s[1]->line, s[1]->col); } for (; i < s.size(); i++) { ret->operands.push_back(parseExpression(s[i])); @@ -2634,7 +2027,26 @@ Expression* SExpressionWasmBuilder::makeRethrow(Element& s) { auto ret = allocator.alloc(); - ret->target = getLabel(*s[1], LabelType::Exception); + ret->exnref = parseExpression(*s[1]); + ret->finalize(); + return ret; +} + +Expression* SExpressionWasmBuilder::makeBrOnExn(Element& s) { + auto ret = allocator.alloc(); + size_t i = 1; + ret->name = getLabel(*s[i++]); + ret->event = getEventName(*s[i++]); + if (!wasm.getEventOrNull(ret->event)) { + throw ParseException("bad event name", s[1]->line, s[1]->col); + } + ret->exnref = parseExpression(s[i]); + + Event* event = wasm.getEventOrNull(ret->event); + assert(event && "br_on_exn's event must exist"); + // Copy params info into BrOnExn, because it is necessary when BrOnExn is + // refinalized without the module. + ret->sent = event->sig.params; ret->finalize(); return ret; } @@ -2650,20 +2062,26 @@ auto ret = allocator.alloc(); ret->index = atoi(s[1]->str().c_str()); ret->tuple = parseExpression(s[2]); - if (ret->tuple->type != Type::unreachable && - ret->index >= ret->tuple->type.size()) { - throw ParseException("Bad index on tuple.extract", s[1]->line, s[1]->col); - } ret->finalize(); return ret; } Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) { - std::vector operands; - parseOperands(s, 1, s.size() - 1, operands); - auto* target = parseExpression(s[s.size() - 1]); - return ValidatingBuilder(wasm, s.line, s.col) - .validateAndMakeCallRef(target, operands, isReturn); + auto ret = allocator.alloc(); + parseCallOperands(s, 1, s.size() - 1, ret); + ret->target = parseExpression(s[s.size() - 1]); + ret->isReturn = isReturn; + if (!ret->target->type.isRef()) { + throw ParseException("Non-reference type for a call_ref", s.line, s.col); + } + auto heapType = ret->target->type.getHeapType(); + if (!heapType.isSignature()) { + throw ParseException( + "Invalid reference type for a call_ref", s.line, s.col); + } + auto sig = heapType.getSignature(); + ret->finalize(sig.results); + return ret; } Expression* SExpressionWasmBuilder::makeI31New(Element& s) { @@ -2682,51 +2100,28 @@ } Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { - auto* ref = parseExpression(*s[1]); - auto* rtt = parseExpression(*s[2]); - return Builder(wasm).makeRefTest(ref, rtt); -} - -Expression* SExpressionWasmBuilder::makeRefTestStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); - return Builder(wasm).makeRefTest(ref, heapType); + auto* rtt = parseExpression(*s[3]); + validateHeapTypeUsingChild(rtt, heapType, s); + return Builder(wasm).makeRefTest(ref, rtt); } Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { - auto* ref = parseExpression(*s[1]); - auto* rtt = parseExpression(*s[2]); - return Builder(wasm).makeRefCast(ref, rtt); -} - -Expression* SExpressionWasmBuilder::makeRefCastStatic(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto* ref = parseExpression(*s[2]); - return Builder(wasm).makeRefCast(ref, heapType, RefCast::Safe); -} - -Expression* SExpressionWasmBuilder::makeRefCastNopStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); - return Builder(wasm).makeRefCast(ref, heapType, RefCast::Unsafe); -} - -Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) { - auto name = getLabel(*s[1]); - auto* ref = parseExpression(*s[2]); - Expression* rtt = nullptr; - if (op == BrOnCast || op == BrOnCastFail) { - rtt = parseExpression(*s[3]); - } - return ValidatingBuilder(wasm, s.line, s.col) - .validateAndMakeBrOn(op, name, ref, rtt); + auto* rtt = parseExpression(*s[3]); + validateHeapTypeUsingChild(rtt, heapType, s); + return Builder(wasm).makeRefCast(ref, rtt); } -Expression* SExpressionWasmBuilder::makeBrOnStatic(Element& s, BrOnOp op) { +Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s) { auto name = getLabel(*s[1]); auto heapType = parseHeapType(*s[2]); auto* ref = parseExpression(*s[3]); - return Builder(wasm).makeBrOn(op, name, ref, heapType); + auto* rtt = parseExpression(*s[4]); + validateHeapTypeUsingChild(rtt, heapType, s); + return Builder(wasm).makeBrOnCast(name, heapType, ref, rtt); } Expression* SExpressionWasmBuilder::makeRttCanon(Element& s) { @@ -2739,14 +2134,10 @@ return Builder(wasm).makeRttSub(heapType, parent); } -Expression* SExpressionWasmBuilder::makeRttFreshSub(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto parent = parseExpression(*s[2]); - return Builder(wasm).makeRttFreshSub(heapType, parent); -} - Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); + auto* rtt = parseExpression(*s[2]); + validateHeapTypeUsingChild(rtt, heapType, s); auto numOperands = s.size() - 3; if (default_ && numOperands > 0) { throw ParseException( @@ -2755,53 +2146,30 @@ std::vector operands; operands.resize(numOperands); for (Index i = 0; i < numOperands; i++) { - operands[i] = parseExpression(*s[i + 2]); + operands[i] = parseExpression(*s[i + 3]); } - auto* rtt = parseExpression(*s[s.size() - 1]); - validateHeapTypeUsingChild(rtt, heapType, s); return Builder(wasm).makeStructNew(rtt, operands); } -Expression* SExpressionWasmBuilder::makeStructNewStatic(Element& s, - bool default_) { - auto heapType = parseHeapType(*s[1]); - auto numOperands = s.size() - 2; - if (default_ && numOperands > 0) { - throw ParseException("arguments provided for struct.new", s.line, s.col); - } - std::vector operands; - operands.resize(numOperands); - for (Index i = 0; i < numOperands; i++) { - operands[i] = parseExpression(*s[i + 2]); - } - return Builder(wasm).makeStructNew(heapType, operands); -} - -Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) { - if (field.dollared()) { - auto name = field.str(); - auto index = typeIndices[type.str().str]; - auto struct_ = types[index].getStruct(); +Index SExpressionWasmBuilder::getStructIndex(const HeapType& type, Element& s) { + if (s.dollared()) { + auto name = s.str(); + auto struct_ = type.getStruct(); auto& fields = struct_.fields; - const auto& names = fieldNames[index]; for (Index i = 0; i < fields.size(); i++) { - auto it = names.find(i); - if (it != names.end() && it->second == name) { + if (fields[i].name == name) { return i; } } - throw ParseException("bad struct field name", field.line, field.col); + throw ParseException("bad struct name", s.line, s.col); } // this is a numeric index - return atoi(field.c_str()); + return atoi(s.c_str()); } Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) { auto heapType = parseHeapType(*s[1]); - if (!heapType.isStruct()) { - throw ParseException("bad struct heap type", s.line, s.col); - } - auto index = getStructIndex(*s[1], *s[2]); + auto index = getStructIndex(heapType, *s[2]); auto type = heapType.getStruct().fields[index].type; auto ref = parseExpression(*s[3]); validateHeapTypeUsingChild(ref, heapType, s); @@ -2810,10 +2178,7 @@ Expression* SExpressionWasmBuilder::makeStructSet(Element& s) { auto heapType = parseHeapType(*s[1]); - if (!heapType.isStruct()) { - throw ParseException("bad struct heap type", s.line, s.col); - } - auto index = getStructIndex(*s[1], *s[2]); + auto index = getStructIndex(heapType, *s[2]); auto ref = parseExpression(*s[3]); validateHeapTypeUsingChild(ref, heapType, s); auto value = parseExpression(*s[4]); @@ -2822,49 +2187,14 @@ Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); - Expression* init = nullptr; - size_t i = 2; - if (!default_) { - init = parseExpression(*s[i++]); - } - auto* size = parseExpression(*s[i++]); - auto* rtt = parseExpression(*s[i++]); + auto* rtt = parseExpression(*s[2]); validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeArrayNew(rtt, size, init); -} - -Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s, - bool default_) { - auto heapType = parseHeapType(*s[1]); + auto* size = parseExpression(*s[3]); Expression* init = nullptr; - size_t i = 2; if (!default_) { - init = parseExpression(*s[i++]); - } - auto* size = parseExpression(*s[i++]); - return Builder(wasm).makeArrayNew(heapType, size, init); -} - -Expression* SExpressionWasmBuilder::makeArrayInit(Element& s) { - auto heapType = parseHeapType(*s[1]); - size_t i = 2; - std::vector values; - while (i < s.size() - 1) { - values.push_back(parseExpression(*s[i++])); - } - auto* rtt = parseExpression(*s[i++]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeArrayInit(rtt, values); -} - -Expression* SExpressionWasmBuilder::makeArrayInitStatic(Element& s) { - auto heapType = parseHeapType(*s[1]); - size_t i = 2; - std::vector values; - while (i < s.size()) { - values.push_back(parseExpression(*s[i++])); + init = parseExpression(*s[4]); } - return Builder(wasm).makeArrayInit(heapType, values); + return Builder(wasm).makeArrayNew(rtt, size, init); } Expression* SExpressionWasmBuilder::makeArrayGet(Element& s, bool signed_) { @@ -2891,24 +2221,6 @@ return Builder(wasm).makeArrayLen(ref); } -Expression* SExpressionWasmBuilder::makeArrayCopy(Element& s) { - auto destHeapType = parseHeapType(*s[1]); - auto srcHeapType = parseHeapType(*s[2]); - auto destRef = parseExpression(*s[3]); - validateHeapTypeUsingChild(destRef, destHeapType, s); - auto destIndex = parseExpression(*s[4]); - auto srcRef = parseExpression(*s[5]); - validateHeapTypeUsingChild(srcRef, srcHeapType, s); - auto srcIndex = parseExpression(*s[6]); - auto length = parseExpression(*s[7]); - return Builder(wasm).makeArrayCopy( - destRef, destIndex, srcRef, srcIndex, length); -} - -Expression* SExpressionWasmBuilder::makeRefAs(Element& s, RefAsOp op) { - return Builder(wasm).makeRefAs(op, parseExpression(s[1])); -} - // converts an s-expression string representing binary data into an output // sequence of raw bytes this appends to data, which may already contain // content. @@ -3032,12 +2344,7 @@ } // (memory (data ..)) format auto j = parseMemoryIndex(inner, 1); - auto offset = allocator.alloc(); - if (wasm.memory.is64()) { - offset->set(Literal(int64_t(0))); - } else { - offset->set(Literal(int32_t(0))); - } + auto offset = allocator.alloc()->set(Literal(int32_t(0))); parseInnerData(inner, j, {}, offset, false); wasm.memory.initial = wasm.memory.segments[0].data.size(); return; @@ -3063,13 +2370,8 @@ } const char* input = curr[j]->c_str(); auto* offset = allocator.alloc(); - if (wasm.memory.is64()) { - offset->type = Type::i64; - offset->value = Literal(offsetValue); - } else { - offset->type = Type::i32; - offset->value = Literal(int32_t(offsetValue)); - } + offset->type = Type::i32; + offset->value = Literal(int32_t(offsetValue)); if (auto size = strlen(input)) { std::vector data; stringToBinary(input, size, data); @@ -3085,34 +2387,27 @@ if (!wasm.memory.exists) { throw ParseException("data but no memory", s.line, s.col); } - bool isPassive = true; + bool isPassive = false; Expression* offset = nullptr; Index i = 1; Name name; - - if (s[i]->isStr() && s[i]->dollared()) { + if (s[i]->dollared()) { name = s[i++]->str(); } - - if (s[i]->isList()) { - // Optional (memory ) - if (elementStartsWith(s[i], MEMORY)) { - // TODO: we're just skipping memory since we have only one. Assign the - // memory name to the segment when we support multiple memories. - i += 1; - } - - // Offset expression (offset ()) | () - auto& inner = *s[i++]; - if (elementStartsWith(inner, OFFSET)) { - offset = parseExpression(inner[1]); - } else { - offset = parseExpression(inner); + if (s[i]->isStr()) { + // data is passive or named + if (s[i]->str() == PASSIVE) { + isPassive = true; } - isPassive = false; + i++; } - - parseInnerData(s, i, name, offset, isPassive); + if (!isPassive) { + offset = parseExpression(s[i]); + } + if (s.size() != 3 && s.size() != 4) { + throw ParseException("Unexpected data items", s.line, s.col); + } + parseInnerData(s, s.size() - 1, name, offset, isPassive); } void SExpressionWasmBuilder::parseInnerData( @@ -3133,21 +2428,17 @@ ex->name = s[1]->str(); if (s[2]->isList()) { auto& inner = *s[2]; + ex->value = inner[1]->str(); if (elementStartsWith(inner, FUNC)) { ex->kind = ExternalKind::Function; - ex->value = getFunctionName(*inner[1]); } else if (elementStartsWith(inner, MEMORY)) { ex->kind = ExternalKind::Memory; - ex->value = inner[1]->str(); } else if (elementStartsWith(inner, TABLE)) { ex->kind = ExternalKind::Table; - ex->value = getTableName(*inner[1]); } else if (elementStartsWith(inner, GLOBAL)) { ex->kind = ExternalKind::Global; - ex->value = getGlobalName(*inner[1]); - } else if (inner[0]->str() == TAG) { - ex->kind = ExternalKind::Tag; - ex->value = getTagName(*inner[1]); + } else if (inner[0]->str() == EVENT) { + ex->kind = ExternalKind::Event; } else { throw ParseException("invalid export", inner.line, inner.col); } @@ -3178,10 +2469,14 @@ wasm.memory.exists = true; } else if (elementStartsWith(*s[3], TABLE)) { kind = ExternalKind::Table; + if (wasm.table.exists) { + throw ParseException("more than one table", s[3]->line, s[3]->col); + } + wasm.table.exists = true; } else if (elementStartsWith(*s[3], GLOBAL)) { kind = ExternalKind::Global; - } else if ((*s[3])[0]->str() == TAG) { - kind = ExternalKind::Tag; + } else if ((*s[3])[0]->str() == EVENT) { + kind = ExternalKind::Event; } else { newStyle = false; // either (param..) or (result..) } @@ -3206,9 +2501,9 @@ name = Name("mimport$" + std::to_string(memoryCounter++)); } else if (kind == ExternalKind::Table) { name = Name("timport$" + std::to_string(tableCounter++)); - } else if (kind == ExternalKind::Tag) { - name = Name("eimport$" + std::to_string(tagCounter++)); - tagNames.push_back(name); + } else if (kind == ExternalKind::Event) { + name = Name("eimport$" + std::to_string(eventCounter++)); + eventNames.push_back(name); } else { throw ParseException("invalid import", s[3]->line, s[3]->col); } @@ -3232,11 +2527,11 @@ if (kind == ExternalKind::Function) { auto func = make_unique(); - j = parseTypeUse(inner, j, func->type); + j = parseTypeUse(inner, j, func->sig); func->setName(name, hasExplicitName); func->module = module; func->base = base; - functionTypes[name] = func->type; + functionSignatures[name] = func->sig; wasm.addFunction(func.release()); } else if (kind == ExternalKind::Global) { Type type; @@ -3259,27 +2554,21 @@ global->mutable_ = mutable_; wasm.addGlobal(global.release()); } else if (kind == ExternalKind::Table) { - auto table = make_unique
(); - table->setName(name, hasExplicitName); - table->module = module; - table->base = base; - tableNames.push_back(name); - + wasm.table.setName(name, hasExplicitName); + wasm.table.module = module; + wasm.table.base = base; if (j < inner.size() - 1) { auto initElem = inner[j++]; - table->initial = getAddress(initElem); - checkAddress(table->initial, "excessive table init size", initElem); + wasm.table.initial = getAddress(initElem); + checkAddress(wasm.table.initial, "excessive table init size", initElem); } if (j < inner.size() - 1) { auto maxElem = inner[j++]; - table->max = getAddress(maxElem); - checkAddress(table->max, "excessive table max size", maxElem); + wasm.table.max = getAddress(maxElem); + checkAddress(wasm.table.max, "excessive table max size", maxElem); } else { - table->max = Table::kUnlimitedSize; + wasm.table.max = Table::kUnlimitedSize; } - - wasm.addTable(std::move(table)); - j++; // funcref // ends with the table element type } else if (kind == ExternalKind::Memory) { @@ -3297,15 +2586,21 @@ } else { j = parseMemoryLimits(inner, j); } - } else if (kind == ExternalKind::Tag) { - auto tag = make_unique(); - HeapType tagType; - j = parseTypeUse(inner, j, tagType); - tag->sig = tagType.getSignature(); - tag->setName(name, hasExplicitName); - tag->module = module; - tag->base = base; - wasm.addTag(tag.release()); + } else if (kind == ExternalKind::Event) { + auto event = make_unique(); + if (j >= inner.size()) { + throw ParseException("event does not have an attribute", s.line, s.col); + } + auto& attrElem = *inner[j++]; + if (!elementStartsWith(attrElem, ATTR) || attrElem.size() != 2) { + throw ParseException("invalid attribute", attrElem.line, attrElem.col); + } + event->attribute = atoi(attrElem[1]->c_str()); + j = parseTypeUse(inner, j, event->sig); + event->setName(name, hasExplicitName); + event->module = module; + event->base = base; + wasm.addEvent(event.release()); } // If there are more elements, they are invalid if (j < inner.size()) { @@ -3397,22 +2692,27 @@ } void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) { - std::unique_ptr
table = make_unique
(); + if (wasm.table.exists) { + throw ParseException("more than one table", s.line, s.col); + } + wasm.table.exists = true; Index i = 1; + if (i == s.size()) { + return; // empty table in old notation + } if (s[i]->dollared()) { - table->setExplicitName(s[i++]->str()); - } else { - table->name = Name::fromInt(tableCounter++); + wasm.table.setExplicitName(s[i++]->str()); + } + if (i == s.size()) { + return; } - tableNames.push_back(table->name); - Name importModule, importBase; if (s[i]->isList()) { auto& inner = *s[i]; if (elementStartsWith(inner, EXPORT)) { auto ex = make_unique(); ex->name = inner[1]->str(); - ex->value = table->name; + ex->value = wasm.table.name; ex->kind = ExternalKind::Table; if (wasm.getExportOrNull(ex->name)) { throw ParseException("duplicate export", inner.line, inner.col); @@ -3423,179 +2723,75 @@ if (!preParseImport) { throw ParseException("!preParseImport in table", inner.line, inner.col); } - table->module = inner[1]->str(); - table->base = inner[2]->str(); + wasm.table.module = inner[1]->str(); + wasm.table.base = inner[2]->str(); i++; - } else if (!elementStartsWith(inner, REF)) { + } else { throw ParseException("invalid table", inner.line, inner.col); } } - - bool hasExplicitLimit = false; - - if (s[i]->isStr() && String::isNumber(s[i]->c_str())) { - table->initial = atoi(s[i++]->c_str()); - hasExplicitLimit = true; - } - if (s[i]->isStr() && String::isNumber(s[i]->c_str())) { - table->max = atoi(s[i++]->c_str()); - } - - table->type = elementToType(*s[i++]); - if (!table->type.isRef()) { - throw ParseException("Only reference types are valid for tables"); - } - - if (i < s.size() && s[i]->isList()) { - if (hasExplicitLimit) { - throw ParseException( - "Table cannot have both explicit limits and an inline (elem ...)"); - } - // (table type (elem ..)) - parseElem(*s[i], table.get()); - auto it = std::find_if(wasm.elementSegments.begin(), - wasm.elementSegments.end(), - [&](std::unique_ptr& segment) { - return segment->table == table->name; - }); - if (it != wasm.elementSegments.end()) { - table->initial = table->max = it->get()->data.size(); - } else { - table->initial = table->max = 0; - } - } - - wasm.addTable(std::move(table)); -} - -// parses an elem segment -// elem ::= (elem (table tableidx)? (offset (expr)) reftype vec(item (expr))) -// | (elem reftype vec(item (expr))) -// | (elem declare reftype vec(item (expr))) -// -// abbreviation: -// (offset (expr)) ≡ (expr) -// (item (expr)) ≡ (expr) -// ϵ ≡ (table 0) -// -// funcref vec(ref.func) ≡ func vec(funcidx) -// (elem (expr) vec(funcidx)) ≡ (elem (table 0) (offset (expr)) func -// vec(funcidx)) -// -void SExpressionWasmBuilder::parseElem(Element& s, Table* table) { - Index i = 1; - Name name = Name::fromInt(elemCounter++); - bool hasExplicitName = false; - bool isPassive = true; - bool usesExpressions = false; - - if (table) { - Expression* offset = allocator.alloc()->set(Literal(int32_t(0))); - auto segment = std::make_unique(table->name, offset); - segment->setName(name, hasExplicitName); - parseElemFinish(s, segment, i, s[i]->isList()); - return; - } - - if (s[i]->isStr() && s[i]->dollared()) { - name = s[i++]->str(); - hasExplicitName = true; - } - if (s[i]->isStr() && s[i]->str() == DECLARE) { - // We don't store declared segments in the IR + if (i == s.size()) { return; } - - auto segment = std::make_unique(); - segment->setName(name, hasExplicitName); - - if (s[i]->isList() && !elementStartsWith(s[i], REF)) { - // Optional (table ) - if (elementStartsWith(s[i], TABLE)) { - auto& inner = *s[i++]; - segment->table = getTableName(*inner[1]); - } - - // Offset expression (offset ()) | () - auto& inner = *s[i++]; - if (elementStartsWith(inner, OFFSET)) { - if (inner.size() > 2) { - throw ParseException( - "Invalid offset for an element segment.", s.line, s.col); + if (!s[i]->dollared()) { + if (s[i]->str() == FUNCREF) { + // (table type (elem ..)) + parseInnerElem(*s[i + 1]); + if (wasm.table.segments.size() > 0) { + wasm.table.initial = wasm.table.max = + wasm.table.segments[0].data.size(); + } else { + wasm.table.initial = wasm.table.max = 0; } - segment->offset = parseExpression(inner[1]); - } else { - segment->offset = parseExpression(inner); + return; } - isPassive = false; - } - - if (i < s.size()) { - if (s[i]->isStr() && s[i]->dollared()) { - usesExpressions = false; - } else if (s[i]->isStr() && s[i]->str() == FUNC) { - usesExpressions = false; - i += 1; - } else { - segment->type = elementToType(*s[i]); - usesExpressions = true; - i += 1; - - if (!segment->type.isFunction()) { - throw ParseException( - "Invalid type for an element segment.", s.line, s.col); + // first element isn't dollared, and isn't funcref. this could be old syntax + // for (table 0 1) which means function 0 and 1, or it could be (table + // initial max? type), look for type + if (s[s.size() - 1]->str() == FUNCREF) { + // (table initial max? type) + if (i < s.size() - 1) { + wasm.table.initial = atoi(s[i++]->c_str()); } + if (i < s.size() - 1) { + wasm.table.max = atoi(s[i++]->c_str()); + } + return; } } - - if (!isPassive && segment->table.isNull()) { - if (wasm.tables.empty()) { - throw ParseException("active element without table", s.line, s.col); - } - table = wasm.tables.front().get(); - segment->table = table->name; + // old notation (table func1 func2 ..) + parseInnerElem(s, i); + if (wasm.table.segments.size() > 0) { + wasm.table.initial = wasm.table.max = wasm.table.segments[0].data.size(); + } else { + wasm.table.initial = wasm.table.max = 0; } - - // We may be post-MVP also due to type reasons or otherwise, as detected by - // the utility function for Binaryen IR. - usesExpressions = - usesExpressions || TableUtils::usesExpressions(segment.get(), &wasm); - - parseElemFinish(s, segment, i, usesExpressions); } -ElementSegment* SExpressionWasmBuilder::parseElemFinish( - Element& s, - std::unique_ptr& segment, - Index i, - bool usesExpressions) { +void SExpressionWasmBuilder::parseElem(Element& s) { + Index i = 1; + if (!s[i]->isList()) { + // the table is named + i++; + } + auto* offset = parseExpression(s[i++]); + parseInnerElem(s, i, offset); +} +void SExpressionWasmBuilder::parseInnerElem(Element& s, + Index i, + Expression* offset) { + if (!wasm.table.exists) { + throw ParseException("elem without table", s.line, s.col); + } + if (!offset) { + offset = allocator.alloc()->set(Literal(int32_t(0))); + } + Table::Segment segment(offset); for (; i < s.size(); i++) { - if (!s[i]->isList()) { - // An MVP-style declaration: just a function name. - auto func = getFunctionName(*s[i]); - segment->data.push_back( - Builder(wasm).makeRefFunc(func, functionTypes[func])); - continue; - } - if (!usesExpressions) { - throw ParseException("expected an MVP-style $funcname in elem."); - } - auto& inner = *s[i]; - if (elementStartsWith(inner, ITEM)) { - if (inner[1]->isList()) { - // (item (ref.func $f)) - segment->data.push_back(parseExpression(inner[1])); - } else { - // (item ref.func $f) - inner.list().removeAt(0); - segment->data.push_back(parseExpression(inner)); - } - } else { - segment->data.push_back(parseExpression(inner)); - } + segment.data.push_back(getFunctionName(*s[i])); } - return wasm.addElementSegment(std::move(segment)); + wasm.table.segments.push_back(segment); } HeapType SExpressionWasmBuilder::parseHeapType(Element& s) { @@ -3621,26 +2817,98 @@ return stringToHeapType(str, /* prefix = */ false); } } + // It's a list. + if (*s[0] == FUNC) { + std::vector params; + std::vector results; + for (size_t k = 1; k < s.size(); k++) { + Element& curr = *s[k]; + if (elementStartsWith(curr, PARAM)) { + auto newParams = parseParamOrLocal(curr); + params.insert(params.end(), newParams.begin(), newParams.end()); + } else if (elementStartsWith(curr, RESULT)) { + auto newResults = parseResults(curr); + results.insert(results.end(), newResults.begin(), newResults.end()); + } + } + return Signature(Type(params), Type(results)); + } + // It's a struct or an array. + auto parseField = [&](Element* t) { + Mutability mutable_ = Immutable; + // t is a list, containing either + // TYPE + // or + // (field TYPE) + // or + // (field $name TYPE) + Name name; + if (elementStartsWith(t, FIELD)) { + if (t->size() == 3) { + name = (*t)[1]->str(); + } + t = (*t)[t->size() - 1]; + } + // The element may also be (mut (..)). + if (elementStartsWith(t, MUT)) { + mutable_ = Mutable; + t = (*t)[1]; + } + if (t->isStr()) { + // t is a simple string name like "i32". It can be a normal wasm type, or + // one of the special types only available in fields. + if (*t == I8) { + return Field(Field::i8, mutable_, name); + } else if (*t == I16) { + return Field(Field::i16, mutable_, name); + } + } + // Otherwise it's an arbitrary type. + return Field(elementToType(*t), mutable_, name); + }; + if (elementStartsWith(s, STRUCT)) { + FieldList fields; + for (size_t k = 1; k < s.size(); k++) { + fields.emplace_back(parseField(s[k])); + } + return Struct(fields); + } + if (elementStartsWith(s, ARRAY)) { + return Array(parseField(s[1])); + } throw ParseException("invalid heap type", s.line, s.col); } -void SExpressionWasmBuilder::parseTag(Element& s, bool preParseImport) { - auto tag = make_unique(); +void SExpressionWasmBuilder::parseType(Element& s) { + size_t i = 1; + if (s[i]->isStr()) { + std::string name = s[i]->str().str; + if (typeIndices.find(name) != typeIndices.end()) { + throw ParseException("duplicate function type", s.line, s.col); + } + typeIndices[name] = types.size(); + i++; + } + types.emplace_back(parseHeapType(*s[i])); +} + +void SExpressionWasmBuilder::parseEvent(Element& s, bool preParseImport) { + auto event = make_unique(); size_t i = 1; // Parse name if (s[i]->isStr() && s[i]->dollared()) { auto& inner = *s[i++]; - tag->setExplicitName(inner.str()); - if (wasm.getTagOrNull(tag->name)) { - throw ParseException("duplicate tag", inner.line, inner.col); + event->setExplicitName(inner.str()); + if (wasm.getEventOrNull(event->name)) { + throw ParseException("duplicate event", inner.line, inner.col); } } else { - tag->name = Name::fromInt(tagCounter); - assert(!wasm.getTagOrNull(tag->name)); + event->name = Name::fromInt(eventCounter); + assert(!wasm.getEventOrNull(event->name)); } - tagCounter++; - tagNames.push_back(tag->name); + eventCounter++; + eventNames.push_back(event->name); // Parse import, if any if (i < s.size() && elementStartsWith(*s[i], IMPORT)) { @@ -3657,14 +2925,14 @@ throw ParseException( "invalid import base name", importElem[2]->line, importElem[2]->col); } - tag->module = importElem[1]->str(); - tag->base = importElem[2]->str(); + event->module = importElem[1]->str(); + event->base = importElem[2]->str(); } // Parse export, if any if (i < s.size() && elementStartsWith(*s[i], EXPORT)) { auto& exportElem = *s[i++]; - if (tag->module.is()) { + if (event->module.is()) { throw ParseException("import and export cannot be specified together", exportElem.line, exportElem.col); @@ -3682,21 +2950,33 @@ throw ParseException( "duplicate export", exportElem[1]->line, exportElem[1]->col); } - ex->value = tag->name; - ex->kind = ExternalKind::Tag; + ex->value = event->name; + ex->kind = ExternalKind::Event; + } + + // Parse attribute + if (i >= s.size()) { + throw ParseException("event does not have an attribute", s.line, s.col); + } + auto& attrElem = *s[i++]; + if (!elementStartsWith(attrElem, ATTR) || attrElem.size() != 2) { + throw ParseException("invalid attribute", attrElem.line, attrElem.col); + } + if (!attrElem[1]->isStr()) { + throw ParseException( + "invalid attribute", attrElem[1]->line, attrElem[1]->col); } + event->attribute = atoi(attrElem[1]->c_str()); // Parse typeuse - HeapType tagType; - i = parseTypeUse(s, i, tagType); - tag->sig = tagType.getSignature(); + i = parseTypeUse(s, i, event->sig); // If there are more elements, they are invalid if (i < s.size()) { throw ParseException("invalid element", s[i]->line, s[i]->col); } - wasm.addTag(tag.release()); + wasm.addEvent(event.release()); } void SExpressionWasmBuilder::validateHeapTypeUsingChild(Expression* child, @@ -3706,7 +2986,7 @@ return; } if ((!child->type.isRef() && !child->type.isRtt()) || - !HeapType::isSubType(child->type.getHeapType(), heapType)) { + child->type.getHeapType() != heapType) { throw ParseException("bad heap type: expected " + heapType.toString() + " but found " + child->type.toString(), s.line, diff -Nru binaryen-108/src/wasm/wasm-stack.cpp binaryen-99/src/wasm/wasm-stack.cpp --- binaryen-108/src/wasm/wasm-stack.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-stack.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -48,6 +48,9 @@ } void BinaryInstWriter::emitIfElse(If* curr) { + assert(!breakStack.empty()); + breakStack.pop_back(); + breakStack.emplace_back(IMPOSSIBLE_CONTINUE); // TODO same as If if (func && !sourceMap) { parent.writeExtraDebugLocation(curr, func, BinaryLocations::Else); } @@ -80,10 +83,10 @@ } void BinaryInstWriter::visitCallIndirect(CallIndirect* curr) { - Index tableIdx = parent.getTableIndex(curr->table); int8_t op = curr->isReturn ? BinaryConsts::RetCallIndirect : BinaryConsts::CallIndirect; - o << op << U32LEB(parent.getTypeIndex(curr->heapType)) << U32LEB(tableIdx); + o << op << U32LEB(parent.getTypeIndex(curr->sig)) + << U32LEB(0); // Reserved flags field } void BinaryInstWriter::visitLocalGet(LocalGet* curr) { @@ -188,10 +191,11 @@ // a load return; case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -291,10 +295,11 @@ << U32LEB(BinaryConsts::V128Store); break; case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -531,7 +536,7 @@ } void BinaryInstWriter::visitSIMDShuffle(SIMDShuffle* curr) { - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Shuffle); + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V8x16Shuffle); for (uint8_t m : curr->mask) { o << m; } @@ -543,35 +548,29 @@ case Bitselect: o << U32LEB(BinaryConsts::V128Bitselect); break; - case LaneselectI8x16: - o << U32LEB(BinaryConsts::I8x16Laneselect); - break; - case LaneselectI16x8: - o << U32LEB(BinaryConsts::I16x8Laneselect); + case QFMAF32x4: + o << U32LEB(BinaryConsts::F32x4QFMA); break; - case LaneselectI32x4: - o << U32LEB(BinaryConsts::I32x4Laneselect); + case QFMSF32x4: + o << U32LEB(BinaryConsts::F32x4QFMS); break; - case LaneselectI64x2: - o << U32LEB(BinaryConsts::I64x2Laneselect); + case QFMAF64x2: + o << U32LEB(BinaryConsts::F64x2QFMA); break; - case RelaxedFmaVecF32x4: - o << U32LEB(BinaryConsts::F32x4RelaxedFma); + case QFMSF64x2: + o << U32LEB(BinaryConsts::F64x2QFMS); break; - case RelaxedFmsVecF32x4: - o << U32LEB(BinaryConsts::F32x4RelaxedFms); + case SignSelectVec8x16: + o << U32LEB(BinaryConsts::V8x16SignSelect); break; - case RelaxedFmaVecF64x2: - o << U32LEB(BinaryConsts::F64x2RelaxedFma); + case SignSelectVec16x8: + o << U32LEB(BinaryConsts::V16x8SignSelect); break; - case RelaxedFmsVecF64x2: - o << U32LEB(BinaryConsts::F64x2RelaxedFms); + case SignSelectVec32x4: + o << U32LEB(BinaryConsts::V32x4SignSelect); break; - case DotI8x16I7x16AddSToVecI32x4: - o << U32LEB(BinaryConsts::I32x4DotI8x16I7x16AddS); - break; - case DotI8x16I7x16AddUToVecI32x4: - o << U32LEB(BinaryConsts::I32x4DotI8x16I7x16AddU); + case SignSelectVec64x2: + o << U32LEB(BinaryConsts::V64x2SignSelect); break; } } @@ -621,40 +620,40 @@ void BinaryInstWriter::visitSIMDLoad(SIMDLoad* curr) { o << int8_t(BinaryConsts::SIMDPrefix); switch (curr->op) { - case Load8SplatVec128: - o << U32LEB(BinaryConsts::V128Load8Splat); + case LoadSplatVec8x16: + o << U32LEB(BinaryConsts::V8x16LoadSplat); break; - case Load16SplatVec128: - o << U32LEB(BinaryConsts::V128Load16Splat); + case LoadSplatVec16x8: + o << U32LEB(BinaryConsts::V16x8LoadSplat); break; - case Load32SplatVec128: - o << U32LEB(BinaryConsts::V128Load32Splat); + case LoadSplatVec32x4: + o << U32LEB(BinaryConsts::V32x4LoadSplat); break; - case Load64SplatVec128: - o << U32LEB(BinaryConsts::V128Load64Splat); + case LoadSplatVec64x2: + o << U32LEB(BinaryConsts::V64x2LoadSplat); break; - case Load8x8SVec128: - o << U32LEB(BinaryConsts::V128Load8x8S); + case LoadExtSVec8x8ToVecI16x8: + o << U32LEB(BinaryConsts::I16x8LoadExtSVec8x8); break; - case Load8x8UVec128: - o << U32LEB(BinaryConsts::V128Load8x8U); + case LoadExtUVec8x8ToVecI16x8: + o << U32LEB(BinaryConsts::I16x8LoadExtUVec8x8); break; - case Load16x4SVec128: - o << U32LEB(BinaryConsts::V128Load16x4S); + case LoadExtSVec16x4ToVecI32x4: + o << U32LEB(BinaryConsts::I32x4LoadExtSVec16x4); break; - case Load16x4UVec128: - o << U32LEB(BinaryConsts::V128Load16x4U); + case LoadExtUVec16x4ToVecI32x4: + o << U32LEB(BinaryConsts::I32x4LoadExtUVec16x4); break; - case Load32x2SVec128: - o << U32LEB(BinaryConsts::V128Load32x2S); + case LoadExtSVec32x2ToVecI64x2: + o << U32LEB(BinaryConsts::I64x2LoadExtSVec32x2); break; - case Load32x2UVec128: - o << U32LEB(BinaryConsts::V128Load32x2U); + case LoadExtUVec32x2ToVecI64x2: + o << U32LEB(BinaryConsts::I64x2LoadExtUVec32x2); break; - case Load32ZeroVec128: + case Load32Zero: o << U32LEB(BinaryConsts::V128Load32Zero); break; - case Load64ZeroVec128: + case Load64Zero: o << U32LEB(BinaryConsts::V128Load64Zero); break; } @@ -665,28 +664,28 @@ void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { o << int8_t(BinaryConsts::SIMDPrefix); switch (curr->op) { - case Load8LaneVec128: + case LoadLaneVec8x16: o << U32LEB(BinaryConsts::V128Load8Lane); break; - case Load16LaneVec128: + case LoadLaneVec16x8: o << U32LEB(BinaryConsts::V128Load16Lane); break; - case Load32LaneVec128: + case LoadLaneVec32x4: o << U32LEB(BinaryConsts::V128Load32Lane); break; - case Load64LaneVec128: + case LoadLaneVec64x2: o << U32LEB(BinaryConsts::V128Load64Lane); break; - case Store8LaneVec128: + case StoreLaneVec8x16: o << U32LEB(BinaryConsts::V128Store8Lane); break; - case Store16LaneVec128: + case StoreLaneVec16x8: o << U32LEB(BinaryConsts::V128Store16Lane); break; - case Store32LaneVec128: + case StoreLaneVec32x4: o << U32LEB(BinaryConsts::V128Store32Lane); break; - case Store64LaneVec128: + case StoreLaneVec64x2: o << U32LEB(BinaryConsts::V128Store64Lane); break; } @@ -695,6 +694,20 @@ o << curr->index; } +void BinaryInstWriter::visitPrefetch(Prefetch* curr) { + o << int8_t(BinaryConsts::SIMDPrefix); + switch (curr->op) { + case PrefetchTemporal: + o << U32LEB(BinaryConsts::PrefetchT); + break; + case PrefetchNontemporal: + o << U32LEB(BinaryConsts::PrefetchNT); + break; + } + assert(curr->align); + emitMemoryAccess(curr->align, /*(unused) bytes=*/0, curr->offset); +} + void BinaryInstWriter::visitMemoryInit(MemoryInit* curr) { o << int8_t(BinaryConsts::MiscPrefix); o << U32LEB(BinaryConsts::MemoryInit); @@ -746,10 +759,11 @@ break; } case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -967,16 +981,16 @@ case NotVec128: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Not); break; - case AnyTrueVec128: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::V128AnyTrue); - break; case AbsVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Abs); break; case NegVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Neg); break; + case AnyTrueVecI8x16: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I8x16AnyTrue); + break; case AllTrueVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16AllTrue); @@ -995,6 +1009,10 @@ case NegVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I16x8Neg); break; + case AnyTrueVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8AnyTrue); + break; case AllTrueVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I16x8AllTrue); @@ -1009,6 +1027,10 @@ case NegVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4Neg); break; + case AnyTrueVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4AnyTrue); + break; case AllTrueVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4AllTrue); @@ -1017,16 +1039,9 @@ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4Bitmask); break; - case AbsVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Abs); - break; case NegVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Neg); break; - case AllTrueVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2AllTrue); - break; case BitmaskVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Bitmask); @@ -1077,123 +1092,99 @@ break; case ExtAddPairwiseSVecI8x16ToI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtaddPairwiseI8x16S); + << U32LEB(BinaryConsts::I16x8ExtAddPairWiseSI8x16); break; case ExtAddPairwiseUVecI8x16ToI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtaddPairwiseI8x16U); + << U32LEB(BinaryConsts::I16x8ExtAddPairWiseUI8x16); break; case ExtAddPairwiseSVecI16x8ToI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtaddPairwiseI16x8S); + << U32LEB(BinaryConsts::I32x4ExtAddPairWiseSI16x8); break; case ExtAddPairwiseUVecI16x8ToI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtaddPairwiseI16x8U); + << U32LEB(BinaryConsts::I32x4ExtAddPairWiseUI16x8); break; case TruncSatSVecF32x4ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4TruncSatF32x4S); + << U32LEB(BinaryConsts::I32x4TruncSatSF32x4); break; case TruncSatUVecF32x4ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4TruncSatF32x4U); - break; - case ConvertSVecI32x4ToVecF32x4: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F32x4ConvertI32x4S); - break; - case ConvertUVecI32x4ToVecF32x4: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F32x4ConvertI32x4U); - break; - case ExtendLowSVecI8x16ToVecI16x8: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtendLowI8x16S); - break; - case ExtendHighSVecI8x16ToVecI16x8: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtendHighI8x16S); - break; - case ExtendLowUVecI8x16ToVecI16x8: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtendLowI8x16U); + << U32LEB(BinaryConsts::I32x4TruncSatUF32x4); break; - case ExtendHighUVecI8x16ToVecI16x8: + case TruncSatSVecF64x2ToVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtendHighI8x16U); + << U32LEB(BinaryConsts::I64x2TruncSatSF64x2); break; - case ExtendLowSVecI16x8ToVecI32x4: + case TruncSatUVecF64x2ToVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtendLowI16x8S); + << U32LEB(BinaryConsts::I64x2TruncSatUF64x2); break; - case ExtendHighSVecI16x8ToVecI32x4: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtendHighI16x8S); - break; - case ExtendLowUVecI16x8ToVecI32x4: + case ConvertSVecI32x4ToVecF32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtendLowI16x8U); + << U32LEB(BinaryConsts::F32x4ConvertSI32x4); break; - case ExtendHighUVecI16x8ToVecI32x4: + case ConvertUVecI32x4ToVecF32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtendHighI16x8U); + << U32LEB(BinaryConsts::F32x4ConvertUI32x4); break; - case ExtendLowSVecI32x4ToVecI64x2: + case ConvertSVecI64x2ToVecF64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtendLowI32x4S); + << U32LEB(BinaryConsts::F64x2ConvertSI64x2); break; - case ExtendHighSVecI32x4ToVecI64x2: + case ConvertUVecI64x2ToVecF64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtendHighI32x4S); + << U32LEB(BinaryConsts::F64x2ConvertUI64x2); break; - case ExtendLowUVecI32x4ToVecI64x2: + case WidenLowSVecI8x16ToVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtendLowI32x4U); + << U32LEB(BinaryConsts::I16x8WidenLowSI8x16); break; - case ExtendHighUVecI32x4ToVecI64x2: + case WidenHighSVecI8x16ToVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtendHighI32x4U); + << U32LEB(BinaryConsts::I16x8WidenHighSI8x16); break; - case ConvertLowSVecI32x4ToVecF64x2: + case WidenLowUVecI8x16ToVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F64x2ConvertLowI32x4S); + << U32LEB(BinaryConsts::I16x8WidenLowUI8x16); break; - case ConvertLowUVecI32x4ToVecF64x2: + case WidenHighUVecI8x16ToVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F64x2ConvertLowI32x4U); + << U32LEB(BinaryConsts::I16x8WidenHighUI8x16); break; - case TruncSatZeroSVecF64x2ToVecI32x4: + case WidenLowSVecI16x8ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4TruncSatF64x2SZero); + << U32LEB(BinaryConsts::I32x4WidenLowSI16x8); break; - case TruncSatZeroUVecF64x2ToVecI32x4: + case WidenHighSVecI16x8ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4TruncSatF64x2UZero); + << U32LEB(BinaryConsts::I32x4WidenHighSI16x8); break; - case DemoteZeroVecF64x2ToVecF32x4: + case WidenLowUVecI16x8ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F32x4DemoteF64x2Zero); + << U32LEB(BinaryConsts::I32x4WidenLowUI16x8); break; - case PromoteLowVecF32x4ToVecF64x2: + case WidenHighUVecI16x8ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F64x2PromoteLowF32x4); + << U32LEB(BinaryConsts::I32x4WidenHighUI16x8); break; - case RelaxedTruncSVecF32x4ToVecI32x4: + case WidenLowSVecI32x4ToVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4RelaxedTruncF32x4S); + << U32LEB(BinaryConsts::I64x2WidenLowSI32x4); break; - case RelaxedTruncUVecF32x4ToVecI32x4: + case WidenHighSVecI32x4ToVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4RelaxedTruncF32x4U); + << U32LEB(BinaryConsts::I64x2WidenHighSI32x4); break; - case RelaxedTruncZeroSVecF64x2ToVecI32x4: + case WidenLowUVecI32x4ToVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2SZero); + << U32LEB(BinaryConsts::I64x2WidenLowUI32x4); break; - case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case WidenHighUVecI32x4ToVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2UZero); + << U32LEB(BinaryConsts::I64x2WidenHighUI32x4); break; case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); @@ -1527,21 +1518,6 @@ case EqVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Eq); break; - case NeVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Ne); - break; - case LtSVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2LtS); - break; - case GtSVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2GtS); - break; - case LeSVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2LeS); - break; - case GeSVecI64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2GeS); - break; case EqVecF32x4: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Eq); break; @@ -1588,7 +1564,7 @@ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Xor); break; case AndNotVec128: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Andnot); + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128AndNot); break; case AddVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Add); @@ -1612,6 +1588,9 @@ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16SubSatU); break; + case MulVecI8x16: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16Mul); + break; case MinSVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I8x16MinS); break; @@ -1673,19 +1652,19 @@ break; case ExtMulLowSVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtmulLowI8x16S); + << U32LEB(BinaryConsts::I16x8ExtMulLowSI8x16); break; case ExtMulHighSVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtmulHighI8x16S); + << U32LEB(BinaryConsts::I16x8ExtMulHighSI8x16); break; case ExtMulLowUVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtmulLowI8x16U); + << U32LEB(BinaryConsts::I16x8ExtMulLowUI8x16); break; case ExtMulHighUVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8ExtmulHighI8x16U); + << U32LEB(BinaryConsts::I16x8ExtMulHighUI8x16); break; case AddVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4Add); @@ -1710,23 +1689,23 @@ break; case DotSVecI16x8ToVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4DotI16x8S); + << U32LEB(BinaryConsts::I32x4DotSVecI16x8); break; case ExtMulLowSVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtmulLowI16x8S); + << U32LEB(BinaryConsts::I32x4ExtMulLowSI16x8); break; case ExtMulHighSVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtmulHighI16x8S); + << U32LEB(BinaryConsts::I32x4ExtMulHighSI16x8); break; case ExtMulLowUVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtmulLowI16x8U); + << U32LEB(BinaryConsts::I32x4ExtMulLowUI16x8); break; case ExtMulHighUVecI32x4: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I32x4ExtmulHighI16x8U); + << U32LEB(BinaryConsts::I32x4ExtMulHighUI16x8); break; case AddVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Add); @@ -1739,19 +1718,19 @@ break; case ExtMulLowSVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtmulLowI32x4S); + << U32LEB(BinaryConsts::I64x2ExtMulLowSI32x4); break; case ExtMulHighSVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtmulHighI32x4S); + << U32LEB(BinaryConsts::I64x2ExtMulHighSI32x4); break; case ExtMulLowUVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtmulLowI32x4U); + << U32LEB(BinaryConsts::I64x2ExtMulLowUI32x4); break; case ExtMulHighUVecI64x2: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I64x2ExtmulHighI32x4U); + << U32LEB(BinaryConsts::I64x2ExtMulHighUI32x4); break; case AddVecF32x4: @@ -1773,10 +1752,10 @@ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Max); break; case PMinVecF32x4: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Pmin); + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4PMin); break; case PMaxVecF32x4: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Pmax); + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4PMax); break; case AddVecF64x2: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Add); @@ -1797,65 +1776,32 @@ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Max); break; case PMinVecF64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Pmin); + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2PMin); break; case PMaxVecF64x2: - o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2Pmax); + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2PMax); break; case NarrowSVecI16x8ToVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I8x16NarrowI16x8S); + << U32LEB(BinaryConsts::I8x16NarrowSI16x8); break; case NarrowUVecI16x8ToVecI8x16: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I8x16NarrowI16x8U); + << U32LEB(BinaryConsts::I8x16NarrowUI16x8); break; case NarrowSVecI32x4ToVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8NarrowI32x4S); + << U32LEB(BinaryConsts::I16x8NarrowSI32x4); break; case NarrowUVecI32x4ToVecI16x8: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8NarrowI32x4U); + << U32LEB(BinaryConsts::I16x8NarrowUI32x4); break; - case SwizzleVecI8x16: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I8x16Swizzle); - break; - - case RelaxedSwizzleVecI8x16: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I8x16RelaxedSwizzle); - break; - case RelaxedMinVecF32x4: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F32x4RelaxedMin); - break; - case RelaxedMaxVecF32x4: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F32x4RelaxedMax); - break; - case RelaxedMinVecF64x2: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F64x2RelaxedMin); - break; - case RelaxedMaxVecF64x2: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::F64x2RelaxedMax); - break; - case RelaxedQ15MulrSVecI16x8: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8RelaxedQ15MulrS); - break; - case DotI8x16I7x16SToVecI16x8: - o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8DotI8x16I7x16S); - break; - case DotI8x16I7x16UToVecI16x8: + case SwizzleVec8x16: o << int8_t(BinaryConsts::SIMDPrefix) - << U32LEB(BinaryConsts::I16x8DotI8x16I7x16U); + << U32LEB(BinaryConsts::V8x16Swizzle); break; case InvalidBinary: @@ -1894,23 +1840,8 @@ parent.writeHeapType(curr->type.getHeapType()); } -void BinaryInstWriter::visitRefIs(RefIs* curr) { - switch (curr->op) { - case RefIsNull: - o << int8_t(BinaryConsts::RefIsNull); - break; - case RefIsFunc: - o << int8_t(BinaryConsts::GCPrefix) << int8_t(BinaryConsts::RefIsFunc); - break; - case RefIsData: - o << int8_t(BinaryConsts::GCPrefix) << int8_t(BinaryConsts::RefIsData); - break; - case RefIsI31: - o << int8_t(BinaryConsts::GCPrefix) << int8_t(BinaryConsts::RefIsI31); - break; - default: - WASM_UNREACHABLE("unimplemented ref.is_*"); - } +void BinaryInstWriter::visitRefIsNull(RefIsNull* curr) { + o << int8_t(BinaryConsts::RefIsNull); } void BinaryInstWriter::visitRefFunc(RefFunc* curr) { @@ -1922,63 +1853,33 @@ o << int8_t(BinaryConsts::RefEq); } -void BinaryInstWriter::visitTableGet(TableGet* curr) { - o << int8_t(BinaryConsts::TableGet); - o << U32LEB(parent.getTableIndex(curr->table)); -} - -void BinaryInstWriter::visitTableSet(TableSet* curr) { - o << int8_t(BinaryConsts::TableSet); - o << U32LEB(parent.getTableIndex(curr->table)); -} - -void BinaryInstWriter::visitTableSize(TableSize* curr) { - o << int8_t(BinaryConsts::MiscPrefix) << U32LEB(BinaryConsts::TableSize); - o << U32LEB(parent.getTableIndex(curr->table)); -} - -void BinaryInstWriter::visitTableGrow(TableGrow* curr) { - o << int8_t(BinaryConsts::MiscPrefix) << U32LEB(BinaryConsts::TableGrow); - o << U32LEB(parent.getTableIndex(curr->table)); -} - void BinaryInstWriter::visitTry(Try* curr) { - breakStack.push_back(curr->name); + breakStack.emplace_back(IMPOSSIBLE_CONTINUE); o << int8_t(BinaryConsts::Try); emitResultType(curr->type); } -void BinaryInstWriter::emitCatch(Try* curr, Index i) { - if (func && !sourceMap) { - parent.writeExtraDebugLocation(curr, func, i); - } - o << int8_t(BinaryConsts::Catch) - << U32LEB(parent.getTagIndex(curr->catchTags[i])); -} - -void BinaryInstWriter::emitCatchAll(Try* curr) { - if (func && !sourceMap) { - parent.writeExtraDebugLocation(curr, func, curr->catchBodies.size()); - } - o << int8_t(BinaryConsts::CatchAll); -} - -void BinaryInstWriter::emitDelegate(Try* curr) { - // The delegate ends the scope in effect, and pops the try's name. Note that - // the getBreakIndex is intentionally after that pop, as the delegate cannot - // target its own try. +void BinaryInstWriter::emitCatch(Try* curr) { assert(!breakStack.empty()); breakStack.pop_back(); - o << int8_t(BinaryConsts::Delegate) - << U32LEB(getBreakIndex(curr->delegateTarget)); + breakStack.emplace_back(IMPOSSIBLE_CONTINUE); + if (func && !sourceMap) { + parent.writeExtraDebugLocation(curr, func, BinaryLocations::Catch); + } + o << int8_t(BinaryConsts::Catch); } void BinaryInstWriter::visitThrow(Throw* curr) { - o << int8_t(BinaryConsts::Throw) << U32LEB(parent.getTagIndex(curr->tag)); + o << int8_t(BinaryConsts::Throw) << U32LEB(parent.getEventIndex(curr->event)); } void BinaryInstWriter::visitRethrow(Rethrow* curr) { - o << int8_t(BinaryConsts::Rethrow) << U32LEB(getBreakIndex(curr->target)); + o << int8_t(BinaryConsts::Rethrow); +} + +void BinaryInstWriter::visitBrOnExn(BrOnExn* curr) { + o << int8_t(BinaryConsts::BrOnExn) << U32LEB(getBreakIndex(curr->name)) + << U32LEB(parent.getEventIndex(curr->event)); } void BinaryInstWriter::visitNop(Nop* curr) { o << int8_t(BinaryConsts::Nop); } @@ -2037,107 +1938,44 @@ } void BinaryInstWriter::visitRefTest(RefTest* curr) { - o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::RefTest); - } else { - o << U32LEB(BinaryConsts::RefTestStatic); - parent.writeIndexedHeapType(curr->intendedType); - } + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefTest); + parent.writeHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->getCastType().getHeapType()); } void BinaryInstWriter::visitRefCast(RefCast* curr) { - o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::RefCast); - } else { - if (curr->safety == RefCast::Unsafe) { - o << U32LEB(BinaryConsts::RefCastNopStatic); - } else { - o << U32LEB(BinaryConsts::RefCastStatic); - } - parent.writeIndexedHeapType(curr->intendedType); - } + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefCast); + parent.writeHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->getCastType().getHeapType()); } -void BinaryInstWriter::visitBrOn(BrOn* curr) { - switch (curr->op) { - case BrOnNull: - o << int8_t(BinaryConsts::BrOnNull); - break; - case BrOnNonNull: - o << int8_t(BinaryConsts::BrOnNonNull); - break; - case BrOnCast: - o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::BrOnCast); - } else { - o << U32LEB(BinaryConsts::BrOnCastStatic); - } - break; - case BrOnCastFail: - o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::BrOnCastFail); - } else { - o << U32LEB(BinaryConsts::BrOnCastStaticFail); - } - break; - case BrOnFunc: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnFunc); - break; - case BrOnNonFunc: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnNonFunc); - break; - case BrOnData: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnData); - break; - case BrOnNonData: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnNonData); - break; - case BrOnI31: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnI31); - break; - case BrOnNonI31: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnNonI31); - break; - default: - WASM_UNREACHABLE("invalid br_on_*"); - } - o << U32LEB(getBreakIndex(curr->name)); - if ((curr->op == BrOnCast || curr->op == BrOnCastFail) && !curr->rtt) { - parent.writeIndexedHeapType(curr->intendedType); - } +void BinaryInstWriter::visitBrOnCast(BrOnCast* curr) { + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnCast) + << U32LEB(getBreakIndex(curr->name)); + parent.writeHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->getCastType().getHeapType()); } void BinaryInstWriter::visitRttCanon(RttCanon* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttCanon); - parent.writeIndexedHeapType(curr->type.getRtt().heapType); + parent.writeHeapType(curr->type.getRtt().heapType); } void BinaryInstWriter::visitRttSub(RttSub* curr) { - o << int8_t(BinaryConsts::GCPrefix); - o << U32LEB(curr->fresh ? BinaryConsts::RttFreshSub : BinaryConsts::RttSub); - parent.writeIndexedHeapType(curr->type.getRtt().heapType); + o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttSub); + // FIXME: the binary format may also have an extra heap type and index that + // are not needed + parent.writeHeapType(curr->type.getRtt().heapType); } void BinaryInstWriter::visitStructNew(StructNew* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::StructNewDefaultWithRtt); - } else { - o << U32LEB(BinaryConsts::StructNewWithRtt); - } + if (curr->isWithDefault()) { + o << U32LEB(BinaryConsts::StructNewDefaultWithRtt); } else { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::StructNewDefault); - } else { - o << U32LEB(BinaryConsts::StructNew); - } + o << U32LEB(BinaryConsts::StructNewWithRtt); } - parent.writeIndexedHeapType(curr->type.getHeapType()); + parent.writeHeapType(curr->rtt->type.getHeapType()); } void BinaryInstWriter::visitStructGet(StructGet* curr) { @@ -2152,43 +1990,24 @@ op = BinaryConsts::StructGetU; } o << int8_t(BinaryConsts::GCPrefix) << U32LEB(op); - parent.writeIndexedHeapType(heapType); + parent.writeHeapType(heapType); o << U32LEB(curr->index); } void BinaryInstWriter::visitStructSet(StructSet* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::StructSet); - parent.writeIndexedHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->ref->type.getHeapType()); o << U32LEB(curr->index); } void BinaryInstWriter::visitArrayNew(ArrayNew* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::ArrayNewDefaultWithRtt); - } else { - o << U32LEB(BinaryConsts::ArrayNewWithRtt); - } + if (curr->isWithDefault()) { + o << U32LEB(BinaryConsts::ArrayNewDefaultWithRtt); } else { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::ArrayNewDefault); - } else { - o << U32LEB(BinaryConsts::ArrayNew); - } + o << U32LEB(BinaryConsts::ArrayNewWithRtt); } - parent.writeIndexedHeapType(curr->type.getHeapType()); -} - -void BinaryInstWriter::visitArrayInit(ArrayInit* curr) { - o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::ArrayInit); - } else { - o << U32LEB(BinaryConsts::ArrayInitStatic); - } - parent.writeIndexedHeapType(curr->type.getHeapType()); - o << U32LEB(curr->values.size()); + parent.writeHeapType(curr->rtt->type.getHeapType()); } void BinaryInstWriter::visitArrayGet(ArrayGet* curr) { @@ -2203,42 +2022,17 @@ op = BinaryConsts::ArrayGetU; } o << int8_t(BinaryConsts::GCPrefix) << U32LEB(op); - parent.writeIndexedHeapType(heapType); + parent.writeHeapType(heapType); } void BinaryInstWriter::visitArraySet(ArraySet* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArraySet); - parent.writeIndexedHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->ref->type.getHeapType()); } void BinaryInstWriter::visitArrayLen(ArrayLen* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayLen); - parent.writeIndexedHeapType(curr->ref->type.getHeapType()); -} - -void BinaryInstWriter::visitArrayCopy(ArrayCopy* curr) { - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayCopy); - parent.writeIndexedHeapType(curr->destRef->type.getHeapType()); - parent.writeIndexedHeapType(curr->srcRef->type.getHeapType()); -} - -void BinaryInstWriter::visitRefAs(RefAs* curr) { - switch (curr->op) { - case RefAsNonNull: - o << int8_t(BinaryConsts::RefAsNonNull); - break; - case RefAsFunc: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsFunc); - break; - case RefAsData: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsData); - break; - case RefAsI31: - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefAsI31); - break; - default: - WASM_UNREACHABLE("invalid ref.as_*"); - } + parent.writeHeapType(curr->ref->type.getHeapType()); } void BinaryInstWriter::emitScopeEnd(Expression* curr) { @@ -2283,41 +2077,34 @@ } for (auto type : func->vars) { for (const auto& t : type) { - noteLocalType(t); + numLocalsByType[t]++; } } countScratchLocals(); - std::unordered_map currLocalsByType; + std::map currLocalsByType; for (Index i = func->getVarIndexBase(); i < func->getNumLocals(); i++) { Index j = 0; for (const auto& type : func->getLocalType(i)) { auto fullIndex = std::make_pair(i, j++); Index index = func->getVarIndexBase(); - for (auto& localType : localTypes) { - if (type == localType) { - mappedLocals[fullIndex] = index + currLocalsByType[localType]; + for (auto& typeCount : numLocalsByType) { + if (type == typeCount.first) { + mappedLocals[fullIndex] = index + currLocalsByType[typeCount.first]; currLocalsByType[type]++; break; } - index += numLocalsByType.at(localType); + index += typeCount.second; } } } setScratchLocals(); o << U32LEB(numLocalsByType.size()); - for (auto& localType : localTypes) { - o << U32LEB(numLocalsByType.at(localType)); - parent.writeType(localType); + for (auto& typeCount : numLocalsByType) { + o << U32LEB(typeCount.second); + parent.writeType(typeCount.first); } } -void BinaryInstWriter::noteLocalType(Type type) { - if (!numLocalsByType.count(type)) { - localTypes.push_back(type); - } - numLocalsByType[type]++; -} - void BinaryInstWriter::countScratchLocals() { // Add a scratch register in `numLocalsByType` for each type of // tuple.extract with nonzero index present. @@ -2327,17 +2114,17 @@ scratchLocals[extract->type] = 0; } } - for (auto& [type, _] : scratchLocals) { - noteLocalType(type); + for (auto t : scratchLocals) { + numLocalsByType[t.first]++; } } void BinaryInstWriter::setScratchLocals() { Index index = func->getVarIndexBase(); - for (auto& localType : localTypes) { - index += numLocalsByType[localType]; - if (scratchLocals.find(localType) != scratchLocals.end()) { - scratchLocals[localType] = index - 1; + for (auto& typeCount : numLocalsByType) { + index += typeCount.second; + if (scratchLocals.find(typeCount.first) != scratchLocals.end()) { + scratchLocals[typeCount.first] = index - 1; } } } @@ -2350,9 +2137,6 @@ } int32_t BinaryInstWriter::getBreakIndex(Name name) { // -1 if not found - if (name == DELEGATE_CALLER_TARGET) { - return breakStack.size(); - } for (int i = breakStack.size() - 1; i >= 0; i--) { if (breakStack[i] == name) { return breakStack.size() - 1 - i; @@ -2420,29 +2204,23 @@ void StackIRToBinaryWriter::write() { writer.mapLocalsAndEmitHeader(); - // Stack to track indices of catches within a try - SmallVector catchIndexStack; for (auto* inst : *func->stackIR) { if (!inst) { continue; // a nullptr is just something we can skip } switch (inst->op) { - case StackInst::TryBegin: - catchIndexStack.push_back(0); - [[fallthrough]]; case StackInst::Basic: case StackInst::BlockBegin: case StackInst::IfBegin: - case StackInst::LoopBegin: { + case StackInst::LoopBegin: + case StackInst::TryBegin: { writer.visit(inst->origin); break; } - case StackInst::TryEnd: - catchIndexStack.pop_back(); - [[fallthrough]]; case StackInst::BlockEnd: case StackInst::IfEnd: - case StackInst::LoopEnd: { + case StackInst::LoopEnd: + case StackInst::TryEnd: { writer.emitScopeEnd(inst->origin); break; } @@ -2451,17 +2229,7 @@ break; } case StackInst::Catch: { - writer.emitCatch(inst->origin->cast(), catchIndexStack.back()++); - break; - } - case StackInst::CatchAll: { - writer.emitCatchAll(inst->origin->cast()); - break; - } - case StackInst::Delegate: { - writer.emitDelegate(inst->origin->cast()); - // Delegates end the try, like a TryEnd. - catchIndexStack.pop_back(); + writer.emitCatch(inst->origin->cast()); break; } default: diff -Nru binaryen-108/src/wasm/wasm-type.cpp binaryen-99/src/wasm/wasm-type.cpp --- binaryen-108/src/wasm/wasm-type.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-type.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -14,49 +14,24 @@ * limitations under the License. */ -#include #include #include -#include #include #include #include #include -#include #include "compiler-support.h" #include "support/hash.h" -#include "support/insert_ordered.h" #include "wasm-features.h" -#include "wasm-type-printing.h" #include "wasm-type.h" -#define TRACE_CANONICALIZATION 0 -#define TIME_CANONICALIZATION 0 - -#if TRACE_CANONICALIZATION || TIME_CANONICALIZATION -#include -#endif - -#if TIME_CANONICALIZATION -#include -#endif - namespace wasm { -static TypeSystem typeSystem = TypeSystem::Equirecursive; - -void setTypeSystem(TypeSystem system) { typeSystem = system; } - -TypeSystem getTypeSystem() { return typeSystem; } - namespace { struct TypeInfo { using type_t = Type; - // Used in assertions to ensure that temporary types don't leak into the - // global store. - bool isTemp = false; enum Kind { TupleKind, RefKind, @@ -86,49 +61,24 @@ bool isNullable() const { return kind == RefKind && ref.nullable; } - // If this TypeInfo represents a Type that can be represented more simply, - // return that simpler Type. For example, this handles canonicalizing the - // TypeInfo representing (ref null any) into the BasicType anyref. It also - // handles eliminating singleton tuple types. - std::optional getCanonical() const; - bool operator==(const TypeInfo& other) const; bool operator!=(const TypeInfo& other) const { return !(*this == other); } + bool operator<(const TypeInfo& other) const; }; -using RecGroupInfo = std::vector; - struct HeapTypeInfo { using type_t = HeapType; - // Used in assertions to ensure that temporary types don't leak into the - // global store. - bool isTemp = false; - // If `isFinalized`, then hashing and equality are performed on the finite - // shape of the type definition tree rooted at the HeapTypeInfo. - // Otherwise, the type definition tree is still being constructed via the - // TypeBuilder interface, so hashing and equality use pointer identity. - bool isFinalized = true; - // In nominal or isorecursive mode, the supertype of this HeapType, if it - // exists. - HeapTypeInfo* supertype = nullptr; - // In isorecursive mode, the recursion group of this type or null if the - // recursion group is trivial (i.e. contains only this type). - RecGroupInfo* recGroup = nullptr; - size_t recGroupIndex = 0; enum Kind { - BasicKind, SignatureKind, StructKind, ArrayKind, } kind; union { - HeapType::BasicHeapType basic; Signature signature; Struct struct_; Array array; }; - HeapTypeInfo(HeapType::BasicHeapType basic) : kind(BasicKind), basic(basic) {} HeapTypeInfo(Signature sig) : kind(SignatureKind), signature(sig) {} HeapTypeInfo(const Struct& struct_) : kind(StructKind), struct_(struct_) {} HeapTypeInfo(Struct&& struct_) @@ -140,358 +90,11 @@ constexpr bool isSignature() const { return kind == SignatureKind; } constexpr bool isStruct() const { return kind == StructKind; } constexpr bool isArray() const { return kind == ArrayKind; } - constexpr bool isData() const { return isStruct() || isArray(); } - - // If this HeapTypeInfo represents a HeapType that can be represented more - // simply, return that simpler HeapType. This handles turning BasicKind - // HeapTypes into their corresponding BasicHeapTypes. - std::optional getCanonical() const; HeapTypeInfo& operator=(const HeapTypeInfo& other); bool operator==(const HeapTypeInfo& other) const; bool operator!=(const HeapTypeInfo& other) const { return !(*this == other); } -}; - -// Helper for coinductively checking whether a pair of Types or HeapTypes are in -// a subtype relation. -struct SubTyper { - // Set of HeapTypes we are assuming are equivalent as long as we cannot prove - // otherwise. - std::unordered_set> seen; - bool isSubType(Type a, Type b); - bool isSubType(HeapType a, HeapType b); - bool isSubType(const Tuple& a, const Tuple& b); - bool isSubType(const Field& a, const Field& b); - bool isSubType(const Signature& a, const Signature& b); - bool isSubType(const Struct& a, const Struct& b); - bool isSubType(const Array& a, const Array& b); - bool isSubType(const Rtt& a, const Rtt& b); -}; - -// Helper for finding the equirecursive least upper bound of two types. -struct TypeBounder { - TypeBuilder builder; - // The indices in `builder` at which the LUB of each pair of HeapTypes are - // being constructed. - std::unordered_map, size_t> indices; - - bool hasLeastUpperBound(Type a, Type b); - Type getLeastUpperBound(Type a, Type b); - HeapType getLeastUpperBound(HeapType a, HeapType b); - -private: - // Return the LUB iff a LUB was found. The HeapType and Struct overloads are - // exceptional because they are infallible; HeapType::any is an upper bound of - // all HeapTypes and the empty struct is an upper bound of all struct types. - // Note that these methods can return temporary types, so they should never be - // used directly. - std::optional lub(Type a, Type b); - HeapType lub(HeapType a, HeapType b); - HeapType::BasicHeapType lub(HeapType::BasicHeapType a, - HeapType::BasicHeapType b); - std::optional lub(const Tuple& a, const Tuple& b); - std::optional lub(const Field& a, const Field& b); - std::optional lub(const Signature& a, const Signature& b); - Struct lub(const Struct& a, const Struct& b); - std::optional lub(const Array& a, const Array& b); - std::optional lub(const Rtt& a, const Rtt& b); -}; - -// Helper for printing types. -struct TypePrinter { - // Whether to print explicit supertypes. - bool printSupertypes; - - // The stream we are printing to. - std::ostream& os; - - // The default generator state if no other generator is provided. - std::optional defaultGenerator; - - // The function we call to get HeapType names. - HeapTypeNameGenerator generator; - - TypePrinter(std::ostream& os, HeapTypeNameGenerator generator) - : printSupertypes(getTypeSystem() != TypeSystem::Equirecursive), os(os), - defaultGenerator(), generator(generator) {} - TypePrinter(std::ostream& os) - : TypePrinter( - os, [&](HeapType type) { return defaultGenerator->getNames(type); }) { - defaultGenerator = DefaultTypeNameGenerator{}; - } - - void printHeapTypeName(HeapType type); - void printSupertypeOr(std::optional super, std::string other); - - std::ostream& print(Type type); - std::ostream& print(HeapType type); - std::ostream& print(const Tuple& tuple); - std::ostream& print(const Field& field); - std::ostream& print(const Signature& sig, - std::optional super = std::nullopt); - std::ostream& print(const Struct& struct_, - std::optional super = std::nullopt); - std::ostream& print(const Array& array, - std::optional super = std::nullopt); - std::ostream& print(const Rtt& rtt); -}; - -// Helper for hashing the shapes of TypeInfos and HeapTypeInfos. Keeps track of -// previously seen HeapTypes to avoid traversing them more than once. Infos -// referring to different type IDs but sharing a finite shape will compare and -// hash the same. -struct FiniteShapeHasher { - bool topLevelOnly; - size_t currDepth = 0; - size_t currStep = 0; - std::unordered_map seen; - - FiniteShapeHasher(bool topLevelOnly = false) : topLevelOnly(topLevelOnly) {} - - size_t hash(Type type); - size_t hash(HeapType heapType); - size_t hash(const TypeInfo& info); - size_t hash(const HeapTypeInfo& info); - size_t hash(const Tuple& tuple); - size_t hash(const Field& field); - size_t hash(const Signature& sig); - size_t hash(const Struct& struct_); - size_t hash(const Array& array); - size_t hash(const Rtt& rtt); -}; - -// Helper for comparing the shapes of TypeInfos and HeapTypeInfos for equality. -// Like FiniteShapeHasher, keeps track of previously seen HeapTypes. Note that -// this does not test for coinductive equality of the infinite expansion of the -// type tree, but rather tests for equality of the finite shape of the graph. If -// FiniteShapeEquator reports that two type shapes are equal, FiniteShapeHasher -// should produce the same hash for them. -struct FiniteShapeEquator { - bool topLevelOnly; - size_t currDepth = 0; - size_t currStep = 0; - std::unordered_map seenA, seenB; - - FiniteShapeEquator(bool topLevelOnly = false) : topLevelOnly(topLevelOnly) {} - - bool eq(Type a, Type b); - bool eq(HeapType a, HeapType b); - bool eq(const TypeInfo& a, const TypeInfo& b); - bool eq(const HeapTypeInfo& a, const HeapTypeInfo& b); - bool eq(const Tuple& a, const Tuple& b); - bool eq(const Field& a, const Field& b); - bool eq(const Signature& a, const Signature& b); - bool eq(const Struct& a, const Struct& b); - bool eq(const Array& a, const Array& b); - bool eq(const Rtt& a, const Rtt& b); -}; - -struct RecGroupHasher { - // `group` may or may not be canonical, but any other recursion group it - // reaches must be canonical. - RecGroup group; - - RecGroupHasher(RecGroup group) : group(group) {} - - // Perform the hash. - size_t operator()() const; - - // `topLevelHash` is applied to the top-level group members and observes their - // structure, while `hash(HeapType)` is applied to the children of group - // members and does not observe their structure. - size_t topLevelHash(HeapType type) const; - size_t hash(Type type) const; - size_t hash(HeapType type) const; - size_t hash(const TypeInfo& info) const; - size_t hash(const HeapTypeInfo& info) const; - size_t hash(const Tuple& tuple) const; - size_t hash(const Field& field) const; - size_t hash(const Signature& sig) const; - size_t hash(const Struct& struct_) const; - size_t hash(const Array& array) const; - size_t hash(const Rtt& rtt) const; -}; - -struct RecGroupEquator { - // `newGroup` may or may not be canonical, but `otherGroup` and any other - // recursion group reachable by either of them must be canonical. - RecGroup newGroup, otherGroup; - - RecGroupEquator(RecGroup newGroup, RecGroup otherGroup) - : newGroup(newGroup), otherGroup(otherGroup) {} - - // Perform the comparison. - bool operator()() const; - - // `topLevelEq` is applied to the top-level group members and observes their - // structure, while `eq(HeapType)` is applied to the children of group members - // and does not observe their structure. - bool topLevelEq(HeapType a, HeapType b) const; - bool eq(Type a, Type b) const; - bool eq(HeapType a, HeapType b) const; - bool eq(const TypeInfo& a, const TypeInfo& b) const; - bool eq(const HeapTypeInfo& a, const HeapTypeInfo& b) const; - bool eq(const Tuple& a, const Tuple& b) const; - bool eq(const Field& a, const Field& b) const; - bool eq(const Signature& a, const Signature& b) const; - bool eq(const Struct& a, const Struct& b) const; - bool eq(const Array& a, const Array& b) const; - bool eq(const Rtt& a, const Rtt& b) const; -}; - -// A wrapper around a RecGroup that provides equality and hashing based on the -// structure of the group such that isorecursively equivalent recursion groups -// will compare equal and will have the same hash. Assumes that all recursion -// groups reachable from this one have been canonicalized, except for the -// wrapped group itself. -struct RecGroupStructure { - RecGroup group; - bool operator==(const RecGroupStructure& other) const { - return RecGroupEquator{group, other.group}(); - } -}; - -} // anonymous namespace -} // namespace wasm - -namespace std { - -template<> class hash { -public: - size_t operator()(const wasm::RecGroupStructure& structure) const { - return wasm::RecGroupHasher{structure.group}(); - } -}; - -} // namespace std - -namespace wasm { -namespace { - -// Generic utility for traversing type graphs. The inserted roots must live as -// long as the Walker because they are referenced by address. This base class -// only has logic for traversing type graphs; figuring out when to stop -// traversing the graph and doing useful work during the traversal is left to -// subclasses. -template struct TypeGraphWalkerBase { - void walkRoot(Type* type); - void walkRoot(HeapType* ht); - - // Override these in subclasses to do useful work. - void preVisitType(Type* type) {} - void preVisitHeapType(HeapType* ht) {} - void postVisitType(Type* type) {} - void postVisitHeapType(HeapType* ht) {} - - // This base walker does not know when to stop scanning, so at least one of - // these needs to be overridden with a method that calls the base scanning - // method only if some end condition isn't met. - void scanType(Type* type); - void scanHeapType(HeapType* ht); - -private: - struct Task { - enum Kind { - PreType, - PreHeapType, - ScanType, - ScanHeapType, - PostType, - PostHeapType, - } kind; - union { - Type* type; - HeapType* heapType; - }; - static Task preVisit(Type* type) { return Task(type, PreType); } - static Task preVisit(HeapType* ht) { return Task(ht, PreHeapType); } - static Task scan(Type* type) { return Task(type, ScanType); } - static Task scan(HeapType* ht) { return Task(ht, ScanHeapType); } - static Task postVisit(Type* type) { return Task(type, PostType); } - static Task postVisit(HeapType* ht) { return Task(ht, PostHeapType); } - - private: - Task(Type* type, Kind kind) : kind(kind), type(type) {} - Task(HeapType* ht, Kind kind) : kind(kind), heapType(ht) {} - }; - - void doWalk(); - - std::vector taskList; - void push(Type* type); - void push(HeapType* type); - - Self& self() { return *static_cast(this); } -}; - -// A type graph walker base class that still does no useful work, but at least -// knows to scan each HeapType only once. -template struct HeapTypeGraphWalker : TypeGraphWalkerBase { - // Override this. - void noteHeapType(HeapType ht) {} - - void scanHeapType(HeapType* ht) { - if (scanned.insert(*ht).second) { - static_cast(this)->noteHeapType(*ht); - TypeGraphWalkerBase::scanHeapType(ht); - } - } - -private: - std::unordered_set scanned; -}; - -// A type graph walker base class that still does no useful work, but at least -// knows to scan each HeapType and Type only once. -template struct TypeGraphWalker : TypeGraphWalkerBase { - // Override these. - void noteType(Type type) {} - void noteHeapType(HeapType ht) {} - - void scanType(Type* type) { - if (scannedTypes.insert(*type).second) { - static_cast(this)->noteType(*type); - TypeGraphWalkerBase::scanType(type); - } - } - void scanHeapType(HeapType* ht) { - if (scannedHeapTypes.insert(*ht).second) { - static_cast(this)->noteHeapType(*ht); - TypeGraphWalkerBase::scanHeapType(ht); - } - } - -private: - std::unordered_set scannedHeapTypes; - std::unordered_set scannedTypes; -}; - -// A type graph walker that only traverses the direct HeapType children of the -// root, looking through child Types. What to do with each child is left to -// subclasses. -template struct HeapTypeChildWalker : HeapTypeGraphWalker { - // Override this. - void noteChild(HeapType* child) {} - - void scanType(Type* type) { - isTopLevel = false; - HeapTypeGraphWalker::scanType(type); - } - void scanHeapType(HeapType* ht) { - if (isTopLevel) { - HeapTypeGraphWalker::scanHeapType(ht); - } else { - static_cast(this)->noteChild(ht); - } - } - -private: - bool isTopLevel = true; -}; - -struct HeapTypeChildCollector : HeapTypeChildWalker { - std::vector children; - void noteChild(HeapType* child) { children.push_back(*child); } + bool operator<(const HeapTypeInfo& other) const; }; } // anonymous namespace @@ -501,27 +104,12 @@ template<> class hash { public: - size_t operator()(const wasm::TypeInfo& info) const; + size_t operator()(const wasm::TypeInfo&) const; }; template<> class hash { public: - size_t operator()(const wasm::HeapTypeInfo& info) const; -}; - -template class hash> { -public: - size_t operator()(const reference_wrapper& ref) const { - return hash{}(ref.get()); - } -}; - -template class equal_to> { -public: - bool operator()(const reference_wrapper& a, - const reference_wrapper& b) const { - return equal_to{}(a.get(), b.get()); - } + size_t operator()(const wasm::HeapTypeInfo&) const; }; } // namespace std @@ -530,58 +118,15 @@ namespace { TypeInfo* getTypeInfo(Type type) { - assert(!type.isBasic()); + assert(type.isCompound()); return (TypeInfo*)type.getID(); } HeapTypeInfo* getHeapTypeInfo(HeapType ht) { - assert(!ht.isBasic()); + assert(ht.isCompound()); return (HeapTypeInfo*)ht.getID(); } -HeapType asHeapType(std::unique_ptr& info) { - return HeapType(uintptr_t(info.get())); -} - -Type markTemp(Type type) { - if (!type.isBasic()) { - getTypeInfo(type)->isTemp = true; - } - return type; -} - -bool isTemp(Type type) { return !type.isBasic() && getTypeInfo(type)->isTemp; } - -bool isTemp(HeapType type) { - return !type.isBasic() && getHeapTypeInfo(type)->isTemp; -} - -// Given a Type that may or may not be backed by the simplest possible -// representation, return the equivalent type that is definitely backed by the -// simplest possible representation. -Type asCanonical(Type type) { - if (type.isBasic()) { - return type; - } else if (auto canon = getTypeInfo(type)->getCanonical()) { - return *canon; - } else { - return type; - } -} - -// Given a HeapType that may or may not be backed by the simplest possible -// representation, return the equivalent type that is definitely backed by the -// simplest possible representation. -HeapType asCanonical(HeapType type) { - if (type.isBasic()) { - return type; - } else if (auto canon = getHeapTypeInfo(type)->getCanonical()) { - return *canon; - } else { - return type; - } -} - TypeInfo::TypeInfo(const TypeInfo& other) { kind = other.kind; switch (kind) { @@ -613,43 +158,6 @@ WASM_UNREACHABLE("unexpected kind"); } -std::optional TypeInfo::getCanonical() const { - if (isTuple()) { - if (tuple.types.size() == 0) { - return Type::none; - } - if (tuple.types.size() == 1) { - return tuple.types[0]; - } - } - if (isRef()) { - HeapType basic = asCanonical(ref.heapType); - if (basic.isBasic()) { - if (ref.nullable) { - switch (basic.getBasic()) { - case HeapType::func: - return Type::funcref; - case HeapType::any: - return Type::anyref; - case HeapType::eq: - return Type::eqref; - case HeapType::i31: - case HeapType::data: - break; - } - } else { - if (basic == HeapType::i31) { - return Type::i31ref; - } - if (basic == HeapType::data) { - return Type::dataref; - } - } - } - } - return {}; -} - bool TypeInfo::operator==(const TypeInfo& other) const { if (kind != other.kind) { return false; @@ -658,22 +166,35 @@ case TupleKind: return tuple == other.tuple; case RefKind: - return ref.nullable == other.ref.nullable && - ref.heapType == other.ref.heapType; + return ref.heapType == other.ref.heapType && + ref.nullable == other.ref.nullable; case RttKind: return rtt == other.rtt; } WASM_UNREACHABLE("unexpected kind"); } +bool TypeInfo::operator<(const TypeInfo& other) const { + if (kind != other.kind) { + return kind < other.kind; + } + switch (kind) { + case TupleKind: + return tuple < other.tuple; + case RefKind: + if (ref.nullable != other.ref.nullable) { + return ref.nullable < other.ref.nullable; + } + return ref.heapType < other.ref.heapType; + case RttKind: + return rtt < other.rtt; + } + WASM_UNREACHABLE("unexpected kind"); +} + HeapTypeInfo::HeapTypeInfo(const HeapTypeInfo& other) { kind = other.kind; - supertype = other.supertype; - recGroup = other.recGroup; switch (kind) { - case BasicKind: - new (&basic) auto(other.basic); - return; case SignatureKind: new (&signature) auto(other.signature); return; @@ -689,8 +210,6 @@ HeapTypeInfo::~HeapTypeInfo() { switch (kind) { - case BasicKind: - return; case SignatureKind: signature.~Signature(); return; @@ -704,13 +223,6 @@ WASM_UNREACHABLE("unexpected kind"); } -std::optional HeapTypeInfo::getCanonical() const { - if (isFinalized && kind == BasicKind) { - return basic; - } - return {}; -} - HeapTypeInfo& HeapTypeInfo::operator=(const HeapTypeInfo& other) { if (&other != this) { this->~HeapTypeInfo(); @@ -720,227 +232,130 @@ } bool HeapTypeInfo::operator==(const HeapTypeInfo& other) const { - return FiniteShapeEquator().eq(*this, other); + if (kind != other.kind) { + return false; + } + switch (kind) { + case SignatureKind: + return signature == other.signature; + case StructKind: + return struct_ == other.struct_; + case ArrayKind: + return array == other.array; + } + WASM_UNREACHABLE("unexpected kind"); +} + +bool HeapTypeInfo::operator<(const HeapTypeInfo& other) const { + if (kind != other.kind) { + return kind < other.kind; + } + switch (kind) { + case SignatureKind: + return signature < other.signature; + case StructKind: + return struct_ < other.struct_; + case ArrayKind: + return array < other.array; + } + WASM_UNREACHABLE("unexpected kind"); } template struct Store { - std::recursive_mutex mutex; + std::mutex mutex; // Track unique_ptrs for constructed types to avoid leaks. std::vector> constructedTypes; // Maps from constructed types to their canonical Type IDs. - std::unordered_map, uintptr_t> typeIDs; + std::unordered_map typeIDs; -#ifndef NDEBUG - bool isGlobalStore(); -#endif - - typename Info::type_t insert(const Info& info) { return doInsert(info); } - typename Info::type_t insert(std::unique_ptr&& info) { - return doInsert(info); - } - bool hasCanonical(const Info& info, typename Info::type_t& canonical); - - void clear() { - typeIDs.clear(); - constructedTypes.clear(); - } - -private: - template typename Info::type_t doInsert(Ref& infoRef) { - const Info& info = [&]() { - if constexpr (std::is_same_v) { - return infoRef; - } else if constexpr (std::is_same_v>) { - infoRef->isTemp = false; - return *infoRef; - } - }(); + typename Info::type_t canonicalize(const Info& info) { + std::lock_guard lock(mutex); + auto indexIt = typeIDs.find(info); + if (indexIt != typeIDs.end()) { + return typename Info::type_t(indexIt->second); + } + auto ptr = std::make_unique(info); + auto id = uintptr_t(ptr.get()); + constructedTypes.push_back(std::move(ptr)); + assert(id > Info::type_t::_last_basic_type); + typeIDs[info] = id; + return typename Info::type_t(id); + } +}; - auto getPtr = [&]() -> std::unique_ptr { - if constexpr (std::is_same_v) { - return std::make_unique(infoRef); - } else if constexpr (std::is_same_v>) { - return std::move(infoRef); +struct TypeStore : Store { + Type canonicalize(TypeInfo info) { + if (info.isTuple()) { + if (info.tuple.types.size() == 0) { + return Type::none; } - }; - - auto insertNew = [&]() { - assert((!isGlobalStore() || !info.isTemp) && "Leaking temporary type!"); - auto ptr = getPtr(); - TypeID id = uintptr_t(ptr.get()); - assert(id > Info::type_t::_last_basic_type); - typeIDs.insert({*ptr, id}); - constructedTypes.emplace_back(std::move(ptr)); - return typename Info::type_t(id); - }; - - // Turn e.g. (ref null any) into anyref. - if (auto canonical = info.getCanonical()) { - return *canonical; - } - std::lock_guard lock(mutex); - // Nominal HeapTypes are always unique, so don't bother deduplicating them. - if constexpr (std::is_same_v) { - if (typeSystem == TypeSystem::Nominal) { - return insertNew(); + if (info.tuple.types.size() == 1) { + return info.tuple.types[0]; } } - // Check whether we already have a type for this structural Info. - auto indexIt = typeIDs.find(std::cref(info)); - if (indexIt != typeIDs.end()) { - return typename Info::type_t(indexIt->second); + if (info.isRef() && info.ref.heapType.isBasic()) { + if (info.ref.nullable) { + switch (info.ref.heapType.getBasic()) { + case HeapType::func: + return Type::funcref; + case HeapType::ext: + return Type::externref; + case HeapType::exn: + return Type::exnref; + case HeapType::any: + return Type::anyref; + case HeapType::eq: + return Type::eqref; + case HeapType::i31: + break; + } + } else { + if (info.ref.heapType == HeapType::i31) { + return Type::i31ref; + } + } } - // We do not have a type for this Info already. Create one. - return insertNew(); + return Store::canonicalize(info); } }; -using TypeStore = Store; using HeapTypeStore = Store; -static TypeStore globalTypeStore; -static HeapTypeStore globalHeapTypeStore; +TypeStore globalTypeStore; +HeapTypeStore globalHeapTypeStore; // Specialized to simplify programming generically over Types and HeapTypes. template struct MetaTypeInfo {}; template<> struct MetaTypeInfo { -#ifndef NDEBUG constexpr static TypeStore& globalStore = globalTypeStore; -#endif static TypeInfo* getInfo(Type type) { return getTypeInfo(type); } }; template<> struct MetaTypeInfo { -#ifndef NDEBUG constexpr static HeapTypeStore& globalStore = globalHeapTypeStore; -#endif static HeapTypeInfo* getInfo(HeapType ht) { return getHeapTypeInfo(ht); } }; -#ifndef NDEBUG -template bool Store::isGlobalStore() { - return this == &MetaTypeInfo::globalStore; -} -#endif - -// Cache canonical nominal signature types. See comment in -// `HeapType::HeapType(Signature)`. -struct SignatureTypeCache { - std::unordered_map cache; - std::mutex mutex; - - HeapType getType(Signature sig) { - std::lock_guard lock(mutex); - // Try inserting a placeholder type, then replace it with a real type if we - // don't already have a canonical type for this signature. - auto [entry, inserted] = cache.insert({sig, {}}); - auto& [_, type] = *entry; - if (inserted) { - type = globalHeapTypeStore.insert(sig); - } - return type; - } - - void insertType(HeapType type) { - std::lock_guard lock(mutex); - cache.insert({type.getSignature(), type}); - } - - void clear() { cache.clear(); } -}; - -static SignatureTypeCache nominalSignatureCache; - -// Keep track of the constructed recursion groups. -struct RecGroupStore { - std::mutex mutex; - // Store the structures of all rec groups created so far so we can avoid - // creating duplicates. - std::unordered_set canonicalGroups; - // Keep the `RecGroupInfos` for the nontrivial groups stored in - // `canonicalGroups` alive. - std::vector> builtGroups; - - RecGroup insert(RecGroup group) { - RecGroupStructure structure{group}; - auto [it, inserted] = canonicalGroups.insert(structure); - if (inserted) { - return group; - } else { - return it->group; - } - } - - RecGroup insert(std::unique_ptr&& info) { - RecGroup group{uintptr_t(info.get())}; - auto canonical = insert(group); - if (canonical == group) { - builtGroups.emplace_back(std::move(info)); - } - return canonical; - } - - // Utility for canonicalizing HeapTypes with trivial recursion groups. - HeapType insert(std::unique_ptr&& info) { - std::lock_guard lock(mutex); - assert(!info->recGroup && "Unexpected nontrivial rec group"); - auto group = asHeapType(info).getRecGroup(); - auto canonical = insert(group); - if (group == canonical) { - globalHeapTypeStore.insert(std::move(info)); - } - return canonical[0]; - } - - void clear() { - canonicalGroups.clear(); - builtGroups.clear(); - } -}; - -static RecGroupStore globalRecGroupStore; - } // anonymous namespace -void destroyAllTypesForTestingPurposesOnly() { - globalTypeStore.clear(); - globalHeapTypeStore.clear(); - nominalSignatureCache.clear(); - globalRecGroupStore.clear(); -} - Type::Type(std::initializer_list types) : Type(Tuple(types)) {} Type::Type(const Tuple& tuple) { -#ifndef NDEBUG - for (auto type : tuple.types) { - assert(!isTemp(type) && "Leaking temporary type!"); - } -#endif - new (this) Type(globalTypeStore.insert(tuple)); + new (this) Type(globalTypeStore.canonicalize(tuple)); } Type::Type(Tuple&& tuple) { -#ifndef NDEBUG - for (auto type : tuple.types) { - assert(!isTemp(type) && "Leaking temporary type!"); - } -#endif - new (this) Type(globalTypeStore.insert(std::move(tuple))); + new (this) Type(globalTypeStore.canonicalize(std::move(tuple))); } Type::Type(HeapType heapType, Nullability nullable) { - assert(!isTemp(heapType) && "Leaking temporary type!"); - new (this) Type(globalTypeStore.insert(TypeInfo(heapType, nullable))); + new (this) Type(globalTypeStore.canonicalize(TypeInfo(heapType, nullable))); } -Type::Type(Rtt rtt) { - assert(!isTemp(rtt.heapType) && "Leaking temporary type!"); - new (this) Type(globalTypeStore.insert(rtt)); -} +Type::Type(Rtt rtt) { new (this) Type(globalTypeStore.canonicalize(rtt)); } bool Type::isTuple() const { if (isBasic()) { @@ -952,7 +367,7 @@ bool Type::isRef() const { if (isBasic()) { - return id >= funcref && id <= _last_basic_type; + return id >= funcref && id <= i31ref; } else { return getTypeInfo(*this)->isRef(); } @@ -967,31 +382,23 @@ } } -bool Type::isData() const { +bool Type::isException() const { if (isBasic()) { - return id == dataref; + return id == exnref; } else { auto* info = getTypeInfo(*this); - return info->isRef() && info->ref.heapType.isData(); + return info->isRef() && info->ref.heapType == HeapType::exn; } } bool Type::isNullable() const { if (isBasic()) { - return id >= funcref && id <= eqref; // except i31ref and dataref + return id >= funcref && id <= eqref; // except i31ref } else { return getTypeInfo(*this)->isNullable(); } } -bool Type::isNonNullable() const { - if (isRef()) { - return !isNullable(); - } else { - return false; - } -} - bool Type::isRtt() const { if (isBasic()) { return false; @@ -1004,36 +411,21 @@ bool Type::isArray() const { return isRef() && getHeapType().isArray(); } -bool Type::isDefaultable() const { - // A variable can get a default value if its type is concrete (unreachable - // and none have no values, hence no default), and if it's a reference, it - // must be nullable. - if (isTuple()) { - for (auto t : *this) { - if (!t.isDefaultable()) { - return false; - } - } - return true; +bool Type::operator<(const Type& other) const { + if (*this == other) { + return false; } - return isConcrete() && !isNonNullable() && !isRtt(); -} - -bool Type::isDefaultableOrNonNullable() const { - if (isTuple()) { - for (auto t : *this) { - if (!t.isDefaultableOrNonNullable()) { - return false; - } - } + if (isBasic() && other.isBasic()) { + return getBasic() < other.getBasic(); + } + if (isBasic()) { return true; } - return isConcrete() && !isRtt(); -} - -Nullability Type::getNullability() const { - return isNullable() ? Nullable : NonNullable; -} + if (other.isBasic()) { + return false; + } + return *getTypeInfo(*this) < *getTypeInfo(other); +}; unsigned Type::getByteSize() const { // TODO: alignment? @@ -1048,10 +440,11 @@ case Type::v128: return 16; case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: break; @@ -1069,19 +462,6 @@ return getSingleByteSize(*this); } -unsigned Type::hasByteSize() const { - auto hasSingleByteSize = [](Type t) { return t.isNumber(); }; - if (isTuple()) { - for (const auto& t : *this) { - if (!hasSingleByteSize(t)) { - return false; - } - } - return true; - } - return hasSingleByteSize(*this); -} - Type Type::reinterpret() const { assert(!isTuple() && "Unexpected tuple type"); switch ((*begin()).getBasic()) { @@ -1109,9 +489,11 @@ } if (heapType.isBasic()) { switch (heapType.getBasic()) { + case HeapType::BasicHeapType::exn: + return FeatureSet::ReferenceTypes | FeatureSet::ExceptionHandling; + case HeapType::BasicHeapType::any: case HeapType::BasicHeapType::eq: case HeapType::BasicHeapType::i31: - case HeapType::BasicHeapType::data: return FeatureSet::ReferenceTypes | FeatureSet::GC; default: {} } @@ -1144,11 +526,6 @@ return getSingleFeatures(*this); } -const Tuple& Type::getTuple() const { - assert(isTuple()); - return getTypeInfo(*this)->tuple; -} - HeapType Type::getHeapType() const { if (isBasic()) { switch (getBasic()) { @@ -1162,14 +539,16 @@ break; case Type::funcref: return HeapType::func; + case Type::externref: + return HeapType::ext; + case Type::exnref: + return HeapType::exn; case Type::anyref: return HeapType::any; case Type::eqref: return HeapType::eq; case Type::i31ref: return HeapType::i31; - case Type::dataref: - return HeapType::data; } WASM_UNREACHABLE("Unexpected type"); } else { @@ -1208,34 +587,111 @@ } bool Type::isSubType(Type left, Type right) { - // As an optimization, in the common case do not even construct a SubTyper. if (left == right) { return true; } - return SubTyper().isSubType(left, right); -} - -std::vector Type::getHeapTypeChildren() { - HeapTypeChildCollector collector; - collector.walkRoot(this); - return collector.children; -} - -bool Type::hasLeastUpperBound(Type a, Type b) { - return TypeBounder().hasLeastUpperBound(a, b); + if (left.isRef() && right.isRef()) { + // Everything is a subtype of anyref. + if (right == Type::anyref) { + return true; + } + // Various things are subtypes of eqref. + auto leftHeap = left.getHeapType(); + auto rightHeap = right.getHeapType(); + if ((leftHeap == HeapType::i31 || leftHeap.isArray() || + leftHeap.isStruct()) && + rightHeap == HeapType::eq && + (!left.isNullable() || right.isNullable())) { + return true; + } + // All typed function signatures are subtypes of funcref. + if (leftHeap.isSignature() && rightHeap == HeapType::func && + (!left.isNullable() || right.isNullable())) { + return true; + } + // A non-nullable type is a supertype of a nullable one + if (leftHeap == rightHeap && !left.isNullable()) { + // The only difference is the nullability. + assert(right.isNullable()); + return true; + } + return false; + } + if (left.isTuple() && right.isTuple()) { + if (left.size() != right.size()) { + return false; + } + for (size_t i = 0; i < left.size(); ++i) { + if (!isSubType(left[i], right[i])) { + return false; + } + } + return true; + } + if (left.isRtt() && right.isRtt()) { + auto leftRtt = left.getRtt(); + auto rightRtt = right.getRtt(); + // (rtt n $x) is a subtype of (rtt $x), that is, if the only difference in + // information is that the left side specifies a depth while the right side + // allows any depth. + return leftRtt.heapType == rightRtt.heapType && leftRtt.hasDepth() && + !rightRtt.hasDepth(); + } + return false; } Type Type::getLeastUpperBound(Type a, Type b) { - return TypeBounder().getLeastUpperBound(a, b); + if (a == b) { + return a; + } + if (a == Type::unreachable) { + return b; + } + if (b == Type::unreachable) { + return a; + } + if (a.size() != b.size()) { + return Type::none; // a poison value that must not be consumed + } + if (a.isRef()) { + if (b.isRef()) { + if (a.isFunction() && b.isFunction()) { + return Type::funcref; + } + if ((a == Type::i31ref && b == Type::eqref) || + (a == Type::eqref && b == Type::i31ref)) { + return Type::eqref; + } + // The LUB of two different reference types is anyref, which may or may + // not be a valid type depending on whether the anyref feature is enabled. + // When anyref is disabled, it is possible for the finalization of invalid + // code to introduce a use of anyref via this function, but that is not a + // problem because it will be caught and rejected by validation. + return Type::anyref; + } + return Type::none; + } + if (a.isTuple()) { + TypeList types; + types.resize(a.size()); + for (size_t i = 0; i < types.size(); ++i) { + types[i] = getLeastUpperBound(a[i], b[i]); + if (types[i] == Type::none) { + return Type::none; + } + } + return Type(types); + } + return Type::none; } -size_t Type::size() const { +Type::Iterator Type::end() const { if (isTuple()) { - return getTypeInfo(*this)->tuple.types.size(); + return Iterator(this, getTypeInfo(*this)->tuple.types.size()); } else { // TODO: unreachable is special and expands to {unreachable} currently. // see also: https://github.com/WebAssembly/binaryen/issues/3062 - return size_t(id != Type::none); + return Iterator(this, size_t(id != Type::none)); } } @@ -1243,89 +699,35 @@ if (parent->isTuple()) { return getTypeInfo(*parent)->tuple.types[index]; } else { - // TODO: see comment in Type::size() + // TODO: see comment in Type::end() assert(index == 0 && parent->id != Type::none && "Index out of bounds"); return *parent; } } -HeapType::HeapType(Signature sig) { - assert(!isTemp(sig.params) && "Leaking temporary type!"); - assert(!isTemp(sig.results) && "Leaking temporary type!"); - switch (getTypeSystem()) { - case TypeSystem::Nominal: - // Special case the creation of signature types in nominal mode to return - // a "canonical" type for the signature, which happens to be the first one - // created. We depend on being able to create new function signatures in - // many places, and historically they have always been structural, so - // creating a copy of an existing signature did not result in any code - // bloat or semantic changes. To avoid regressions or significant changes - // of behavior in nominal mode, we cache the canonical heap types for each - // signature to emulate structural behavior. - new (this) HeapType(nominalSignatureCache.getType(sig)); - return; - case TypeSystem::Equirecursive: - new (this) HeapType(globalHeapTypeStore.insert(sig)); - return; - case TypeSystem::Isorecursive: - new (this) HeapType( - globalRecGroupStore.insert(std::make_unique(sig))); - return; +const Type& Type::operator[](size_t index) const { + if (isTuple()) { + return getTypeInfo(*this)->tuple.types[index]; + } else { + assert(index == 0 && "Index out of bounds"); + return *begin(); } - WASM_UNREACHABLE("unexpected type system"); +} + +HeapType::HeapType(Signature signature) { + new (this) HeapType(globalHeapTypeStore.canonicalize(signature)); } HeapType::HeapType(const Struct& struct_) { -#ifndef NDEBUG - for (const auto& field : struct_.fields) { - assert(!isTemp(field.type) && "Leaking temporary type!"); - } -#endif - switch (getTypeSystem()) { - case TypeSystem::Nominal: - case TypeSystem::Equirecursive: - new (this) HeapType(globalHeapTypeStore.insert(struct_)); - return; - case TypeSystem::Isorecursive: - new (this) HeapType( - globalRecGroupStore.insert(std::make_unique(struct_))); - return; - } - WASM_UNREACHABLE("unexpected type system"); + new (this) HeapType(globalHeapTypeStore.canonicalize(struct_)); } HeapType::HeapType(Struct&& struct_) { -#ifndef NDEBUG - for (const auto& field : struct_.fields) { - assert(!isTemp(field.type) && "Leaking temporary type!"); - } -#endif - switch (getTypeSystem()) { - case TypeSystem::Nominal: - case TypeSystem::Equirecursive: - new (this) HeapType(globalHeapTypeStore.insert(std::move(struct_))); - return; - case TypeSystem::Isorecursive: - new (this) HeapType(globalRecGroupStore.insert( - std::make_unique(std::move(struct_)))); - return; - } - WASM_UNREACHABLE("unexpected type system"); + new (this) HeapType(globalHeapTypeStore.canonicalize(std::move(struct_))); } HeapType::HeapType(Array array) { - assert(!isTemp(array.element.type) && "Leaking temporary type!"); - switch (getTypeSystem()) { - case TypeSystem::Nominal: - case TypeSystem::Equirecursive: - new (this) HeapType(globalHeapTypeStore.insert(array)); - return; - case TypeSystem::Isorecursive: - new (this) HeapType( - globalRecGroupStore.insert(std::make_unique(array))); - return; - } - WASM_UNREACHABLE("unexpected type system"); + new (this) HeapType(globalHeapTypeStore.canonicalize(array)); } bool HeapType::isFunction() const { @@ -1336,14 +738,6 @@ } } -bool HeapType::isData() const { - if (isBasic()) { - return id == data; - } else { - return getHeapTypeInfo(*this)->isData(); - } -} - bool HeapType::isSignature() const { if (isBasic()) { return false; @@ -1360,6 +754,22 @@ } } +bool HeapType::operator<(const HeapType& other) const { + if (*this == other) { + return false; + } + if (isBasic() && other.isBasic()) { + return getBasic() < other.getBasic(); + } + if (isBasic()) { + return true; + } + if (other.isBasic()) { + return false; + } + return *getHeapTypeInfo(*this) < *getHeapTypeInfo(other); +} + bool HeapType::isArray() const { if (isBasic()) { return false; @@ -1383,2538 +793,502 @@ return getHeapTypeInfo(*this)->array; } -std::optional HeapType::getSuperType() const { - if (isBasic()) { - return {}; - } - HeapTypeInfo* super = getHeapTypeInfo(*this)->supertype; - if (super != nullptr) { - return HeapType(uintptr_t(super)); - } - return {}; -} - -size_t HeapType::getDepth() const { - size_t depth = 0; - std::optional super; - for (auto curr = *this; (super = curr.getSuperType()); curr = *super) { - ++depth; - } - return depth; -} - -bool HeapType::isSubType(HeapType left, HeapType right) { - // As an optimization, in the common case do not even construct a SubTyper. - if (left == right) { - return true; +bool Signature::operator<(const Signature& other) const { + if (results != other.results) { + return results < other.results; } - return SubTyper().isSubType(left, right); -} - -std::vector HeapType::getHeapTypeChildren() const { - HeapTypeChildCollector collector; - collector.walkRoot(const_cast(this)); - return collector.children; + return params < other.params; } -std::vector HeapType::getReferencedHeapTypes() const { - auto types = getHeapTypeChildren(); - if (auto super = getSuperType()) { - types.push_back(*super); +bool Field::operator<(const Field& other) const { + if (mutable_ != other.mutable_) { + return mutable_ < other.mutable_; } - return types; -} - -HeapType HeapType::getLeastUpperBound(HeapType a, HeapType b) { - return TypeBounder().getLeastUpperBound(a, b); -} - -// Recursion groups with single elements are encoded as that single element's -// type ID with the low bit set and other recursion groups are encoded with the -// address of the vector containing their members. These encodings are disjoint -// because the alignment of the vectors is greater than 1. -static_assert(alignof(std::vector) > 1); - -RecGroup HeapType::getRecGroup() const { - assert(!isBasic()); - if (auto* info = getHeapTypeInfo(*this)->recGroup) { - return RecGroup(uintptr_t(info)); - } else { - // Mark the low bit to signify that this is a trivial recursion group and - // points to a heap type info rather than a vector of heap types. - return RecGroup(id | 1); + if (type == Type::i32 && other.type == Type::i32) { + return packedType < other.packedType; } + return type < other.type; } -size_t HeapType::getRecGroupIndex() const { - assert(!isBasic()); - return getHeapTypeInfo(*this)->recGroupIndex; -} - -HeapType RecGroup::Iterator::operator*() const { - if (parent->id & 1) { - // This is a trivial recursion group. Mask off the low bit to recover the - // single HeapType. - return {HeapType(parent->id & ~(uintptr_t)1)}; - } else { - return (*(std::vector*)parent->id)[index]; +bool Rtt::operator<(const Rtt& other) const { + if (depth != other.depth) { + return depth < other.depth; } + return heapType < other.heapType; } -size_t RecGroup::size() const { - if (id & 1) { - return 1; - } else { - return ((std::vector*)id)->size(); - } -} +namespace { -TypeNames DefaultTypeNameGenerator::getNames(HeapType type) { - auto [it, inserted] = nameCache.insert({type, {}}); - if (inserted) { - // Generate a new name for this type we have not previously seen. - std::stringstream stream; - if (type.isSignature()) { - stream << "func." << funcCount++; - } else if (type.isStruct()) { - stream << "struct." << structCount++; - } else if (type.isArray()) { - stream << "array." << arrayCount++; - } else { - WASM_UNREACHABLE("unexpected kind"); - } - it->second = {stream.str(), {}}; +std::ostream& +printPrefixedTypes(std::ostream& os, const char* prefix, Type type) { + os << '(' << prefix; + for (const auto& t : type) { + os << " " << t; } - return it->second; + os << ')'; + return os; } -template static std::string genericToString(const T& t) { +template std::string genericToString(const T& t) { std::ostringstream ss; ss << t; return ss.str(); } + +} // anonymous namespace + std::string Type::toString() const { return genericToString(*this); } -std::string HeapType::toString() const { return genericToString(*this); } + +std::string ParamType::toString() const { return genericToString(*this); } + +std::string ResultType::toString() const { return genericToString(*this); } + std::string Tuple::toString() const { return genericToString(*this); } + std::string Signature::toString() const { return genericToString(*this); } + std::string Struct::toString() const { return genericToString(*this); } + std::string Array::toString() const { return genericToString(*this); } + +std::string HeapType::toString() const { return genericToString(*this); } + std::string Rtt::toString() const { return genericToString(*this); } +std::ostream& operator<<(std::ostream&, TypeInfo); +std::ostream& operator<<(std::ostream&, HeapTypeInfo); + std::ostream& operator<<(std::ostream& os, Type type) { - return TypePrinter(os).print(type); -} -std::ostream& operator<<(std::ostream& os, Type::Printed printed) { - return TypePrinter(os, printed.generateName).print(Type(printed.typeID)); + if (type.isBasic()) { + switch (type.getBasic()) { + case Type::none: + return os << "none"; + case Type::unreachable: + return os << "unreachable"; + case Type::i32: + return os << "i32"; + case Type::i64: + return os << "i64"; + case Type::f32: + return os << "f32"; + case Type::f64: + return os << "f64"; + case Type::v128: + return os << "v128"; + case Type::funcref: + return os << "funcref"; + case Type::externref: + return os << "externref"; + case Type::exnref: + return os << "exnref"; + case Type::anyref: + return os << "anyref"; + case Type::eqref: + return os << "eqref"; + case Type::i31ref: + return os << "i31ref"; + } + } + return os << *getTypeInfo(type); } -std::ostream& operator<<(std::ostream& os, HeapType type) { - return TypePrinter(os).print(type); + +std::ostream& operator<<(std::ostream& os, ParamType param) { + return printPrefixedTypes(os, "param", param.type); } -std::ostream& operator<<(std::ostream& os, HeapType::Printed printed) { - return TypePrinter(os, printed.generateName).print(HeapType(printed.typeID)); + +std::ostream& operator<<(std::ostream& os, ResultType param) { + return printPrefixedTypes(os, "result", param.type); } + std::ostream& operator<<(std::ostream& os, Tuple tuple) { - return TypePrinter(os).print(tuple); + auto& types = tuple.types; + auto size = types.size(); + os << "("; + if (size) { + os << types[0]; + for (size_t i = 1; i < size; ++i) { + os << " " << types[i]; + } + } + return os << ")"; } + std::ostream& operator<<(std::ostream& os, Signature sig) { - return TypePrinter(os).print(sig); -} -std::ostream& operator<<(std::ostream& os, Field field) { - return TypePrinter(os).print(field); -} -std::ostream& operator<<(std::ostream& os, Struct struct_) { - return TypePrinter(os).print(struct_); -} -std::ostream& operator<<(std::ostream& os, Array array) { - return TypePrinter(os).print(array); -} -std::ostream& operator<<(std::ostream& os, Rtt rtt) { - return TypePrinter(os).print(rtt); -} -std::ostream& operator<<(std::ostream& os, TypeBuilder::ErrorReason reason) { - switch (reason) { - case TypeBuilder::ErrorReason::SelfSupertype: - return os << "Heap type is a supertype of itself"; - case TypeBuilder::ErrorReason::InvalidSupertype: - return os << "Heap type has an invalid supertype"; - case TypeBuilder::ErrorReason::ForwardSupertypeReference: - return os << "Heap type has an undeclared supertype"; - case TypeBuilder::ErrorReason::ForwardChildReference: - return os << "Heap type has an undeclared child"; - } - WASM_UNREACHABLE("Unexpected error reason"); -} - -unsigned Field::getByteSize() const { - if (type != Type::i32) { - return type.getByteSize(); - } - switch (packedType) { - case Field::PackedType::i8: - return 1; - case Field::PackedType::i16: - return 2; - case Field::PackedType::not_packed: - return 4; + os << "(func"; + if (sig.params.getID() != Type::none) { + os << " "; + printPrefixedTypes(os, "param", sig.params); + } + if (sig.results.getID() != Type::none) { + os << " "; + printPrefixedTypes(os, "result", sig.results); } - WASM_UNREACHABLE("impossible packed type"); + return os << ")"; } -namespace { - -bool SubTyper::isSubType(Type a, Type b) { - if (a == b) { - return true; - } - if (a == Type::unreachable) { - return true; +std::ostream& operator<<(std::ostream& os, Field field) { + if (field.mutable_) { + os << "(mut "; } - if (a.isRef() && b.isRef()) { - return (a.isNullable() == b.isNullable() || !a.isNullable()) && - isSubType(a.getHeapType(), b.getHeapType()); + if (field.isPacked()) { + auto packedType = field.packedType; + if (packedType == Field::PackedType::i8) { + os << "i8"; + } else if (packedType == Field::PackedType::i16) { + os << "i16"; + } else { + WASM_UNREACHABLE("unexpected packed type"); + } + } else { + os << field.type; } - if (a.isTuple() && b.isTuple()) { - return isSubType(a.getTuple(), b.getTuple()); + if (field.mutable_) { + os << ")"; } - if (a.isRtt() && b.isRtt()) { - return isSubType(a.getRtt(), b.getRtt()); + return os; +}; + +std::ostream& operator<<(std::ostream& os, Struct struct_) { + os << "(struct"; + if (struct_.fields.size()) { + os << " (field"; + for (auto f : struct_.fields) { + os << " " << f; + } + os << ")"; } - return false; + return os << ")"; } -bool SubTyper::isSubType(HeapType a, HeapType b) { - // See: - // https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md#subtyping - // https://github.com/WebAssembly/gc/blob/master/proposals/gc/MVP.md#defined-types - if (a == b) { - return true; - } - if (b.isBasic()) { - switch (b.getBasic()) { +std::ostream& operator<<(std::ostream& os, Array array) { + return os << "(array " << array.element << ")"; +} + +std::ostream& operator<<(std::ostream& os, HeapType heapType) { + if (heapType.isBasic()) { + switch (heapType.getBasic()) { case HeapType::func: - return a.isSignature(); + return os << "func"; + case HeapType::ext: + return os << "extern"; + case HeapType::exn: + return os << "exn"; case HeapType::any: - return true; + return os << "any"; case HeapType::eq: - return a == HeapType::i31 || a.isData(); + return os << "eq"; case HeapType::i31: - return false; - case HeapType::data: - return a.isData(); + return os << "i31"; } } - if (a.isBasic()) { - // Basic HeapTypes are never subtypes of compound HeapTypes. - return false; - } - if (typeSystem == TypeSystem::Nominal || - typeSystem == TypeSystem::Isorecursive) { - // Subtyping must be declared in a nominal system, not derived from - // structure, so we will not recurse. TODO: optimize this search with some - // form of caching. - HeapTypeInfo* curr = getHeapTypeInfo(a); - while ((curr = curr->supertype)) { - if (curr == getHeapTypeInfo(b)) { - return true; + return os << *getHeapTypeInfo(heapType); +} + +std::ostream& operator<<(std::ostream& os, Rtt rtt) { + return os << "(rtt " << rtt.depth << " " << rtt.heapType << ")"; +} + +std::ostream& operator<<(std::ostream& os, TypeInfo info) { + switch (info.kind) { + case TypeInfo::TupleKind: { + return os << info.tuple; + } + case TypeInfo::RefKind: { + os << "(ref "; + if (info.ref.nullable) { + os << "null "; } + return os << info.ref.heapType << ")"; + } + case TypeInfo::RttKind: { + return os << info.rtt; } - return false; - } - // As we recurse, we will coinductively assume that a == b unless proven - // otherwise. - if (!seen.insert({a, b}).second) { - // We weren't able to disprove that a == b since we last saw them, so the - // relation holds coinductively. - return true; - } - if (a.isSignature() && b.isSignature()) { - return isSubType(a.getSignature(), b.getSignature()); - } - if (a.isArray() && b.isArray()) { - return isSubType(a.getArray(), b.getArray()); - } - if (a.isStruct() && b.isStruct()) { - return isSubType(a.getStruct(), b.getStruct()); } - return false; + WASM_UNREACHABLE("unexpected kind"); } -bool SubTyper::isSubType(const Tuple& a, const Tuple& b) { - if (a.types.size() != b.types.size()) { - return false; +std::ostream& operator<<(std::ostream& os, HeapTypeInfo info) { + switch (info.kind) { + case HeapTypeInfo::SignatureKind: + return os << info.signature; + case HeapTypeInfo::StructKind: + return os << info.struct_; + case HeapTypeInfo::ArrayKind: + return os << info.array; } - for (size_t i = 0; i < a.types.size(); ++i) { - if (!isSubType(a.types[i], b.types[i])) { - return false; + WASM_UNREACHABLE("unexpected kind"); +} + +struct TypeBuilder::Impl { + TypeStore typeStore; + HeapTypeStore heapTypeStore; + + struct Entry { + // HeapTypeInfo has no default constructor, so pick an arbitrary default. + HeapTypeInfo info = Signature(); + bool initialized = false; + void set(HeapTypeInfo&& hti) { + info = hti; + initialized = true; } - } - return true; + HeapType get() { return HeapType(TypeID(&info)); } + }; + + std::vector entries; +}; + +TypeBuilder::TypeBuilder(size_t n) { + impl = std::make_unique(); + impl->entries.resize(n); } -bool SubTyper::isSubType(const Field& a, const Field& b) { - if (a == b) { - return true; - } - // Immutable fields can be subtypes. - return a.mutable_ == Immutable && b.mutable_ == Immutable && - a.packedType == b.packedType && isSubType(a.type, b.type); +TypeBuilder::~TypeBuilder() = default; + +void TypeBuilder::setHeapType(size_t i, Signature signature) { + assert(i < impl->entries.size() && "Index out of bounds"); + impl->entries[i].set(signature); } -bool SubTyper::isSubType(const Signature& a, const Signature& b) { - // TODO: Implement proper signature subtyping, covariant in results and - // contravariant in params, once V8 implements it. - // return isSubType(b.params, a.params) && isSubType(a.results, b.results); - return a == b; +void TypeBuilder::setHeapType(size_t i, const Struct& struct_) { + assert(i < impl->entries.size() && "index out of bounds"); + impl->entries[i].set(struct_); } -bool SubTyper::isSubType(const Struct& a, const Struct& b) { - // There may be more fields on the left, but not fewer. - if (a.fields.size() < b.fields.size()) { - return false; - } - for (size_t i = 0; i < b.fields.size(); ++i) { - if (!isSubType(a.fields[i], b.fields[i])) { - return false; - } - } - return true; +void TypeBuilder::setHeapType(size_t i, Struct&& struct_) { + assert(i < impl->entries.size() && "index out of bounds"); + impl->entries[i].set(std::move(struct_)); } -bool SubTyper::isSubType(const Array& a, const Array& b) { - return isSubType(a.element, b.element); +void TypeBuilder::setHeapType(size_t i, Array array) { + assert(i < impl->entries.size() && "index out of bounds"); + impl->entries[i].set(array); } -bool SubTyper::isSubType(const Rtt& a, const Rtt& b) { - // (rtt n $x) is a subtype of (rtt $x), that is, if the only difference in - // information is that the left side specifies a depth while the right side - // allows any depth. - return a.heapType == b.heapType && a.hasDepth() && !b.hasDepth(); +Type TypeBuilder::getTempTupleType(const Tuple& tuple) { + return impl->typeStore.canonicalize(tuple); } -bool TypeBounder::hasLeastUpperBound(Type a, Type b) { return bool(lub(a, b)); } +Type TypeBuilder::getTempRefType(size_t i, Nullability nullable) { + assert(i < impl->entries.size() && "Index out of bounds"); + return impl->typeStore.canonicalize( + TypeInfo(impl->entries[i].get(), nullable)); +} -Type TypeBounder::getLeastUpperBound(Type a, Type b) { - auto tempLUB = lub(a, b); - if (!tempLUB) { - return Type::none; - } - if (!isTemp(*tempLUB)) { - // The LUB is already canonical, so we're done. - return *tempLUB; - } - // `tempLUB` is a temporary type owned by `builder`. Since TypeBuilder::build - // returns HeapTypes rather than Types, create a new HeapType definition meant - // only to get `tempLUB` canonicalized in a known location. The use of an - // Array is arbitrary; it might as well have been a Struct. - builder.grow(1); - builder[builder.size() - 1] = Array(Field(*tempLUB, Mutable)); - std::vector built = *builder.build(); - return built.back().getArray().element.type; -} - -HeapType TypeBounder::getLeastUpperBound(HeapType a, HeapType b) { - HeapType l = lub(a, b); - if (!isTemp(l)) { - // The LUB is already canonical, so we're done. - return l; - } - // Find the index corresponding to the LUB. - size_t index = 0; - while (l != builder[index]) { - ++index; - } - // Canonicalize and return the LUB. - return (*builder.build())[index]; +Type TypeBuilder::getTempRttType(size_t i, uint32_t depth) { + assert(i < impl->entries.size() && "Index out of bounds"); + return impl->typeStore.canonicalize(Rtt(depth, impl->entries[i].get())); } -std::optional TypeBounder::lub(Type a, Type b) { - if (a == b) { - return a; - } - if (a == Type::unreachable) { - return b; - } - if (b == Type::unreachable) { - return a; - } - if (a.isTuple() && b.isTuple()) { - auto tuple = lub(a.getTuple(), b.getTuple()); - if (!tuple) { - return {}; - } - return builder.getTempTupleType(*tuple); - } else if (a.isRef() && b.isRef()) { - auto nullability = - (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; - HeapType heapType = lub(a.getHeapType(), b.getHeapType()); - return builder.getTempRefType(heapType, nullability); - } else if (a.isRtt() && b.isRtt()) { - auto rtt = lub(a.getRtt(), b.getRtt()); - if (!rtt) { - return {}; - } - return builder.getTempRttType(*rtt); - } - return {}; -} - -HeapType TypeBounder::lub(HeapType a, HeapType b) { - if (a == b) { - return a; - } - - auto getBasicApproximation = [](HeapType x) { - if (x.isBasic()) { - return x.getBasic(); - } - auto* info = getHeapTypeInfo(x); - switch (info->kind) { - case HeapTypeInfo::BasicKind: - break; - case HeapTypeInfo::SignatureKind: - return HeapType::func; - case HeapTypeInfo::StructKind: - case HeapTypeInfo::ArrayKind: - return HeapType::data; - } - WASM_UNREACHABLE("unexpected kind"); - }; - - auto getBasicLUB = [&]() { - return lub(getBasicApproximation(a), getBasicApproximation(b)); - }; - - if (a.isBasic() || b.isBasic()) { - return getBasicLUB(); - } - - HeapTypeInfo* infoA = getHeapTypeInfo(a); - HeapTypeInfo* infoB = getHeapTypeInfo(b); - - if (infoA->kind != infoB->kind) { - return getBasicLUB(); - } - - if (typeSystem == TypeSystem::Nominal || - typeSystem == TypeSystem::Isorecursive) { - // Walk up the subtype tree to find the LUB. Ascend the tree from both `a` - // and `b` in lockstep. The first type we see for a second time must be the - // LUB because there are no cycles and the only way to encounter a type - // twice is for it to be on the path above both `a` and `b`. - std::unordered_set seen; - auto* currA = infoA; - auto* currB = infoB; - seen.insert(currA); - seen.insert(currB); - while (true) { - auto* nextA = currA->supertype; - auto* nextB = currB->supertype; - if (nextA == nullptr && nextB == nullptr) { - // Did not find a LUB in the subtype tree. - return getBasicLUB(); - } - if (nextA) { - if (!seen.insert(nextA).second) { - return HeapType(uintptr_t(nextA)); - } - currA = nextA; - } - if (nextB) { - if (!seen.insert(nextB).second) { - return HeapType(uintptr_t(nextB)); - } - currB = nextB; - } - } - } - - // Allocate a new slot to construct the LUB of this pair if we have not - // already seen it before. Canonicalize the pair to have the element with the - // smaller ID first since order does not matter. - auto pair = - a.getID() < b.getID() ? std::make_pair(a, b) : std::make_pair(b, a); - size_t index = builder.size(); - auto result = indices.insert({pair, index}); - if (!result.second) { - // We've seen this pair before; stop recursing and do not allocate. - return builder[result.first->second]; - } - - builder.grow(1); - switch (infoA->kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("unexpected kind"); - case HeapTypeInfo::SignatureKind: { - if (auto sig = lub(infoA->signature, infoB->signature)) { - return builder[index] = *sig; - } else { - return builder[index] = HeapType::func; - } - } - case HeapTypeInfo::StructKind: { - return builder[index] = lub(infoA->struct_, infoB->struct_); - } - case HeapTypeInfo::ArrayKind: { - if (auto array = lub(infoA->array, infoB->array)) { - return builder[index] = *array; - } else { - return builder[index] = HeapType::data; - } - } - } - WASM_UNREACHABLE("unexpected kind"); -} - -HeapType::BasicHeapType TypeBounder::lub(HeapType::BasicHeapType a, - HeapType::BasicHeapType b) { - if (a == b) { - return a; - } - // Canonicalize to have `x` be the lesser type. - if (unsigned(a) > unsigned(b)) { - std::swap(a, b); - } - switch (a) { - case HeapType::func: - case HeapType::any: - return HeapType::any; - case HeapType::eq: - if (b == HeapType::i31 || b == HeapType::data) { - return HeapType::eq; - } - return HeapType::any; - case HeapType::i31: - if (b == HeapType::data) { - return HeapType::eq; - } - return HeapType::any; - case HeapType::data: - return HeapType::any; - } - WASM_UNREACHABLE("unexpected basic type"); -} - -std::optional TypeBounder::lub(const Tuple& a, const Tuple& b) { - if (a.types.size() != b.types.size()) { - return {}; - } - Tuple result; - result.types.resize(a.types.size()); - for (size_t i = 0; i < a.types.size(); ++i) { - if (auto type = lub(a.types[i], b.types[i])) { - result.types[i] = *type; - } else { - return {}; - } - } - return result; -} - -std::optional TypeBounder::lub(const Field& a, const Field& b) { - if (a == b) { - return a; - } - // Mutable fields are invariant, so they would have had to be the same. - if (a.mutable_ == Mutable || b.mutable_ == Mutable) { - return {}; - } - // Packed types must match. - if (a.isPacked() != b.isPacked() || - (a.isPacked() && a.packedType != b.packedType)) { - return {}; - } - // Either the packed types match or the types aren't packed. - Type type; - if (auto type = lub(a.type, b.type)) { - Field result = a; - result.type = *type; - return result; - } else { - return {}; - } -} - -std::optional TypeBounder::lub(const Signature& a, - const Signature& b) { - // TODO: Implement proper signature subtyping, covariant in results and - // contravariant in params, once V8 implements it. - if (a != b) { - return {}; - } else { - return a; - } -} - -Struct TypeBounder::lub(const Struct& a, const Struct& b) { - Struct result; - size_t numFields = std::min(a.fields.size(), b.fields.size()); - for (size_t i = 0; i < numFields; ++i) { - if (auto field = lub(a.fields[i], b.fields[i])) { - result.fields.push_back(*field); - } else { - // Stop at the common prefix and ignore the rest. - break; - } - } - return result; -} - -std::optional TypeBounder::lub(const Array& a, const Array& b) { - if (auto elem = lub(a.element, b.element)) { - return Array{*elem}; - } else { - return {}; - } -} - -std::optional TypeBounder::lub(const Rtt& a, const Rtt& b) { - if (a.heapType != b.heapType) { - return {}; - } - uint32_t depth = (a.depth == b.depth) ? a.depth : Rtt::NoDepth; - return Rtt(depth, a.heapType); -} - -void TypePrinter::printHeapTypeName(HeapType type) { - if (type.isBasic()) { - print(type); - return; - } - os << '$' << generator(type).name; -} - -void TypePrinter::printSupertypeOr(std::optional super, - std::string other) { - if (super) { - printHeapTypeName(*super); - } else { - os << other; - } -} - -std::ostream& TypePrinter::print(Type type) { - if (type.isBasic()) { - switch (type.getBasic()) { - case Type::none: - return os << "none"; - case Type::unreachable: - return os << "unreachable"; - case Type::i32: - return os << "i32"; - case Type::i64: - return os << "i64"; - case Type::f32: - return os << "f32"; - case Type::f64: - return os << "f64"; - case Type::v128: - return os << "v128"; - case Type::funcref: - return os << "funcref"; - case Type::anyref: - return os << "anyref"; - case Type::eqref: - return os << "eqref"; - case Type::i31ref: - return os << "i31ref"; - case Type::dataref: - return os << "dataref"; - } - } - - if (isTemp(type)) { - os << "(; temp ;) "; - } -#if TRACE_CANONICALIZATION - os << "(;" << ((type.getID() >> 4) % 1000) << ";) "; -#endif - if (type.isTuple()) { - print(type.getTuple()); - } else if (type.isRef()) { - os << "(ref "; - if (type.isNullable()) { - os << "null "; - } - printHeapTypeName(type.getHeapType()); - os << ')'; - } else if (type.isRtt()) { - print(type.getRtt()); - } else { - WASM_UNREACHABLE("unexpected type"); - } - return os; -} - -std::ostream& TypePrinter::print(HeapType type) { - if (type.isBasic()) { - switch (type.getBasic()) { - case HeapType::func: - return os << "func"; - case HeapType::any: - return os << "any"; - case HeapType::eq: - return os << "eq"; - case HeapType::i31: - return os << "i31"; - case HeapType::data: - return os << "data"; - } - } - - if (isTemp(type)) { - os << "(; temp ;) "; - } -#if TRACE_CANONICALIZATION - os << "(;" << ((type.getID() >> 4) % 1000) << ";)"; -#endif - if (getHeapTypeInfo(type)->kind == HeapTypeInfo::BasicKind) { - os << "(; noncanonical ;) "; - print(getHeapTypeInfo(type)->basic); - } else if (type.isSignature()) { - print(type.getSignature(), type.getSuperType()); - } else if (type.isStruct()) { - print(type.getStruct(), type.getSuperType()); - } else if (type.isArray()) { - print(type.getArray(), type.getSuperType()); - } else { - WASM_UNREACHABLE("unexpected type"); - } - return os; -} - -std::ostream& TypePrinter::print(const Tuple& tuple) { - os << '('; - auto sep = ""; - for (Type type : tuple.types) { - os << sep; - sep = " "; - print(type); - } - return os << ')'; -} - -std::ostream& TypePrinter::print(const Field& field) { - if (field.mutable_) { - os << "(mut "; - } - if (field.isPacked()) { - auto packedType = field.packedType; - if (packedType == Field::PackedType::i8) { - os << "i8"; - } else if (packedType == Field::PackedType::i16) { - os << "i16"; - } else { - WASM_UNREACHABLE("unexpected packed type"); - } - } else { - print(field.type); - } - if (field.mutable_) { - os << ')'; - } - return os; -} - -std::ostream& TypePrinter::print(const Signature& sig, - std::optional super) { - auto printPrefixed = [&](const char* prefix, Type type) { - os << '(' << prefix; - for (Type t : type) { - os << ' '; - print(t); - } - os << ')'; - }; - - os << "(func"; - if (printSupertypes) { - os << "_subtype"; - } - if (sig.params.getID() != Type::none) { - os << ' '; - printPrefixed("param", sig.params); - } - if (sig.results.getID() != Type::none) { - os << ' '; - printPrefixed("result", sig.results); - } - if (printSupertypes) { - os << ' '; - printSupertypeOr(super, "func"); - } - return os << ')'; -} - -std::ostream& TypePrinter::print(const Struct& struct_, - std::optional super) { - os << "(struct"; - if (printSupertypes) { - os << "_subtype"; - } - if (struct_.fields.size()) { - os << " (field"; - } - for (const Field& field : struct_.fields) { - os << ' '; - print(field); - } - if (struct_.fields.size()) { - os << ')'; - } - if (printSupertypes) { - os << ' '; - printSupertypeOr(super, "data"); - } - return os << ')'; -} - -std::ostream& TypePrinter::print(const Array& array, - std::optional super) { - os << "(array"; - if (printSupertypes) { - os << "_subtype"; - } - os << ' '; - print(array.element); - if (printSupertypes) { - os << ' '; - printSupertypeOr(super, "data"); - } - return os << ')'; -} - -std::ostream& TypePrinter::print(const Rtt& rtt) { - os << "(rtt "; - if (rtt.hasDepth()) { - os << rtt.depth << ' '; - } - printHeapTypeName(rtt.heapType); - return os << ')'; -} - -size_t FiniteShapeHasher::hash(Type type) { - size_t digest = wasm::hash(type.isBasic()); - if (type.isBasic()) { - rehash(digest, type.getID()); - } else { - hash_combine(digest, hash(*getTypeInfo(type))); - } - return digest; -} - -size_t FiniteShapeHasher::hash(HeapType heapType) { - size_t digest = wasm::hash(heapType.isBasic()); - if (heapType.isBasic()) { - rehash(digest, heapType.getID()); - return digest; - } - if (topLevelOnly && currDepth > 0) { - return digest; - } - auto it = seen.find(heapType); - rehash(digest, it != seen.end()); - if (it != seen.end()) { - rehash(digest, it->second); - return digest; - } - seen[heapType] = ++currStep; - ++currDepth; - hash_combine(digest, hash(*getHeapTypeInfo(heapType))); - --currDepth; - return digest; -} - -size_t FiniteShapeHasher::hash(const TypeInfo& info) { - size_t digest = wasm::hash(info.kind); - switch (info.kind) { - case TypeInfo::TupleKind: - hash_combine(digest, hash(info.tuple)); - return digest; - case TypeInfo::RefKind: - rehash(digest, info.ref.nullable); - hash_combine(digest, hash(info.ref.heapType)); - return digest; - case TypeInfo::RttKind: - hash_combine(digest, hash(info.rtt)); - return digest; - } - WASM_UNREACHABLE("unexpected kind"); -} - -size_t FiniteShapeHasher::hash(const HeapTypeInfo& info) { - if (getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive) { - return wasm::hash(uintptr_t(&info)); - } - // If the HeapTypeInfo is not finalized, then it is mutable and its shape - // might change in the future. In that case, fall back to pointer identity to - // keep the hash consistent until all the TypeBuilder's types are finalized. - size_t digest = wasm::hash(info.isFinalized); - if (!info.isFinalized) { - rehash(digest, uintptr_t(&info)); - return digest; - } - rehash(digest, info.kind); - switch (info.kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("Basic HeapTypeInfo should have been canonicalized"); - case HeapTypeInfo::SignatureKind: - hash_combine(digest, hash(info.signature)); - return digest; - case HeapTypeInfo::StructKind: - hash_combine(digest, hash(info.struct_)); - return digest; - case HeapTypeInfo::ArrayKind: - hash_combine(digest, hash(info.array)); - return digest; - } - WASM_UNREACHABLE("unexpected kind"); -} - -size_t FiniteShapeHasher::hash(const Tuple& tuple) { - size_t digest = wasm::hash(tuple.types.size()); - for (auto type : tuple.types) { - hash_combine(digest, hash(type)); - } - return digest; -} - -size_t FiniteShapeHasher::hash(const Field& field) { - size_t digest = wasm::hash(field.packedType); - rehash(digest, field.mutable_); - hash_combine(digest, hash(field.type)); - return digest; -} - -size_t FiniteShapeHasher::hash(const Signature& sig) { - size_t digest = hash(sig.params); - hash_combine(digest, hash(sig.results)); - return digest; -} - -size_t FiniteShapeHasher::hash(const Struct& struct_) { - size_t digest = wasm::hash(struct_.fields.size()); - for (const auto& field : struct_.fields) { - hash_combine(digest, hash(field)); - } - return digest; -} - -size_t FiniteShapeHasher::hash(const Array& array) { - return hash(array.element); -} - -size_t FiniteShapeHasher::hash(const Rtt& rtt) { - size_t digest = wasm::hash(rtt.depth); - hash_combine(digest, hash(rtt.heapType)); - return digest; -} - -bool FiniteShapeEquator::eq(Type a, Type b) { - if (a.isBasic() != b.isBasic()) { - return false; - } else if (a.isBasic()) { - return a.getID() == b.getID(); - } else { - return eq(*getTypeInfo(a), *getTypeInfo(b)); - } -} - -bool FiniteShapeEquator::eq(HeapType a, HeapType b) { - if (a.isBasic() != b.isBasic()) { - return false; - } else if (a.isBasic()) { - return a.getID() == b.getID(); - } - if (topLevelOnly && currDepth > 0) { - return true; - } - auto itA = seenA.find(a); - auto itB = seenB.find(b); - if ((itA != seenA.end()) != (itB != seenB.end())) { - return false; - } else if (itA != seenA.end()) { - return itA->second == itB->second; - } - seenA[a] = seenB[b] = ++currStep; - ++currDepth; - bool ret = eq(*getHeapTypeInfo(a), *getHeapTypeInfo(b)); - --currDepth; - return ret; -} - -bool FiniteShapeEquator::eq(const TypeInfo& a, const TypeInfo& b) { - if (a.kind != b.kind) { - return false; - } - switch (a.kind) { - case TypeInfo::TupleKind: - return eq(a.tuple, b.tuple); - case TypeInfo::RefKind: - return a.ref.nullable == b.ref.nullable && - eq(a.ref.heapType, b.ref.heapType); - case TypeInfo::RttKind: - return eq(a.rtt, b.rtt); - } - WASM_UNREACHABLE("unexpected kind"); -} - -bool FiniteShapeEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) { - if (getTypeSystem() == TypeSystem::Nominal || - getTypeSystem() == TypeSystem::Isorecursive) { - return &a == &b; - } - if (a.isFinalized != b.isFinalized) { - return false; - } else if (!a.isFinalized) { - // See comment on corresponding FiniteShapeHasher method. - return &a == &b; - } - if (a.kind != b.kind) { - return false; - } - switch (a.kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("Basic HeapTypeInfo should have been canonicalized"); - case HeapTypeInfo::SignatureKind: - return eq(a.signature, b.signature); - case HeapTypeInfo::StructKind: - return eq(a.struct_, b.struct_); - case HeapTypeInfo::ArrayKind: - return eq(a.array, b.array); - } - WASM_UNREACHABLE("unexpected kind"); -} - -bool FiniteShapeEquator::eq(const Tuple& a, const Tuple& b) { - return std::equal(a.types.begin(), - a.types.end(), - b.types.begin(), - b.types.end(), - [&](const Type& x, const Type& y) { return eq(x, y); }); -} - -bool FiniteShapeEquator::eq(const Field& a, const Field& b) { - return a.packedType == b.packedType && a.mutable_ == b.mutable_ && - eq(a.type, b.type); -} - -bool FiniteShapeEquator::eq(const Signature& a, const Signature& b) { - return eq(a.params, b.params) && eq(a.results, b.results); -} - -bool FiniteShapeEquator::eq(const Struct& a, const Struct& b) { - return std::equal(a.fields.begin(), - a.fields.end(), - b.fields.begin(), - b.fields.end(), - [&](const Field& x, const Field& y) { return eq(x, y); }); -} - -bool FiniteShapeEquator::eq(const Array& a, const Array& b) { - return eq(a.element, b.element); -} - -bool FiniteShapeEquator::eq(const Rtt& a, const Rtt& b) { - return a.depth == b.depth && eq(a.heapType, b.heapType); -} - -size_t RecGroupHasher::operator()() const { - size_t digest = wasm::hash(group.size()); - for (auto type : group) { - hash_combine(digest, topLevelHash(type)); - } - return digest; -} - -size_t RecGroupHasher::topLevelHash(HeapType type) const { - size_t digest = wasm::hash(type.isBasic()); - if (type.isBasic()) { - wasm::rehash(digest, type.getID()); - } else { - hash_combine(digest, hash(*getHeapTypeInfo(type))); - } - return digest; -} - -size_t RecGroupHasher::hash(Type type) const { - size_t digest = wasm::hash(type.isBasic()); - if (type.isBasic()) { - wasm::rehash(digest, type.getID()); - } else { - hash_combine(digest, hash(*getTypeInfo(type))); - } - return digest; -} - -size_t RecGroupHasher::hash(HeapType type) const { - // Do not recurse into the structure of this child type, but rather hash it as - // an index into a rec group. Only take the rec group identity into account if - // the child is not a member of the top-level group because in that case the - // group may not be canonicalized yet. - size_t digest = wasm::hash(type.isBasic()); - if (type.isBasic()) { - wasm::rehash(digest, type.getID()); - return digest; - } - wasm::rehash(digest, type.getRecGroupIndex()); - auto currGroup = type.getRecGroup(); - if (currGroup != group) { - wasm::rehash(digest, currGroup.getID()); - } - return digest; -} - -size_t RecGroupHasher::hash(const TypeInfo& info) const { - size_t digest = wasm::hash(info.kind); - switch (info.kind) { - case TypeInfo::TupleKind: - hash_combine(digest, hash(info.tuple)); - return digest; - case TypeInfo::RefKind: - rehash(digest, info.ref.nullable); - hash_combine(digest, hash(info.ref.heapType)); - return digest; - case TypeInfo::RttKind: - hash_combine(digest, hash(info.rtt)); - return digest; - } - WASM_UNREACHABLE("unexpected kind"); -} - -size_t RecGroupHasher::hash(const HeapTypeInfo& info) const { - assert(info.isFinalized); - size_t digest = wasm::hash(bool(info.supertype)); - if (info.supertype) { - hash_combine(digest, hash(HeapType(uintptr_t(info.supertype)))); - } - wasm::rehash(digest, info.kind); - switch (info.kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("Basic HeapTypeInfo should have been canonicalized"); - case HeapTypeInfo::SignatureKind: - hash_combine(digest, hash(info.signature)); - return digest; - case HeapTypeInfo::StructKind: - hash_combine(digest, hash(info.struct_)); - return digest; - case HeapTypeInfo::ArrayKind: - hash_combine(digest, hash(info.array)); - return digest; - } - WASM_UNREACHABLE("unexpected kind"); -} - -size_t RecGroupHasher::hash(const Tuple& tuple) const { - size_t digest = wasm::hash(tuple.types.size()); - for (auto type : tuple.types) { - hash_combine(digest, hash(type)); - } - return digest; -} - -size_t RecGroupHasher::hash(const Field& field) const { - size_t digest = wasm::hash(field.packedType); - rehash(digest, field.mutable_); - hash_combine(digest, hash(field.type)); - return digest; -} - -size_t RecGroupHasher::hash(const Signature& sig) const { - size_t digest = hash(sig.params); - hash_combine(digest, hash(sig.results)); - return digest; -} - -size_t RecGroupHasher::hash(const Struct& struct_) const { - size_t digest = wasm::hash(struct_.fields.size()); - for (const auto& field : struct_.fields) { - hash_combine(digest, hash(field)); - } - return digest; -} - -size_t RecGroupHasher::hash(const Array& array) const { - return hash(array.element); -} - -size_t RecGroupHasher::hash(const Rtt& rtt) const { - size_t digest = wasm::hash(rtt.depth); - hash_combine(digest, hash(rtt.heapType)); - return digest; -} - -bool RecGroupEquator::operator()() const { - if (newGroup == otherGroup) { - return true; - } - // The rec groups are equivalent if they are piecewise equivalent. - return std::equal( - newGroup.begin(), - newGroup.end(), - otherGroup.begin(), - otherGroup.end(), - [&](const HeapType& a, const HeapType& b) { return topLevelEq(a, b); }); -} - -bool RecGroupEquator::topLevelEq(HeapType a, HeapType b) const { - if (a == b) { - return true; - } - if (a.isBasic() || b.isBasic()) { - return false; - } - return eq(*getHeapTypeInfo(a), *getHeapTypeInfo(b)); -} - -bool RecGroupEquator::eq(Type a, Type b) const { - if (a == b) { - return true; - } - if (a.isBasic() || b.isBasic()) { - return false; - } - return eq(*getTypeInfo(a), *getTypeInfo(b)); -} - -bool RecGroupEquator::eq(HeapType a, HeapType b) const { - // Do not recurse into the structure of children `a` and `b`, but check - // whether their recursion groups and indices match. Since `newGroup` may not - // be canonicalized, explicitly check whether `a` and `b` are in the - // respective recursion groups of the respective top-level groups we are - // comparing, in which case the structure is still equivalent. - if (a.isBasic() || b.isBasic()) { - return a == b; - } - if (a.getRecGroupIndex() != b.getRecGroupIndex()) { - return false; - } - auto groupA = a.getRecGroup(); - auto groupB = b.getRecGroup(); - return groupA == groupB || (groupA == newGroup && groupB == otherGroup); -} - -bool RecGroupEquator::eq(const TypeInfo& a, const TypeInfo& b) const { - if (a.kind != b.kind) { - return false; - } - switch (a.kind) { - case TypeInfo::TupleKind: - return eq(a.tuple, b.tuple); - case TypeInfo::RefKind: - return a.ref.nullable == b.ref.nullable && - eq(a.ref.heapType, b.ref.heapType); - case TypeInfo::RttKind: - return eq(a.rtt, b.rtt); - } - WASM_UNREACHABLE("unexpected kind"); -} - -bool RecGroupEquator::eq(const HeapTypeInfo& a, const HeapTypeInfo& b) const { - if (bool(a.supertype) != bool(b.supertype)) { - return false; - } - if (a.supertype) { - HeapType superA(uintptr_t(a.supertype)); - HeapType superB(uintptr_t(b.supertype)); - if (!eq(superA, superB)) { - return false; - } - } - if (a.kind != b.kind) { - return false; - } - switch (a.kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("Basic HeapTypeInfo should have been canonicalized"); - case HeapTypeInfo::SignatureKind: - return eq(a.signature, b.signature); - case HeapTypeInfo::StructKind: - return eq(a.struct_, b.struct_); - case HeapTypeInfo::ArrayKind: - return eq(a.array, b.array); - } - WASM_UNREACHABLE("unexpected kind"); -} - -bool RecGroupEquator::eq(const Tuple& a, const Tuple& b) const { - return std::equal(a.types.begin(), - a.types.end(), - b.types.begin(), - b.types.end(), - [&](const Type& x, const Type& y) { return eq(x, y); }); -} - -bool RecGroupEquator::eq(const Field& a, const Field& b) const { - return a.packedType == b.packedType && a.mutable_ == b.mutable_ && - eq(a.type, b.type); -} - -bool RecGroupEquator::eq(const Signature& a, const Signature& b) const { - return eq(a.params, b.params) && eq(a.results, b.results); -} - -bool RecGroupEquator::eq(const Struct& a, const Struct& b) const { - return std::equal(a.fields.begin(), - a.fields.end(), - b.fields.begin(), - b.fields.end(), - [&](const Field& x, const Field& y) { return eq(x, y); }); -} - -bool RecGroupEquator::eq(const Array& a, const Array& b) const { - return eq(a.element, b.element); -} - -bool RecGroupEquator::eq(const Rtt& a, const Rtt& b) const { - return a.depth == b.depth && eq(a.heapType, b.heapType); -} - -template void TypeGraphWalkerBase::walkRoot(Type* type) { - assert(taskList.empty()); - taskList.push_back(Task::scan(type)); - doWalk(); -} - -template void TypeGraphWalkerBase::walkRoot(HeapType* ht) { - assert(taskList.empty()); - taskList.push_back(Task::scan(ht)); - doWalk(); -} - -template void TypeGraphWalkerBase::doWalk() { - while (!taskList.empty()) { - auto curr = taskList.back(); - taskList.pop_back(); - switch (curr.kind) { - case Task::PreType: - self().preVisitType(curr.type); - break; - case Task::PreHeapType: - self().preVisitHeapType(curr.heapType); - break; - case Task::ScanType: - taskList.push_back(Task::postVisit(curr.type)); - self().scanType(curr.type); - taskList.push_back(Task::preVisit(curr.type)); - break; - case Task::ScanHeapType: - taskList.push_back(Task::postVisit(curr.heapType)); - self().scanHeapType(curr.heapType); - taskList.push_back(Task::preVisit(curr.heapType)); - break; - case Task::PostType: - self().postVisitType(curr.type); - break; - case Task::PostHeapType: - self().postVisitHeapType(curr.heapType); - break; - } - } -} - -template void TypeGraphWalkerBase::scanType(Type* type) { - if (type->isBasic()) { - return; - } - auto* info = getTypeInfo(*type); - switch (info->kind) { - case TypeInfo::TupleKind: { - auto& types = info->tuple.types; - for (auto it = types.rbegin(); it != types.rend(); ++it) { - taskList.push_back(Task::scan(&*it)); - } - break; - } - case TypeInfo::RefKind: { - taskList.push_back(Task::scan(&info->ref.heapType)); - break; - } - case TypeInfo::RttKind: - taskList.push_back(Task::scan(&info->rtt.heapType)); - break; - } -} - -template -void TypeGraphWalkerBase::scanHeapType(HeapType* ht) { - if (ht->isBasic()) { - return; - } - auto* info = getHeapTypeInfo(*ht); - switch (info->kind) { - case HeapTypeInfo::BasicKind: - break; - case HeapTypeInfo::SignatureKind: - taskList.push_back(Task::scan(&info->signature.results)); - taskList.push_back(Task::scan(&info->signature.params)); - break; - case HeapTypeInfo::StructKind: { - auto& fields = info->struct_.fields; - for (auto field = fields.rbegin(); field != fields.rend(); ++field) { - taskList.push_back(Task::scan(&field->type)); - } - break; - } - case HeapTypeInfo::ArrayKind: - taskList.push_back(Task::scan(&info->array.element.type)); - break; - } -} - -} // anonymous namespace - -struct TypeBuilder::Impl { - // Store of temporary Types. Types that need to be canonicalized will be - // copied into the global TypeStore. - TypeStore typeStore; - - // Store of temporary recursion groups, which will be moved to the global - // collection of recursion groups as part of building. - std::vector> recGroups; - - struct Entry { - std::unique_ptr info; - bool initialized = false; - Entry() { - // We need to eagerly allocate the HeapTypeInfo so we have a TypeID to use - // to refer to it before it is initialized. Arbitrarily choose a default - // value. - info = std::make_unique(Signature()); - set(Signature()); - initialized = false; - } - void set(HeapTypeInfo&& hti) { - hti.supertype = info->supertype; - hti.recGroup = info->recGroup; - *info = std::move(hti); - info->isTemp = true; - info->isFinalized = false; - initialized = true; - } - HeapType get() { return HeapType(TypeID(info.get())); } - }; - - std::vector entries; - - Impl(size_t n) : entries(n) {} -}; - -TypeBuilder::TypeBuilder(size_t n) { - impl = std::make_unique(n); -} - -TypeBuilder::~TypeBuilder() = default; - -TypeBuilder::TypeBuilder(TypeBuilder&& other) = default; -TypeBuilder& TypeBuilder::operator=(TypeBuilder&& other) = default; - -void TypeBuilder::grow(size_t n) { - assert(size() + n > size()); - impl->entries.resize(size() + n); -} - -size_t TypeBuilder::size() { return impl->entries.size(); } - -void TypeBuilder::setHeapType(size_t i, HeapType::BasicHeapType basic) { - assert(i < size() && "Index out of bounds"); - impl->entries[i].set(basic); -} - -void TypeBuilder::setHeapType(size_t i, Signature signature) { - assert(i < size() && "index out of bounds"); - impl->entries[i].set(signature); -} - -void TypeBuilder::setHeapType(size_t i, const Struct& struct_) { - assert(i < size() && "index out of bounds"); - impl->entries[i].set(struct_); -} - -void TypeBuilder::setHeapType(size_t i, Struct&& struct_) { - assert(i < size() && "index out of bounds"); - impl->entries[i].set(std::move(struct_)); -} - -void TypeBuilder::setHeapType(size_t i, Array array) { - assert(i < size() && "index out of bounds"); - impl->entries[i].set(array); -} - -bool TypeBuilder::isBasic(size_t i) { - assert(i < size() && "index out of bounds"); - return impl->entries[i].info->kind == HeapTypeInfo::BasicKind; -} - -HeapType::BasicHeapType TypeBuilder::getBasic(size_t i) { - assert(isBasic(i)); - return impl->entries[i].info->basic; -} - -HeapType TypeBuilder::getTempHeapType(size_t i) { - assert(i < size() && "index out of bounds"); - return impl->entries[i].get(); -} - -Type TypeBuilder::getTempTupleType(const Tuple& tuple) { - Type ret = impl->typeStore.insert(tuple); - if (tuple.types.size() > 1) { - return markTemp(ret); - } else { - // No new tuple was created, so the result might not be temporary. - return ret; - } -} - -Type TypeBuilder::getTempRefType(HeapType type, Nullability nullable) { - return markTemp(impl->typeStore.insert(TypeInfo(type, nullable))); -} - -Type TypeBuilder::getTempRttType(Rtt rtt) { - return markTemp(impl->typeStore.insert(rtt)); -} - -void TypeBuilder::setSubType(size_t i, size_t j) { - assert(i < size() && j < size() && "index out of bounds"); - HeapTypeInfo* sub = impl->entries[i].info.get(); - HeapTypeInfo* super = impl->entries[j].info.get(); - sub->supertype = super; -} - -void TypeBuilder::createRecGroup(size_t i, size_t length) { - assert(i <= size() && i + length <= size() && "group out of bounds"); - // Only materialize nontrivial recursion groups. - if (length < 2) { - return; - } - auto& groups = impl->recGroups; - groups.emplace_back(std::make_unique()); - for (; length > 0; --length) { - auto& info = impl->entries[i + length - 1].info; - assert(info->recGroup == nullptr && "group already assigned"); - info->recGroup = groups.back().get(); - } -} - -namespace { - -// Helper for TypeBuilder::build() that keeps track of temporary types and -// provides logic for replacing them gradually with more canonical types. -struct CanonicalizationState { - // The list of types being built and canonicalized. Will eventually be - // returned to the TypeBuilder user. - std::vector results; - // The newly constructed, temporary HeapTypeInfos that still need to be - // canonicalized. - std::vector> newInfos; - - // Either the fully canonical HeapType or a new temporary HeapTypeInfo that a - // previous HeapTypeInfo will be replaced with. - struct Replacement : std::variant> { - using Super = std::variant>; - Replacement(std::unique_ptr&& info) - : Super(std::move(info)) {} - Replacement(HeapType type) : Super(type) {} - HeapType* getHeapType() { return std::get_if(this); } - std::unique_ptr* getHeapTypeInfo() { - return std::get_if>(this); - } - HeapType getAsHeapType() { - if (auto* type = getHeapType()) { - return *type; - } - return asHeapType(*getHeapTypeInfo()); - } - }; - - using ReplacementMap = std::unordered_map; - - // Updates the `results` and `newInfo` lists, but does not modify any of the - // infos to update HeapType use sites. - void updateShallow(ReplacementMap& replacements); - // Updates the HeapType use sites within `info`. - void updateUses(ReplacementMap& replacements, - std::unique_ptr& info); - // Updates lists and uses. - void update(ReplacementMap& replacements); - -#if TRACE_CANONICALIZATION - void dump() { - std::cerr << "Results:\n"; - for (size_t i = 0; i < results.size(); ++i) { - std::cerr << i << ": " << results[i] << "\n"; - } - std::cerr << "NewInfos:\n"; - for (size_t i = 0; i < newInfos.size(); ++i) { - std::cerr << asHeapType(newInfos[i]) << "\n"; - } - std::cerr << '\n'; - } -#endif // TRACE_CANONICALIZATION -}; - -void CanonicalizationState::update(ReplacementMap& replacements) { - if (replacements.empty()) { - return; - } - updateShallow(replacements); - for (auto& info : newInfos) { - updateUses(replacements, info); - } -} - -void CanonicalizationState::updateShallow(ReplacementMap& replacements) { - if (replacements.empty()) { - return; - } - - // Update the results vector. - for (auto& type : results) { - if (auto it = replacements.find(type); it != replacements.end()) { - type = it->second.getAsHeapType(); - } - } - - // Remove replaced types from newInfos. - bool needsConsolidation = false; - for (auto& info : newInfos) { - HeapType oldType = asHeapType(info); - if (auto it = replacements.find(oldType); it != replacements.end()) { - auto& replacement = it->second; - if (auto* newInfo = replacement.getHeapTypeInfo()) { - // Replace the old info with the new info in `newInfos`, replacing the - // moved info in `replacement` with the corresponding new HeapType so we - // can still perform the correct replacement in the next step. - HeapType newType = asHeapType(*newInfo); - info = std::move(*newInfo); - replacement = {newType}; - } else { - // The old info is replaced, but there is no new Info to replace it, so - // just delete the old info. We will remove the holes in `newInfos` - // afterwards. - info = nullptr; - needsConsolidation = true; - } - } - } - if (needsConsolidation) { - newInfos.erase(std::remove(newInfos.begin(), newInfos.end(), nullptr), - newInfos.end()); - } -} - -void CanonicalizationState::updateUses(ReplacementMap& replacements, - std::unique_ptr& info) { - if (replacements.empty()) { - return; - } - // Replace all old types reachable from `info`. - struct ChildUpdater : HeapTypeChildWalker { - ReplacementMap& replacements; - ChildUpdater(ReplacementMap& replacements) : replacements(replacements) {} - void noteChild(HeapType* child) { - if (auto it = replacements.find(*child); it != replacements.end()) { - *child = it->second.getAsHeapType(); - } - } - }; - HeapType root = asHeapType(info); - ChildUpdater(replacements).walkRoot(&root); - - // We may need to update its supertype as well. - if (info->supertype) { - HeapType super(uintptr_t(info->supertype)); - if (auto it = replacements.find(super); it != replacements.end()) { - info->supertype = getHeapTypeInfo(it->second.getAsHeapType()); - } - } -} - -// A wrapper around a HeapType that provides equality and hashing based only on -// its top-level shape, up to but not including its closest HeapType -// descendants. This is the shape that determines the most fine-grained initial -// partitions for DFA minimization and also the shape that determines the -// "alphabet" for transitioning to the child HeapTypes in the DFA view of the -// type definition. -struct ShallowHeapType { - HeapType heapType; - - ShallowHeapType(HeapType heapType) : heapType(heapType) {} - bool operator==(const ShallowHeapType& other) const; -}; - -bool ShallowHeapType::operator==(const ShallowHeapType& other) const { - return FiniteShapeEquator(/*topLevelOnly=*/true) - .eq(this->heapType, other.heapType); -} - -} // anonymous namespace -} // namespace wasm - -namespace std { - -template<> class hash { -public: - size_t operator()(const wasm::ShallowHeapType& type) const { - return wasm::FiniteShapeHasher(/*topLevelOnly=*/true).hash(type.heapType); - } -}; - -} // namespace std - -namespace wasm { namespace { -// The Refined Partitions data structure used in Valmari-Lehtinen DFA -// minimization. The translation from terms used in the Valmari-Lehtinen paper -// to the more expanded terms used here is: -// -// Block => Set -// elems => elements -// loc => elementIndices -// sidx => setIndices -// first => beginnings -// end => endings -// mid => pivots -// -struct Partitions { - // The number of sets. - size_t sets = 0; - - // The partitioned elements. Elements in the same set are next to each other. - // Within each set, "marked" elements come first followed by "unmarked" - // elements. - std::vector elements; - - // Maps elements to their indices in `elements`. - std::vector elementIndices; - - // Maps elements to their sets, identified by an index. - std::vector setIndices; - - // Maps sets to the indices of their first elements in `elements`. - std::vector beginnings; - - // Maps sets to (one past) the indices of their ends in `elements`. - std::vector endings; - - // Maps sets to the indices of their first unmarked elements in `elements`. - std::vector pivots; - - Partitions() = default; - - // Allocate space up front so we never need to re-allocate. The actual - // contents of all the vectors will need to be externally initialized, - // though. - Partitions(size_t size) - : elements(size), elementIndices(size), setIndices(size), beginnings(size), - endings(size), pivots(size) {} - - struct Set { - using Iterator = std::vector::iterator; - - Partitions& partitions; - size_t index; - - Set(Partitions& partitions, size_t index) - : partitions(partitions), index(index) {} - - Iterator begin() { - return partitions.elements.begin() + partitions.beginnings[index]; - } - Iterator end() { - return partitions.elements.begin() + partitions.endings[index]; - } - size_t size() { - return partitions.endings[index] - partitions.beginnings[index]; - } - - bool hasMarks() { - return partitions.pivots[index] != partitions.beginnings[index]; - } - - // Split the set between marked and unmarked elements if there are both - // marked and unmarked elements. Unmark all elements of this set regardless. - // Return the index of the new partition or 0 if there was no split. - size_t split(); - }; - - Set getSet(size_t index) { return {*this, index}; } +// Implements the algorithm to canonicalize the HeapTypes in a TypeBuilder, +// replacing and deduplicating the temporary type and heaptypes backed by +// storage owned by the TypeBuilder into normal types and heap types backed by +// the global stores. +struct Canonicalizer { + TypeBuilder& builder; - // Returns the set containing an element, which can be iterated upon. The set - // may be invalidated by calls to `mark` or `Set::split`. - Set getSetForElem(size_t element) { return getSet(setIndices[element]); } - - void mark(size_t element) { - size_t index = elementIndices[element]; - size_t set = setIndices[element]; - size_t pivot = pivots[set]; - if (index >= pivot) { - // Move the pivot element into the location of the newly marked element. - elements[index] = elements[pivot]; - elementIndices[elements[index]] = index; - // Move the newly marked element into the pivot location. - elements[pivot] = element; - elementIndices[element] = pivot; - // Update the pivot index to mark the element. - ++pivots[set]; - } - } -}; - -size_t Partitions::Set::split() { - size_t begin = partitions.beginnings[index]; - size_t end = partitions.endings[index]; - size_t pivot = partitions.pivots[index]; - if (pivot == begin) { - // No elements marked, so there is nothing to do. - return 0; - } - if (pivot == end) { - // All elements were marked, so just unmark them. - partitions.pivots[index] = begin; - return 0; - } - // Create a new set covering the marked region. - size_t newIndex = partitions.sets++; - partitions.beginnings[newIndex] = begin; - partitions.pivots[newIndex] = begin; - partitions.endings[newIndex] = pivot; - for (size_t i = begin; i < pivot; ++i) { - partitions.setIndices[partitions.elements[i]] = newIndex; - } - // Update the old set. The end and pivot are already correct. - partitions.beginnings[index] = pivot; - return newIndex; -} - -// Uses Valmari and Lehtinen's partial DFA minimization algorithm to construct a -// minimal type definition graph from an input graph. See -// https://arxiv.org/pdf/0802.2826.pdf. -struct ShapeCanonicalizer { - // The results of shape canonicalization. - CanonicalizationState::ReplacementMap replacements; - - ShapeCanonicalizer(std::vector& roots); - -private: - // Maps state indices to their underlying HeapTypes and vice versa. - std::vector heapTypes; - std::unordered_map states; - - // A DFA transition into a state. - struct Transition { - size_t pred; - size_t label; + struct Item { + enum Kind { + TypeKind, + HeapTypeKind, + } kind; + union { + Type* type; + HeapType* heapType; + }; + Item(Type* type) : kind(TypeKind), type(type) {} + Item(HeapType* heapType) : kind(HeapTypeKind), heapType(heapType) {} }; - // The transitions arranged such that the transitions leading to state `q` are - // `transitions[transitionIndices[q] : transitionIndices[q+1]]`. - std::vector transitions; - std::vector transitionIndices; - - // The state partitions. - Partitions partitions; - - // The splitters, which are partitions of the input transitions. - Partitions splitters; - - void initialize(std::vector& roots); - void createReplacements(); - - // Return pointers to the non-basic HeapType children of `ht`, including - // BasicKind children. - std::vector getChildren(HeapType ht); - -#if TRACE_CANONICALIZATION - void dumpPartitions() { - for (size_t set = 0; set < partitions.sets; ++set) { - std::cerr << "Partition " << set << '\n'; - std::cerr << "begin: " << partitions.beginnings[set] - << ", end: " << partitions.endings[set] - << ", pivot: " << partitions.pivots[set] << '\n'; - for (size_t index : partitions.getSet(set)) { - assert(partitions.setIndices[index] == set); - std::cerr << heapTypes[index] << '\n'; - } - std::cerr << '\n'; - } - } -#endif -}; - -ShapeCanonicalizer::ShapeCanonicalizer(std::vector& roots) { -#if TRACE_CANONICALIZATION - std::cerr << "Root HeapTypes:\n"; - for (auto root : roots) { - std::cerr << root << '\n'; - } - std::cerr << '\n'; -#endif - - initialize(roots); - -#if TRACE_CANONICALIZATION - std::cerr << "Initial partitions:\n"; - dumpPartitions(); -#endif - - // The list of splitter partitions that might be able to split states in some - // state partition. Starts out containing all splitter partitions. - std::vector potentialSplitters; - potentialSplitters.reserve(splitters.sets); - for (size_t i = 0; i < splitters.sets; ++i) { - potentialSplitters.push_back(i); - } - - while (!potentialSplitters.empty()) { - size_t potentialSplitter = potentialSplitters.back(); - potentialSplitters.pop_back(); - - // The partitions that may be able to be split. - std::vector markedPartitions; - - // Mark states that are predecessors via this splitter partition. - for (size_t transition : splitters.getSet(potentialSplitter)) { - size_t state = transitions[transition].pred; - auto partition = partitions.getSetForElem(state); - if (!partition.hasMarks()) { - markedPartitions.push_back(partition.index); - } - partitions.mark(state); - } - - // Try to split each partition with marked states. - for (size_t partition : markedPartitions) { - size_t newPartition = partitions.getSet(partition).split(); - if (!newPartition) { - // There was nothing to split. - continue; - } - - // We only want to keep using the smaller of the two split partitions. - if (partitions.getSet(newPartition).size() < - partitions.getSet(partition).size()) { - newPartition = partition; - } - - // The splitter partitions that may need to be split to match the new - // split of the state partitions. - std::vector markedSplitters; - - // Mark transitions that lead to the newly split off states. - for (size_t state : partitions.getSet(newPartition)) { - for (size_t t = transitionIndices[state], - end = transitionIndices[state + 1]; - t < end; - ++t) { - auto splitter = splitters.getSetForElem(t); - if (!splitter.hasMarks()) { - markedSplitters.push_back(splitter.index); - } - splitters.mark(t); - } - } - - // Split the splitters and update `potentialSplitters`. - for (size_t splitter : markedSplitters) { - size_t newSplitter = splitters.getSet(splitter).split(); - if (newSplitter) { - potentialSplitters.push_back(newSplitter); - } - } - } - } - -#if TRACE_CANONICALIZATION - std::cerr << "Final partitions:\n"; - dumpPartitions(); -#endif - - createReplacements(); -} - -void ShapeCanonicalizer::initialize(std::vector& roots) { - struct Initializer : HeapTypeGraphWalker { - ShapeCanonicalizer& canonicalizer; - - // Maps shallow HeapType shapes to corresponding HeapType indices. - InsertOrderedMap> initialPartitions; - - // Maps `dest` HeapType indices to their input transitions. - std::map> transitions; - size_t numTransitions = 0; - - Initializer(ShapeCanonicalizer& canonicalizer) - : canonicalizer(canonicalizer) {} - - size_t getIndex(HeapType type) { - // Allocate an index for the HeapType if it doesn't already have one. - auto inserted = - canonicalizer.states.insert({type, canonicalizer.states.size()}); - if (inserted.second) { - canonicalizer.heapTypes.push_back(type); - } - return inserted.first->second; - } - - void noteHeapType(HeapType type) { - size_t index = getIndex(type); - - // Allocate an initial partition for this HeapType's shallow shape if one - // does not already exist, then append the HeapType to the partition. - initialPartitions[ShallowHeapType(type)].push_back(index); - - // Traverse the non-basic children to collect graph edges, i.e. - // transitions in the DFA. - struct TransitionInitializer - : HeapTypeChildWalker { - Initializer& initializer; - size_t parent; - size_t label = 0; - TransitionInitializer(Initializer& initializer, size_t parent) - : initializer(initializer), parent(parent) {} - void noteChild(HeapType* childType) { - if (childType->isBasic()) { - return; - } - // Record the transition from parent to child. - size_t child = initializer.getIndex(*childType); - initializer.transitions[child].push_back({parent, label++}); - ++initializer.numTransitions; - } - }; - TransitionInitializer(*this, index).walkRoot(&type); - } - }; + // IDs of scanned Types and HeapTypes, used to prevent repeated scanning. + std::unordered_set scanned; - Initializer initializer(*this); - for (HeapType& root : roots) { - initializer.walkRoot(&root); - } - - // Now that we have initialized maps containing all the necessary data, use - // them to initialize the flattened vector-based data structures that we will - // use to efficiently run the minimization algorithm. - - // Initialize `partitions`. - partitions = Partitions(heapTypes.size()); - size_t elementIndex = 0; - for (auto pair : initializer.initialPartitions) { - size_t set = partitions.sets++; - partitions.beginnings[set] = elementIndex; - partitions.pivots[set] = elementIndex; - for (size_t elem : pair.second) { - partitions.elements[elementIndex] = elem; - partitions.elementIndices[elem] = elementIndex; - partitions.setIndices[elem] = set; - ++elementIndex; - } - partitions.endings[set] = elementIndex; - } - - // Initialize `transitions` and `transitionIndices`. - transitions.reserve(initializer.numTransitions); - transitionIndices.resize(heapTypes.size() + 1); - for (size_t dest = 0; dest < heapTypes.size(); ++dest) { - // Record the first index of transitions leading to `dest`. - transitionIndices[dest] = transitions.size(); - auto it = initializer.transitions.find(dest); - if (it != initializer.transitions.end()) { - transitions.insert( - transitions.end(), it->second.begin(), it->second.end()); - } - } - // Record one-past the end of the transitions leading to the final `dest`. - transitionIndices[heapTypes.size()] = transitions.size(); - - // Initialize `splitters`. The initial sets are partitioned by destination - // state partition and transition label. - splitters = Partitions(transitions.size()); - elementIndex = 0; - for (size_t statePartition = 0; statePartition < partitions.sets; - ++statePartition) { - // The in-transitions leading to states in the current partition, organized - // by transition label. - std::map> currTransitions; - for (size_t state : partitions.getSet(statePartition)) { - for (size_t transition = transitionIndices[state], - end = transitionIndices[state + 1]; - transition < end; - ++transition) { - currTransitions[transitions[transition].label].push_back(transition); - } - } - // Create a splitter partition for each in-transition label leading to the - // current state partition. - for (auto& pair : currTransitions) { - size_t set = splitters.sets++; - splitters.beginnings[set] = elementIndex; - splitters.pivots[set] = elementIndex; - for (size_t transition : pair.second) { - splitters.elements[elementIndex] = transition; - splitters.elementIndices[transition] = elementIndex; - splitters.setIndices[transition] = set; - ++elementIndex; - } - splitters.endings[set] = elementIndex; - } - } -} + // The work list of Types and HeapTypes remaining to be scanned. + std::vector scanList; -void ShapeCanonicalizer::createReplacements() { - // Create a single new HeapTypeInfo for each partition. Initialize each new - // HeapTypeInfo as a copy of a representative HeapTypeInfo from its partition, - // then patch all the children of the new HeapTypeInfos to refer to other new - // HeapTypeInfos rather than the original HeapTypeInfos. This newly formed - // graph will have a shape coinductively equivalent to the original graph's - // shape, but each type definition will be minimal and distinct. - // - // However, for partitions that already contain globally canonical types, find - // and use the corresponding HeapTypeInfo directly without copying. Since the - // partitions reachable from a globally canonical type will also contain a - // globally canonical type, no temporary types will end up being patched into - // the globally canonical types and we can skip patching the children of those - // types. - for (size_t p = 0; p < partitions.sets; ++p) { - auto partition = partitions.getSet(p); - auto it = std::find_if(partition.begin(), - partition.end(), - [this](size_t i) { return !isTemp(heapTypes[i]); }); - HeapType newType; - auto partitionIt = partition.begin(); - if (it != partition.end()) { - newType = heapTypes[*it]; - } else { - // We do not already know about a globally canonical type for this - // partition. Create a copy and a replacement that owns it. - HeapType oldType = heapTypes[*partitionIt++]; - const auto& representative = *getHeapTypeInfo(oldType); - auto info = std::make_unique(representative); - info->isTemp = true; - newType = asHeapType(info); - replacements.insert({oldType, std::move(info)}); - } - // Create replacements for all the other types in the partition. - for (; partitionIt != partition.end(); ++partitionIt) { - if (partitionIt != it) { - replacements.insert({heapTypes[*partitionIt], newType}); - } - } - } -} + // The list of Types and HeapTypes to visit constructed in forward preorder + // and eventually traversed in reverse to give a reverse postorder. + std::vector visitList; + + // Maps Type and HeapType IDs to the IDs of Types and HeapTypes they can + // reach in the type graph. Only considers compound Types and HeapTypes. + std::unordered_map> reaches; + + // Maps Types and HeapTypes backed by the TypeBuilder's Stores to globally + // canonical Types and HeapTypes. + std::unordered_map canonicalTypes; + std::unordered_map canonicalHeapTypes; -// Replaces temporary types and heap types in a type definition graph with their -// globally canonical versions to prevent temporary types or heap type from -// leaking into the global stores. -void globallyCanonicalize(CanonicalizationState& state) { - // Map each temporary Type and HeapType to the locations where they will - // have to be replaced with canonical Types and HeapTypes. - struct Locations : TypeGraphWalker { - std::unordered_map> types; - std::unordered_map> heapTypes; - - void preVisitType(Type* type) { - if (!type->isBasic()) { - types[*type].insert(type); - } - } - void preVisitHeapType(HeapType* ht) { - if (!ht->isBasic()) { - heapTypes[*ht].insert(ht); - } - } - }; + // The fully canonicalized heap types. + std::vector results; - Locations locations; - for (auto& type : state.results) { - if (!type.isBasic() && getHeapTypeInfo(type)->isTemp) { - locations.walkRoot(&type); - } - } + Canonicalizer(TypeBuilder& builder); + template void noteChild(T1 parent, T2* child); + void scanHeapType(HeapType* ht); + void scanType(Type* child); + void makeReachabilityFixedPoint(); -#if TRACE_CANONICALIZATION - std::cerr << "Initial Types:\n"; - state.dump(); -#endif - - // Canonicalize HeapTypes at all their use sites. HeapTypes for which there - // was not already a globally canonical version are moved to the global store - // to become the canonical version. These new canonical HeapTypes still - // contain references to temporary Types owned by the TypeBuilder, so we must - // subsequently replace those references with references to canonical Types. - // - // Keep a lock on the global HeapType store as long as it can reach temporary - // types to ensure that no other threads observe the temporary types, for - // example if another thread concurrently constructs a new HeapType with the - // same shape as one being canonicalized here. This cannot happen with Types - // because they are hashed in the global store by pointer identity, which has - // not yet escaped the builder, rather than shape. - std::lock_guard lock(globalHeapTypeStore.mutex); - std::unordered_map canonicalHeapTypes; - for (auto& info : state.newInfos) { - HeapType original = asHeapType(info); - HeapType canonical = globalHeapTypeStore.insert(std::move(info)); - if (original != canonical) { - canonicalHeapTypes[original] = canonical; - } - } - for (auto& [original, canonical] : canonicalHeapTypes) { - for (HeapType* use : locations.heapTypes.at(original)) { - *use = canonical; + // Replaces the pointee Type or HeapType of `type` with its globally canonical + // equivalent, recording the substitution for future use in either + // `canonicalTypes` or `canonicalHeapTypes`. + template + void canonicalize(T* type, std::unordered_map& canonicals); +}; + +// Traverse the type graph rooted at the initialized HeapTypeInfos in reverse +// postorder, replacing in place all Types and HeapTypes backed by the +// TypeBuilder's Stores with equivalent globally canonicalized Types and +// HeapTypes. +Canonicalizer::Canonicalizer(TypeBuilder& builder) : builder(builder) { + // Initialize `results` to hold all the temporary HeapTypes. Since we are + // canonicalizing all Types and HeapTypes in place, this will end up holding + // all the canonicalized HeapTypes instead. Also seed the scan list with these + // HeapTypes. + results.reserve(builder.impl->entries.size()); + for (auto& entry : builder.impl->entries) { + assert(entry.initialized && "Cannot access uninitialized HeapType"); + results.push_back(entry.get()); + scanList.push_back(&results.back()); + } + + // Traverse the type graph reachable from the heap types, calculating + // reachability and collecting a list of types and heap types that need to be + // canonicalized. We must scan in depth-first order so that we can do a + // postorder traversal later. + while (scanList.size() != 0) { + auto item = scanList.back(); + scanList.pop_back(); + switch (item.kind) { + case Item::TypeKind: + scanType(item.type); + break; + case Item::HeapTypeKind: + scanHeapType(item.heapType); + break; } } - // Canonicalize non-tuple Types (which never directly refer to other Types) - // before tuple Types to avoid canonicalizing a tuple that still contains - // non-canonical Types. - auto canonicalizeTypes = [&](bool tuples) { - for (auto& [original, uses] : locations.types) { - if (original.isTuple() == tuples) { - Type canonical = globalTypeStore.insert(*getTypeInfo(original)); - for (Type* use : uses) { - *use = canonical; - } - } + // Check for recursive types and heap types. TODO: pre-canonicalize these into + // their minimal finite representations. + makeReachabilityFixedPoint(); + for (auto& reach : reaches) { + if (reach.second.count(reach.first) != 0) { + WASM_UNREACHABLE("TODO: support recursive types"); } - }; - canonicalizeTypes(false); - canonicalizeTypes(true); - -#if TRACE_CANONICALIZATION - std::cerr << "Final Types:\n"; - state.dump(); -#endif -} - -void canonicalizeEquirecursive(CanonicalizationState& state) { - // Equirecursive types always have null supertypes and recursion groups. - for (auto& info : state.newInfos) { - info->recGroup = nullptr; - info->supertype = nullptr; - } - - // Canonicalize the shape of the type definition graph. - ShapeCanonicalizer minimized(state.results); - state.update(minimized.replacements); -} - -std::optional -validateSubtyping(const std::vector& types) { - if (getTypeSystem() == TypeSystem::Equirecursive) { - // Subtyping is not explicitly declared, so nothing to check. - return {}; } - for (size_t i = 0; i < types.size(); ++i) { - HeapType type = types[i]; - if (type.isBasic()) { - continue; - } - auto* sub = getHeapTypeInfo(type); - auto* super = sub->supertype; - if (super == nullptr) { - continue; - } - - auto fail = [&]() { - return TypeBuilder::Error{i, TypeBuilder::ErrorReason::InvalidSupertype}; - }; - if (sub->kind != super->kind) { - return fail(); - } - SubTyper typer; - switch (sub->kind) { - case HeapTypeInfo::BasicKind: - WASM_UNREACHABLE("unexpected kind"); - case HeapTypeInfo::SignatureKind: - if (!typer.isSubType(sub->signature, super->signature)) { - return fail(); - } - break; - case HeapTypeInfo::StructKind: - if (!typer.isSubType(sub->struct_, super->struct_)) { - return fail(); - } + // Visit the types and heap types in reverse postorder, replacing them with + // their canonicalized versions. + for (auto it = visitList.rbegin(); it != visitList.rend(); ++it) { + switch (it->kind) { + case Item::TypeKind: + canonicalize(it->type, canonicalTypes); break; - case HeapTypeInfo::ArrayKind: - if (!typer.isSubType(sub->array, super->array)) { - return fail(); - } + case Item::HeapTypeKind: + canonicalize(it->heapType, canonicalHeapTypes); break; } } - return {}; } -std::optional -canonicalizeNominal(CanonicalizationState& state) { - for (auto& info : state.newInfos) { - info->recGroup = nullptr; - } - - // Nominal types do not require separate canonicalization, so just validate - // that their subtyping is correct. - - // Ensure there are no cycles in the subtype graph. This is the classic DFA - // algorithm for detecting cycles, but in the form of a simple loop because - // each node (type) has at most one child (supertype). - std::unordered_set checked; - for (size_t i = 0; i < state.results.size(); ++i) { - HeapType type = state.results[i]; - if (type.isBasic()) { - continue; - } - std::unordered_set path; - for (auto* curr = getHeapTypeInfo(type); - curr != nullptr && !checked.count(curr); - curr = curr->supertype) { - if (!path.insert(curr).second) { - return TypeBuilder::Error{i, TypeBuilder::ErrorReason::SelfSupertype}; - } - } - // None of the types in `path` reach themselves. - checked.insert(path.begin(), path.end()); +template +void Canonicalizer::noteChild(T1 parent, T2* child) { + if (child->isCompound()) { + reaches[parent.getID()].insert(child->getID()); + scanList.push_back(child); } - - return {}; } -std::optional canonicalizeIsorecursive( - CanonicalizationState& state, - std::vector>& recGroupInfos) { - // Fill out the recursion groups. - for (auto& info : state.newInfos) { - if (info->recGroup != nullptr) { - info->recGroupIndex = info->recGroup->size(); - info->recGroup->push_back(asHeapType(info)); - } +void Canonicalizer::scanHeapType(HeapType* ht) { + assert(ht->isCompound()); + visitList.push_back(ht); + if (scanned.count(ht->getID())) { + return; } + scanned.insert(ht->getID()); - // Map rec groups to the unique pointers to their infos. - std::unordered_map> groupInfoMap; - for (auto& info : recGroupInfos) { - RecGroup group{uintptr_t(info.get())}; - groupInfoMap[group] = std::move(info); - } - - // Check that supertypes precede their subtypes and that other child types - // either precede their parents or appear later in the same recursion group. - // `indexOfType` both maps types to their indices and keeps track of which - // types we have seen so far. - std::unordered_map indexOfType; - std::vector groups; - size_t groupStart = 0; - - // Validate the children of all types in a recursion group after all the types - // have been registered in `indexOfType`. - auto finishGroup = [&](size_t groupEnd) -> std::optional { - for (size_t index = groupStart; index < groupEnd; ++index) { - HeapType type = state.results[index]; - for (HeapType child : type.getHeapTypeChildren()) { - // Only basic children, globally canonical children, and children - // defined in this or previous recursion groups are allowed. - if (isTemp(child) && !indexOfType.count(child)) { - return {{index, TypeBuilder::ErrorReason::ForwardChildReference}}; - } - } - } - groupStart = groupEnd; - return {}; - }; - - for (size_t index = 0; index < state.results.size(); ++index) { - HeapType type = state.results[index]; - if (type.isBasic()) { - continue; - } - // Validate the supertype. Supertypes must precede their subtypes. - if (auto super = type.getSuperType()) { - if (!indexOfType.count(*super)) { - return {{index, TypeBuilder::ErrorReason::ForwardSupertypeReference}}; - } - } - // Check whether we have finished a rec group. - auto newGroup = type.getRecGroup(); - if (groups.empty() || groups.back() != newGroup) { - if (auto error = finishGroup(index)) { - return *error; + auto* info = getHeapTypeInfo(*ht); + switch (info->kind) { + case HeapTypeInfo::SignatureKind: + noteChild(*ht, &info->signature.params); + noteChild(*ht, &info->signature.results); + break; + case HeapTypeInfo::StructKind: + for (auto& field : info->struct_.fields) { + noteChild(*ht, &field.type); } - groups.push_back(newGroup); - } - // Register this type as seen. - indexOfType.insert({type, index}); - } - if (auto error = finishGroup(state.results.size())) { - return *error; + break; + case HeapTypeInfo::ArrayKind: + noteChild(*ht, &info->array.element.type); + break; } +}; - // Now that we know everything is valid, start canonicalizing recursion - // groups. Before canonicalizing each group, update all the HeapType use sites - // within it to make sure it only refers to other canonical groups or to - // itself (since other groups it refers to may have been duplicates of - // previously canonicalized groups and therefore would not be canonical). To - // canonicalize the group, try to insert it into the global store. If that - // fails, we already have an isorecursively equivalent group, so update the - // replacements accordingly. - CanonicalizationState::ReplacementMap replacements; - { - std::lock_guard lock(globalRecGroupStore.mutex); - groupStart = 0; - for (auto group : groups) { - size_t size = group.size(); - for (size_t i = 0; i < size; ++i) { - state.updateUses(replacements, state.newInfos[groupStart + i]); - } - groupStart += size; - RecGroup canonical(0); - // There may or may not be a `RecGroupInfo` for this group depending on - // whether it is a singleton group or not. If there is one, it is in the - // `groupInfoMap`. Make the info available for the global store to take - // ownership of it in case this group is made the canonical group for its - // structure. - if (auto it = groupInfoMap.find(group); it != groupInfoMap.end()) { - canonical = globalRecGroupStore.insert(std::move(it->second)); - } else { - canonical = globalRecGroupStore.insert(group); - } - if (group != canonical) { - // Replace the non-canonical types with their canonical equivalents. - assert(canonical.size() == size); - for (size_t i = 0; i < size; ++i) { - replacements.insert({group[i], canonical[i]}); - } - } - } +void Canonicalizer::scanType(Type* type) { + assert(type->isCompound()); + visitList.push_back(type); + if (scanned.count(type->getID())) { + return; } - state.updateShallow(replacements); - return {}; -} + scanned.insert(type->getID()); -void canonicalizeBasicTypes(CanonicalizationState& state) { - // Replace heap types backed by BasicKind HeapTypeInfos with their - // corresponding BasicHeapTypes. The heap types backed by BasicKind - // HeapTypeInfos exist only to support building basic types in a TypeBuilder - // and are never canonical. - CanonicalizationState::ReplacementMap replacements; - for (auto& info : state.newInfos) { - if (info->kind == HeapTypeInfo::BasicKind) { - replacements.insert({asHeapType(info), HeapType(info->basic)}); - } - // Basic supertypes should be implicit. - if (info->supertype && info->supertype->kind == HeapTypeInfo::BasicKind) { - info->supertype = nullptr; - } - } - state.update(replacements); - - if (replacements.size()) { - // Canonicalizing basic heap types may cause their parent types to become - // canonicalizable as well, for example after creating `(ref null any)` we - // can futher canonicalize to `anyref`. - struct TypeCanonicalizer : TypeGraphWalkerBase { - void scanType(Type* type) { - if (type->isTuple()) { - TypeGraphWalkerBase::scanType(type); - } else { - *type = asCanonical(*type); - } + auto* info = getTypeInfo(*type); + switch (info->kind) { + case TypeInfo::TupleKind: + for (auto& child : info->tuple.types) { + noteChild(*type, &child); } - }; - for (auto& info : state.newInfos) { - auto root = asHeapType(info); - TypeCanonicalizer{}.walkRoot(&root); - } - } -} - -} // anonymous namespace - -TypeBuilder::BuildResult TypeBuilder::build() { - size_t entryCount = impl->entries.size(); - - // Initialize the canonicalization state using the HeapTypeInfos from the - // builder, marking entries finalized. - CanonicalizationState state; - state.results.reserve(entryCount); - state.newInfos.reserve(entryCount); - for (size_t i = 0; i < entryCount; ++i) { - assert(impl->entries[i].initialized && - "Cannot access uninitialized HeapType"); - auto& info = impl->entries[i].info; - info->isFinalized = true; - state.results.push_back(asHeapType(info)); - state.newInfos.emplace_back(std::move(info)); - } - -#if TRACE_CANONICALIZATION - std::cerr << "Before replacing basic heap types:\n"; - state.dump(); -#endif - - // Eagerly replace references to built basic heap types so the more - // complicated canonicalization algorithms don't need to consider them. - canonicalizeBasicTypes(state); - -#if TRACE_CANONICALIZATION - std::cerr << "After replacing basic heap types:\n"; - state.dump(); -#endif - -#if TIME_CANONICALIZATION - using instant_t = std::chrono::time_point; - auto getMillis = [&](instant_t start, instant_t end) { - return std::chrono::duration_cast(end - start) - .count(); - }; - auto start = std::chrono::steady_clock::now(); -#endif - - switch (typeSystem) { - case TypeSystem::Equirecursive: - canonicalizeEquirecursive(state); break; - case TypeSystem::Nominal: - if (auto error = canonicalizeNominal(state)) { - return {*error}; - } + case TypeInfo::RefKind: + noteChild(*type, &info->ref.heapType); break; - case TypeSystem::Isorecursive: - if (auto error = canonicalizeIsorecursive(state, impl->recGroups)) { - return {*error}; - } + case TypeInfo::RttKind: + noteChild(*type, &info->rtt.heapType); break; } +} -#if TIME_CANONICALIZATION - auto afterStructureCanonicalization = std::chrono::steady_clock::now(); -#endif - - globallyCanonicalize(state); - -#if TIME_CANONICALIZATION - auto end = std::chrono::steady_clock::now(); - std::cerr << "Total canonicalization time was " << getMillis(start, end) - << " ms\n"; - std::cerr << "Structure canonicalization took " - << getMillis(start, afterStructureCanonicalization) << " ms\n"; - std::cerr << "Global canonicalization took " - << getMillis(afterStructureCanonicalization, end) << " ms\n"; -#endif - - // Check that the declared supertypes are structurally valid. - if (auto error = validateSubtyping(state.results)) { - return {*error}; +void Canonicalizer::makeReachabilityFixedPoint() { + // Naively calculate the transitive closure of the reachability graph. + bool changed; + do { + changed = false; + for (auto& entry : reaches) { + auto& reachable = entry.second; + std::unordered_set nextReachable; + for (auto& other : reachable) { + auto& otherReaches = reaches[other]; + nextReachable.insert(otherReaches.begin(), otherReaches.end()); + } + size_t oldSize = reachable.size(); + reachable.insert(nextReachable.begin(), nextReachable.end()); + if (reachable.size() != oldSize) { + changed = true; + } + } + } while (changed); +} + +template +void Canonicalizer::canonicalize(T* type, + std::unordered_map& canonicals) { + auto it = canonicals.find(*type); + if (it != canonicals.end()) { + *type = it->second; + } else { + // Get the globally canonicalized version of the type + auto* info = MetaTypeInfo::getInfo(*type); + T canonical = MetaTypeInfo::globalStore.canonicalize(*info); + canonicals.insert({*type, canonical}); + *type = canonical; } +} - // Note built signature types. See comment in `HeapType::HeapType(Signature)`. - for (auto type : state.results) { - if (type.isSignature() && (getTypeSystem() == TypeSystem::Nominal)) { - nominalSignatureCache.insertType(type); - } - } +} // anonymous namespace - return {state.results}; +std::vector TypeBuilder::build() { + return Canonicalizer(*this).results; } } // namespace wasm @@ -3943,6 +1317,40 @@ } }; +size_t hash::operator()(const wasm::TypeInfo& info) const { + auto digest = wasm::hash(info.kind); + switch (info.kind) { + case wasm::TypeInfo::TupleKind: + wasm::rehash(digest, info.tuple); + return digest; + case wasm::TypeInfo::RefKind: + wasm::rehash(digest, info.ref.heapType); + wasm::rehash(digest, info.ref.nullable); + return digest; + case wasm::TypeInfo::RttKind: + wasm::rehash(digest, info.rtt); + return digest; + } + WASM_UNREACHABLE("unexpected kind"); +} + +size_t hash:: +operator()(const wasm::HeapTypeInfo& info) const { + auto digest = wasm::hash(info.kind); + switch (info.kind) { + case wasm::HeapTypeInfo::SignatureKind: + wasm::rehash(digest, info.signature); + return digest; + case wasm::HeapTypeInfo::StructKind: + wasm::rehash(digest, info.struct_); + return digest; + case wasm::HeapTypeInfo::ArrayKind: + wasm::rehash(digest, info.array); + return digest; + } + WASM_UNREACHABLE("unexpected kind"); +} + size_t hash::operator()(const wasm::Type& type) const { return wasm::hash(type.getID()); } @@ -3961,6 +1369,8 @@ auto digest = wasm::hash(field.type); wasm::rehash(digest, field.packedType); wasm::rehash(digest, field.mutable_); + // Note that the name is not hashed here - it is pure metadata for printing + // purposes only. return digest; } @@ -3976,36 +1386,10 @@ return wasm::hash(heapType.getID()); } -size_t hash::operator()(const wasm::RecGroup& group) const { - return wasm::hash(group.getID()); -} - size_t hash::operator()(const wasm::Rtt& rtt) const { auto digest = wasm::hash(rtt.depth); wasm::rehash(digest, rtt.heapType); return digest; } -size_t hash::operator()(const wasm::TypeInfo& info) const { - auto digest = wasm::hash(info.kind); - switch (info.kind) { - case wasm::TypeInfo::TupleKind: - wasm::rehash(digest, info.tuple); - return digest; - case wasm::TypeInfo::RefKind: - wasm::rehash(digest, info.ref.nullable); - wasm::rehash(digest, info.ref.heapType); - return digest; - case wasm::TypeInfo::RttKind: - wasm::rehash(digest, info.rtt); - return digest; - } - WASM_UNREACHABLE("unexpected kind"); -} - -size_t -hash::operator()(const wasm::HeapTypeInfo& info) const { - return wasm::FiniteShapeHasher().hash(info); -} - } // namespace std diff -Nru binaryen-108/src/wasm/wasm-validator.cpp binaryen-99/src/wasm/wasm-validator.cpp --- binaryen-108/src/wasm/wasm-validator.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm/wasm-validator.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -19,10 +19,8 @@ #include #include -#include "ir/eh-utils.h" #include "ir/features.h" #include "ir/global-utils.h" -#include "ir/intrinsics.h" #include "ir/module-utils.h" #include "ir/stack-utils.h" #include "ir/utils.h" @@ -37,25 +35,22 @@ typename std::enable_if::type>::value>::type* = nullptr> -inline std::ostream& -printModuleComponent(T curr, std::ostream& stream, Module& wasm) { +inline std::ostream& printModuleComponent(T curr, std::ostream& stream) { stream << curr << std::endl; return stream; } // Extra overload for Expressions, to print their contents. -inline std::ostream& -printModuleComponent(Expression* curr, std::ostream& stream, Module& wasm) { +inline std::ostream& printModuleComponent(Expression* curr, + std::ostream& stream) { if (curr) { - stream << ModuleExpression(wasm, curr) << '\n'; + stream << *curr << '\n'; } return stream; } // For parallel validation, we have a helper struct for coordination struct ValidationInfo { - Module& wasm; - bool validateWeb; bool validateGlobally; bool quiet; @@ -68,7 +63,7 @@ std::mutex mutex; std::unordered_map> outputs; - ValidationInfo(Module& wasm) : wasm(wasm) { valid.store(true); } + ValidationInfo() { valid.store(true); } std::ostringstream& getStream(Function* func) { std::unique_lock lock(mutex); @@ -91,7 +86,7 @@ } auto& ret = printFailureHeader(func); ret << text << ", on \n"; - return printModuleComponent(curr, ret, wasm); + return printModuleComponent(curr, ret); } std::ostream& printFailureHeader(Function* func) { @@ -201,32 +196,48 @@ fail(text, curr, func); return false; } + + // Type 'left' should be a subtype of 'right', or unreachable. + bool shouldBeSubTypeOrFirstIsUnreachable(Type left, + Type right, + Expression* curr, + const char* text, + Function* func = nullptr) { + if (left == Type::unreachable) { + return true; + } + return shouldBeSubType(left, right, curr, text, func); + } }; struct FunctionValidator : public WalkerPass> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new FunctionValidator(*getModule(), &info); } + Pass* create() override { return new FunctionValidator(&info); } bool modifiesBinaryenIR() override { return false; } ValidationInfo& info; - FunctionValidator(Module& wasm, ValidationInfo* info) : info(*info) { - setModule(&wasm); - } + FunctionValidator(ValidationInfo* info) : info(*info) {} - // Validate the entire module. - void validate(PassRunner* runner) { run(runner, getModule()); } + struct BreakInfo { + enum { UnsetArity = Index(-1), PoisonArity = Index(-2) }; - // Validate a specific expression. - void validate(Expression* curr) { walk(curr); } + Type type; + Index arity; + BreakInfo() : arity(UnsetArity) {} + BreakInfo(Type type, Index arity) : type(type), arity(arity) {} + + bool hasBeenSet() { + // Compare to the impossible value. + return arity != UnsetArity; + } + }; - std::unordered_map> breakTypes; - std::unordered_set delegateTargetNames; - std::unordered_set rethrowTargetNames; + std::unordered_map breakInfos; - std::unordered_set returnTypes; // types used in returns + std::set returnTypes; // types used in returns // Binaryen IR requires that label names must be unique - IR generators must // ensure that @@ -247,7 +258,7 @@ static void visitPreBlock(FunctionValidator* self, Expression** currp) { auto* curr = (*currp)->cast(); if (curr->name.is()) { - self->breakTypes[curr->name]; + self->breakInfos[curr->name]; } } @@ -258,60 +269,18 @@ static void visitPreLoop(FunctionValidator* self, Expression** currp) { auto* curr = (*currp)->cast(); if (curr->name.is()) { - self->breakTypes[curr->name]; + self->breakInfos[curr->name]; } } void visitLoop(Loop* curr); void visitIf(If* curr); - static void visitPreTry(FunctionValidator* self, Expression** currp) { - auto* curr = (*currp)->cast(); - if (curr->name.is()) { - self->delegateTargetNames.insert(curr->name); - } - } - - // We remove try's label before proceeding to verify catch bodies because the - // following is a validation failure: - // (try $l0 - // (do ... ) - // (catch $e - // (try - // (do ...) - // (delegate $l0) ;; validation failure - // ) - // ) - // ) - // Unlike branches, if delegate's target 'catch' is located above the - // delegate, it is a validation failure. - static void visitPreCatch(FunctionValidator* self, Expression** currp) { - auto* curr = (*currp)->cast(); - if (curr->name.is()) { - self->delegateTargetNames.erase(curr->name); - self->rethrowTargetNames.insert(curr->name); - } - } - // override scan to add a pre and a post check task to all nodes static void scan(FunctionValidator* self, Expression** currp) { - auto* curr = *currp; - // Treat 'Try' specially because we need to run visitPreCatch between the - // try body and catch bodies - if (curr->is()) { - self->pushTask(doVisitTry, currp); - auto& list = curr->cast()->catchBodies; - for (int i = int(list.size()) - 1; i >= 0; i--) { - self->pushTask(scan, &list[i]); - } - self->pushTask(visitPreCatch, currp); - self->pushTask(scan, &curr->cast()->body); - self->pushTask(visitPreTry, currp); - return; - } - PostWalker::scan(self, currp); + auto* curr = *currp; if (curr->is()) { self->pushTask(visitPreBlock, currp); } @@ -362,18 +331,13 @@ void visitMemorySize(MemorySize* curr); void visitMemoryGrow(MemoryGrow* curr); void visitRefNull(RefNull* curr); - void visitRefIs(RefIs* curr); + void visitRefIsNull(RefIsNull* curr); void visitRefFunc(RefFunc* curr); void visitRefEq(RefEq* curr); - void visitTableGet(TableGet* curr); - void visitTableSet(TableSet* curr); - void visitTableSize(TableSize* curr); - void visitTableGrow(TableGrow* curr); - void noteDelegate(Name name, Expression* curr); - void noteRethrow(Name name, Expression* curr); void visitTry(Try* curr); void visitThrow(Throw* curr); void visitRethrow(Rethrow* curr); + void visitBrOnExn(BrOnExn* curr); void visitTupleMake(TupleMake* curr); void visitTupleExtract(TupleExtract* curr); void visitCallRef(CallRef* curr); @@ -381,18 +345,16 @@ void visitI31Get(I31Get* curr); void visitRefTest(RefTest* curr); void visitRefCast(RefCast* curr); - void visitBrOn(BrOn* curr); + void visitBrOnCast(BrOnCast* curr); void visitRttCanon(RttCanon* curr); void visitRttSub(RttSub* curr); void visitStructNew(StructNew* curr); void visitStructGet(StructGet* curr); void visitStructSet(StructSet* curr); void visitArrayNew(ArrayNew* curr); - void visitArrayInit(ArrayInit* curr); void visitArrayGet(ArrayGet* curr); void visitArraySet(ArraySet* curr); void visitArrayLen(ArrayLen* curr); - void visitArrayCopy(ArrayCopy* curr); void visitFunction(Function* curr); // helpers @@ -434,6 +396,14 @@ return info.shouldBeSubType(left, right, curr, text, getFunction()); } + bool shouldBeSubTypeOrFirstIsUnreachable(Type left, + Type right, + Expression* curr, + const char* text) { + return info.shouldBeSubTypeOrFirstIsUnreachable( + left, right, curr, text, getFunction()); + } + void validateAlignment( size_t align, Type type, Index bytes, bool isAtomic, Expression* curr); void validateMemBytes(uint8_t bytes, Type type, Expression* curr); @@ -445,12 +415,7 @@ } template - void validateCallParamsAndResult(T* curr, HeapType sigType) { - if (!shouldBeTrue( - sigType.isSignature(), curr, "Heap type must be a signature type")) { - return; - } - auto sig = sigType.getSignature(); + void validateCallParamsAndResult(T* curr, Signature sig) { if (!shouldBeTrue(curr->operands.size() == sig.params.size(), curr, "call* param number must match")) { @@ -458,10 +423,10 @@ } size_t i = 0; for (const auto& param : sig.params) { - if (!shouldBeSubType(curr->operands[i]->type, - param, - curr, - "call param types must match") && + if (!shouldBeSubTypeOrFirstIsUnreachable(curr->operands[i]->type, + param, + curr, + "call param types must match") && !info.quiet) { getStream() << "(on argument " << i << ")\n"; } @@ -472,9 +437,9 @@ Type(Type::unreachable), curr, "return_call* should have unreachable type"); - shouldBeSubType( + shouldBeEqual( + getFunction()->sig.results, sig.results, - getFunction()->getResults(), curr, "return_call* callee return type must match caller return type"); } else { @@ -493,7 +458,8 @@ if (!name.is()) { return; } - auto [_, inserted] = labelNames.insert(name); + bool inserted; + std::tie(std::ignore, inserted) = labelNames.insert(name); shouldBeTrue( inserted, name, @@ -542,17 +508,49 @@ // if we are break'ed to, then the value must be right for us if (curr->name.is()) { noteLabelName(curr->name); - auto iter = breakTypes.find(curr->name); - assert(iter != breakTypes.end()); // we set it ourselves - for (Type breakType : iter->second) { + auto iter = breakInfos.find(curr->name); + assert(iter != breakInfos.end()); // we set it ourselves + auto& info = iter->second; + if (info.hasBeenSet()) { + if (curr->type.isConcrete()) { + shouldBeTrue(info.arity != 0, + curr, + "break arities must be > 0 if block has a value"); + } else { + shouldBeTrue(info.arity == 0, + curr, + "break arities must be 0 if block has no value"); + } // none or unreachable means a poison value that we should ignore - if // consumed, it will error - shouldBeSubType(breakType, - curr->type, - curr, - "break type must be a subtype of the target block type"); + if (info.type.isConcrete() && curr->type.isConcrete()) { + shouldBeSubType( + info.type, + curr->type, + curr, + "block+breaks must have right type if breaks return a value"); + } + if (curr->type.isConcrete() && info.arity && + info.type != Type::unreachable) { + shouldBeSubType( + info.type, + curr->type, + curr, + "block+breaks must have right type if breaks have arity"); + } + shouldBeTrue( + info.arity != BreakInfo::PoisonArity, curr, "break arities must match"); + if (curr->list.size() > 0) { + auto last = curr->list.back()->type; + if (last == Type::none) { + shouldBeTrue(info.arity == Index(0), + curr, + "if block ends with a none, breaks cannot send a value " + "of any type"); + } + } } - breakTypes.erase(iter); + breakInfos.erase(iter); } switch (getFunction()->profile) { case IRProfile::Normal: @@ -623,8 +621,8 @@ !info.quiet) { getStream() << "(on index " << i << ":\n" << expr << "\n), required: " << sig.params << ", available: "; - if (blockSig.kind == StackSignature::Polymorphic) { - getStream() << "polymorphic, "; + if (blockSig.unreachable) { + getStream() << "unreachable, "; } getStream() << blockSig.results << "\n"; return; @@ -632,22 +630,16 @@ blockSig += sig; } if (curr->type == Type::unreachable) { - shouldBeTrue(blockSig.kind == StackSignature::Polymorphic, + shouldBeTrue(blockSig.unreachable, curr, "unreachable block should have unreachable element"); } else { - if (!shouldBeTrue( - StackSignature::isSubType( - blockSig, - StackSignature(Type::none, curr->type, StackSignature::Fixed)), - curr, - "block contents should satisfy block type") && + if (!shouldBeTrue(blockSig.satisfies(Signature(Type::none, curr->type)), + curr, + "block contents should satisfy block type") && !info.quiet) { getStream() << "contents: " << blockSig.results - << (blockSig.kind == StackSignature::Polymorphic - ? " [polymorphic]" - : "") - << "\n" + << (blockSig.unreachable ? " [unreachable]" : "") << "\n" << "expected: " << curr->type << "\n"; } } @@ -656,15 +648,14 @@ void FunctionValidator::visitLoop(Loop* curr) { if (curr->name.is()) { noteLabelName(curr->name); - auto iter = breakTypes.find(curr->name); - assert(iter != breakTypes.end()); // we set it ourselves - for (Type breakType : iter->second) { - shouldBeEqual(breakType, - Type(Type::none), - curr, - "breaks to a loop cannot pass a value"); + auto iter = breakInfos.find(curr->name); + assert(iter != breakInfos.end()); // we set it ourselves + auto& info = iter->second; + if (info.hasBeenSet()) { + shouldBeEqual( + info.arity, Index(0), curr, "breaks to a loop cannot pass a value"); } - breakTypes.erase(iter); + breakInfos.erase(iter); } if (curr->type == Type::none) { shouldBeFalse(curr->body->type.isConcrete(), @@ -682,10 +673,11 @@ "if loop is not returning a value, final element should " "not flow out a value"); } else { - shouldBeSubType(curr->body->type, - curr->type, - curr, - "loop with value and body must match types"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->body->type, + curr->type, + curr, + "loop with value and body must match types"); } } } @@ -707,14 +699,16 @@ } } else { if (curr->type != Type::unreachable) { - shouldBeSubType(curr->ifTrue->type, - curr->type, - curr, - "returning if-else's true must have right type"); - shouldBeSubType(curr->ifFalse->type, - curr->type, - curr, - "returning if-else's false must have right type"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->ifTrue->type, + curr->type, + curr, + "returning if-else's true must have right type"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->ifFalse->type, + curr->type, + curr, + "returning if-else's false must have right type"); } else { if (curr->condition->type != Type::unreachable) { shouldBeEqual(curr->ifTrue->type, @@ -753,14 +747,25 @@ } void FunctionValidator::noteBreak(Name name, Type valueType, Expression* curr) { - auto iter = breakTypes.find(name); + Index arity = 0; + if (valueType != Type::none) { + arity = 1; + } + auto iter = breakInfos.find(name); if (!shouldBeTrue( - iter != breakTypes.end(), curr, "all break targets must be valid")) { + iter != breakInfos.end(), curr, "all break targets must be valid")) { return; } - iter->second.insert(valueType); + auto& info = iter->second; + if (!info.hasBeenSet()) { + info = BreakInfo(valueType, arity); + } else { + info.type = Type::getLeastUpperBound(info.type, valueType); + if (arity != info.arity) { + info.arity = BreakInfo::PoisonArity; + } + } } - void FunctionValidator::visitBreak(Break* curr) { noteBreak(curr->name, curr->value, curr); if (curr->value) { @@ -796,7 +801,7 @@ if (!shouldBeTrue(!!target, curr, "call target must exist")) { return; } - validateCallParamsAndResult(curr, target->type); + validateCallParamsAndResult(curr, target->sig); } void FunctionValidator::visitCallIndirect(CallIndirect* curr) { @@ -805,18 +810,7 @@ Type(Type::i32), curr, "indirect call target must be an i32"); - - if (curr->target->type != Type::unreachable) { - auto* table = getModule()->getTableOrNull(curr->table); - shouldBeTrue(!!table, curr, "call-indirect table must exist"); - if (table) { - shouldBeTrue(table->type.isFunction(), - curr, - "call-indirect table must be of function type."); - } - } - - validateCallParamsAndResult(curr, curr->heapType); + validateCallParamsAndResult(curr, curr->sig); } void FunctionValidator::visitConst(Const* curr) { @@ -877,10 +871,11 @@ "global.set name must be valid (and not an import; imports " "can't be modified)")) { shouldBeTrue(global->mutable_, curr, "global.set global must be mutable"); - shouldBeSubType(curr->value->type, - global->type, - curr, - "global.set value must have right type"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->value->type, + global->type, + curr, + "global.set value must have right type"); } } @@ -1154,7 +1149,7 @@ shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( - curr->type, Type(Type::v128), curr, "i8x16.shuffle must have type v128"); + curr->type, Type(Type::v128), curr, "v128.shuffle must have type v128"); shouldBeEqualOrFirstIsUnreachable( curr->left->type, Type(Type::v128), curr, "expected operand of type v128"); shouldBeEqualOrFirstIsUnreachable( @@ -1204,20 +1199,20 @@ "load_splat address must match memory index type"); Type memAlignType = Type::none; switch (curr->op) { - case Load8SplatVec128: - case Load16SplatVec128: - case Load32SplatVec128: - case Load32ZeroVec128: + case LoadSplatVec8x16: + case LoadSplatVec16x8: + case LoadSplatVec32x4: + case Load32Zero: memAlignType = Type::i32; break; - case Load64SplatVec128: - case Load8x8SVec128: - case Load8x8UVec128: - case Load16x4SVec128: - case Load16x4UVec128: - case Load32x2SVec128: - case Load32x2UVec128: - case Load64ZeroVec128: + case LoadSplatVec64x2: + case LoadExtSVec8x8ToVecI16x8: + case LoadExtUVec8x8ToVecI16x8: + case LoadExtSVec16x4ToVecI32x4: + case LoadExtUVec16x4ToVecI32x4: + case LoadExtSVec32x2ToVecI64x2: + case LoadExtUVec32x2ToVecI64x2: + case Load64Zero: memAlignType = Type::i64; break; } @@ -1250,23 +1245,23 @@ size_t lanes; Type memAlignType = Type::none; switch (curr->op) { - case Load8LaneVec128: - case Store8LaneVec128: + case LoadLaneVec8x16: + case StoreLaneVec8x16: lanes = 16; memAlignType = Type::i32; break; - case Load16LaneVec128: - case Store16LaneVec128: + case LoadLaneVec16x8: + case StoreLaneVec16x8: lanes = 8; memAlignType = Type::i32; break; - case Load32LaneVec128: - case Store32LaneVec128: + case LoadLaneVec32x4: + case StoreLaneVec32x4: lanes = 4; memAlignType = Type::i32; break; - case Load64LaneVec128: - case Store64LaneVec128: + case LoadLaneVec64x2: + case StoreLaneVec64x2: lanes = 2; memAlignType = Type::i64; break; @@ -1399,10 +1394,11 @@ case Type::unreachable: break; case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -1540,11 +1536,6 @@ case GeSVecI32x4: case GeUVecI32x4: case EqVecI64x2: - case NeVecI64x2: - case LtSVecI64x2: - case LeSVecI64x2: - case GtSVecI64x2: - case GeSVecI64x2: case EqVecF32x4: case NeVecF32x4: case LtVecF32x4: @@ -1567,6 +1558,7 @@ case SubVecI8x16: case SubSatSVecI8x16: case SubSatUVecI8x16: + case MulVecI8x16: case MinSVecI8x16: case MinUVecI8x16: case MaxSVecI8x16: @@ -1616,8 +1608,6 @@ case MaxVecF32x4: case PMinVecF32x4: case PMaxVecF32x4: - case RelaxedMinVecF32x4: - case RelaxedMaxVecF32x4: case AddVecF64x2: case SubVecF64x2: case MulVecF64x2: @@ -1626,17 +1616,11 @@ case MaxVecF64x2: case PMinVecF64x2: case PMaxVecF64x2: - case RelaxedMinVecF64x2: - case RelaxedMaxVecF64x2: case NarrowSVecI16x8ToVecI8x16: case NarrowUVecI16x8ToVecI8x16: case NarrowSVecI32x4ToVecI16x8: case NarrowUVecI32x4ToVecI16x8: - case SwizzleVecI8x16: - case RelaxedSwizzleVecI8x16: - case RelaxedQ15MulrSVecI16x8: - case DotI8x16I7x16SToVecI16x8: - case DotI8x16I7x16UToVecI16x8: { + case SwizzleVec8x16: { shouldBeEqualOrFirstIsUnreachable( curr->left->type, Type(Type::v128), curr, "v128 op"); shouldBeEqualOrFirstIsUnreachable( @@ -1864,7 +1848,6 @@ case AbsVecI8x16: case AbsVecI16x8: case AbsVecI32x4: - case AbsVecI64x2: case NegVecI8x16: case NegVecI16x8: case NegVecI32x4: @@ -1889,39 +1872,34 @@ case ExtAddPairwiseUVecI16x8ToI32x4: case TruncSatSVecF32x4ToVecI32x4: case TruncSatUVecF32x4ToVecI32x4: + case TruncSatSVecF64x2ToVecI64x2: + case TruncSatUVecF64x2ToVecI64x2: case ConvertSVecI32x4ToVecF32x4: case ConvertUVecI32x4ToVecF32x4: - case ExtendLowSVecI8x16ToVecI16x8: - case ExtendHighSVecI8x16ToVecI16x8: - case ExtendLowUVecI8x16ToVecI16x8: - case ExtendHighUVecI8x16ToVecI16x8: - case ExtendLowSVecI16x8ToVecI32x4: - case ExtendHighSVecI16x8ToVecI32x4: - case ExtendLowUVecI16x8ToVecI32x4: - case ExtendHighUVecI16x8ToVecI32x4: - case ExtendLowSVecI32x4ToVecI64x2: - case ExtendHighSVecI32x4ToVecI64x2: - case ExtendLowUVecI32x4ToVecI64x2: - case ExtendHighUVecI32x4ToVecI64x2: - case ConvertLowSVecI32x4ToVecF64x2: - case ConvertLowUVecI32x4ToVecF64x2: - case TruncSatZeroSVecF64x2ToVecI32x4: - case TruncSatZeroUVecF64x2ToVecI32x4: - case DemoteZeroVecF64x2ToVecF32x4: - case PromoteLowVecF32x4ToVecF64x2: - case RelaxedTruncSVecF32x4ToVecI32x4: - case RelaxedTruncUVecF32x4ToVecI32x4: - case RelaxedTruncZeroSVecF64x2ToVecI32x4: - case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case ConvertSVecI64x2ToVecF64x2: + case ConvertUVecI64x2ToVecF64x2: + case WidenLowSVecI8x16ToVecI16x8: + case WidenHighSVecI8x16ToVecI16x8: + case WidenLowUVecI8x16ToVecI16x8: + case WidenHighUVecI8x16ToVecI16x8: + case WidenLowSVecI16x8ToVecI32x4: + case WidenHighSVecI16x8ToVecI32x4: + case WidenLowUVecI16x8ToVecI32x4: + case WidenHighUVecI16x8ToVecI32x4: + case WidenLowSVecI32x4ToVecI64x2: + case WidenHighSVecI32x4ToVecI64x2: + case WidenLowUVecI32x4ToVecI64x2: + case WidenHighUVecI32x4ToVecI64x2: shouldBeEqual(curr->type, Type(Type::v128), curr, "expected v128 type"); shouldBeEqual( curr->value->type, Type(Type::v128), curr, "expected v128 operand"); break; - case AnyTrueVec128: + case AnyTrueVecI8x16: + case AnyTrueVecI16x8: + case AnyTrueVecI32x4: case AllTrueVecI8x16: case AllTrueVecI16x8: case AllTrueVecI32x4: - case AllTrueVecI64x2: case BitmaskVecI8x16: case BitmaskVecI16x8: case BitmaskVecI32x4: @@ -1991,31 +1969,25 @@ } void FunctionValidator::visitRefNull(RefNull* curr) { - // If we are not in a function, this is a global location like a table. We - // allow RefNull there as we represent tables that way regardless of what - // features are enabled. - shouldBeTrue(!getFunction() || getModule()->features.hasReferenceTypes(), + shouldBeTrue(getModule()->features.hasReferenceTypes(), curr, "ref.null requires reference-types to be enabled"); shouldBeTrue( curr->type.isNullable(), curr, "ref.null types must be nullable"); } -void FunctionValidator::visitRefIs(RefIs* curr) { +void FunctionValidator::visitRefIsNull(RefIsNull* curr) { shouldBeTrue(getModule()->features.hasReferenceTypes(), curr, - "ref.is_* requires reference-types to be enabled"); + "ref.is_null requires reference-types to be enabled"); shouldBeTrue(curr->value->type == Type::unreachable || curr->value->type.isRef(), curr->value, - "ref.is_*'s argument should be a reference type"); + "ref.is_null's argument should be a reference type"); } void FunctionValidator::visitRefFunc(RefFunc* curr) { - // If we are not in a function, this is a global location like a table. We - // allow RefFunc there as we represent tables that way regardless of what - // features are enabled. - shouldBeTrue(!getFunction() || getModule()->features.hasReferenceTypes(), + shouldBeTrue(getModule()->features.hasReferenceTypes(), curr, "ref.func requires reference-types to be enabled"); if (!info.validateGlobally) { @@ -2026,209 +1998,49 @@ shouldBeTrue(curr->type.isFunction(), curr, "ref.func must have a function reference type"); - shouldBeTrue( - !curr->type.isNullable(), curr, "ref.func must have non-nullable type"); - // TODO: verify it also has a typed function references type, and the right - // one, - // curr->type.getHeapType().getSignature() - // That is blocked on having the ability to create signature types in the C - // API (for now those users create the type with funcref). This also needs to - // be fixed in LegalizeJSInterface and FuncCastEmulation and other places that - // update function types. // TODO: check for non-nullability } void FunctionValidator::visitRefEq(RefEq* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "ref.eq requires gc to be enabled"); - shouldBeSubType(curr->left->type, - Type::eqref, - curr->left, - "ref.eq's left argument should be a subtype of eqref"); - shouldBeSubType(curr->right->type, - Type::eqref, - curr->right, - "ref.eq's right argument should be a subtype of eqref"); -} - -void FunctionValidator::visitTableGet(TableGet* curr) { - shouldBeTrue(getModule()->features.hasReferenceTypes(), - curr, - "table.get requires reference types to be enabled"); - shouldBeEqualOrFirstIsUnreachable( - curr->index->type, Type(Type::i32), curr, "table.get index must be an i32"); - auto* table = getModule()->getTableOrNull(curr->table); - if (shouldBeTrue(!!table, curr, "table.get table must exist") && - curr->type != Type::unreachable) { - shouldBeEqual( - curr->type, table->type, curr, "table.get must have same type as table."); - } -} - -void FunctionValidator::visitTableSet(TableSet* curr) { - shouldBeTrue(getModule()->features.hasReferenceTypes(), - curr, - "table.set requires reference types to be enabled"); - shouldBeEqualOrFirstIsUnreachable( - curr->index->type, Type(Type::i32), curr, "table.set index must be an i32"); - auto* table = getModule()->getTableOrNull(curr->table); - if (shouldBeTrue(!!table, curr, "table.set table must exist") && - curr->type != Type::unreachable) { - shouldBeSubType(curr->value->type, - table->type, - curr, - "table.set value must have right type"); - } -} - -void FunctionValidator::visitTableSize(TableSize* curr) { - shouldBeTrue(getModule()->features.hasReferenceTypes(), - curr, - "table.size requires reference types to be enabled"); - auto* table = getModule()->getTableOrNull(curr->table); - shouldBeTrue(!!table, curr, "table.size table must exist"); -} - -void FunctionValidator::visitTableGrow(TableGrow* curr) { - shouldBeTrue(getModule()->features.hasReferenceTypes(), - curr, - "table.grow requires reference types to be enabled"); - auto* table = getModule()->getTableOrNull(curr->table); - if (shouldBeTrue(!!table, curr, "table.grow table must exist") && - curr->type != Type::unreachable) { - shouldBeSubType(curr->value->type, - table->type, - curr, - "table.grow value must have right type"); - shouldBeEqual(curr->delta->type, - Type(Type::i32), - curr, - "table.grow must match table index type"); - } -} - -void FunctionValidator::noteDelegate(Name name, Expression* curr) { - if (name != DELEGATE_CALLER_TARGET) { - shouldBeTrue(delegateTargetNames.count(name) != 0, - curr, - "all delegate targets must be valid"); - } -} - -void FunctionValidator::noteRethrow(Name name, Expression* curr) { - shouldBeTrue(rethrowTargetNames.count(name) != 0, - curr, - "all rethrow targets must be valid"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->left->type, + Type::eqref, + curr->left, + "ref.eq's left argument should be a subtype of eqref"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->right->type, + Type::eqref, + curr->right, + "ref.eq's right argument should be a subtype of eqref"); } void FunctionValidator::visitTry(Try* curr) { shouldBeTrue(getModule()->features.hasExceptionHandling(), curr, "try requires exception-handling to be enabled"); - if (curr->name.is()) { - noteLabelName(curr->name); - } if (curr->type != Type::unreachable) { - shouldBeSubType(curr->body->type, - curr->type, - curr->body, - "try's type does not match try body's type"); - for (auto catchBody : curr->catchBodies) { - shouldBeSubType(catchBody->type, - curr->type, - catchBody, - "try's type does not match catch's body type"); - } + shouldBeSubTypeOrFirstIsUnreachable( + curr->body->type, + curr->type, + curr->body, + "try's type does not match try body's type"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->catchBody->type, + curr->type, + curr->catchBody, + "try's type does not match catch's body type"); } else { shouldBeEqual(curr->body->type, Type(Type::unreachable), curr, "unreachable try-catch must have unreachable try body"); - for (auto catchBody : curr->catchBodies) { - shouldBeEqual(catchBody->type, - Type(Type::unreachable), - curr, - "unreachable try-catch must have unreachable catch body"); - } - } - shouldBeTrue(curr->catchBodies.size() - curr->catchTags.size() <= 1, - curr, - "the number of catch blocks and tags do not match"); - - shouldBeFalse(curr->isCatch() && curr->isDelegate(), - curr, - "try cannot have both catch and delegate at the same time"); - - // Given a catch body, find pops corresponding to the catch - auto findPops = [](Expression* expr) { - SmallVector pops; - SmallVector work; - work.push_back(expr); - while (!work.empty()) { - auto* curr = work.back(); - work.pop_back(); - if (auto* pop = curr->dynCast()) { - pops.push_back(pop); - } else if (auto* try_ = curr->dynCast()) { - // We don't go into inner catch bodies; pops in inner catch bodies - // belong to the inner catches - work.push_back(try_->body); - } else { - for (auto* child : ChildIterator(curr)) { - work.push_back(child); - } - } - } - return pops; - }; - - for (Index i = 0; i < curr->catchTags.size(); i++) { - Name tagName = curr->catchTags[i]; - auto* tag = getModule()->getTagOrNull(tagName); - if (!shouldBeTrue(tag != nullptr, curr, "")) { - getStream() << "tag name is invalid: " << tagName << "\n"; - } - - auto* catchBody = curr->catchBodies[i]; - SmallVector pops = findPops(catchBody); - if (tag->sig.params == Type::none) { - if (!shouldBeTrue(pops.empty(), curr, "")) { - getStream() << "catch's tag (" << tagName - << ") doesn't have any params, but there are pops"; - } - } else { - if (shouldBeTrue(pops.size() == 1, curr, "")) { - auto* pop = *pops.begin(); - if (!shouldBeSubType(pop->type, tag->sig.params, curr, "")) { - getStream() - << "catch's tag (" << tagName - << ")'s pop doesn't have the same type as the tag's params"; - } - if (!shouldBeTrue( - EHUtils::containsValidDanglingPop(catchBody), curr, "")) { - getStream() << "catch's body (" << tagName - << ")'s pop's location is not valid"; - } - } else { - getStream() << "catch's tag (" << tagName - << ") has params, so there should be a single pop within " - "the catch body"; - } - } - } - - if (curr->hasCatchAll()) { - auto* catchAllBody = curr->catchBodies.back(); - shouldBeTrue(findPops(catchAllBody).empty(), - curr, - "catch_all's body should not have pops"); - } - - if (curr->isDelegate()) { - noteDelegate(curr->delegateTarget, curr); + shouldBeEqual(curr->catchBody->type, + Type(Type::unreachable), + curr, + "unreachable try-catch must have unreachable catch body"); } - - rethrowTargetNames.erase(curr->name); } void FunctionValidator::visitThrow(Throw* curr) { @@ -2242,21 +2054,21 @@ if (!info.validateGlobally) { return; } - auto* tag = getModule()->getTagOrNull(curr->tag); - if (!shouldBeTrue(!!tag, curr, "throw's tag must exist")) { + auto* event = getModule()->getEventOrNull(curr->event); + if (!shouldBeTrue(!!event, curr, "throw's event must exist")) { return; } - if (!shouldBeTrue(curr->operands.size() == tag->sig.params.size(), + if (!shouldBeTrue(curr->operands.size() == event->sig.params.size(), curr, - "tag's param numbers must match")) { + "event's param numbers must match")) { return; } size_t i = 0; - for (const auto& param : tag->sig.params) { - if (!shouldBeSubType(curr->operands[i]->type, - param, - curr->operands[i], - "tag param types must match") && + for (const auto& param : event->sig.params) { + if (!shouldBeSubTypeOrFirstIsUnreachable(curr->operands[i]->type, + param, + curr->operands[i], + "event param types must match") && !info.quiet) { getStream() << "(on argument " << i << ")\n"; } @@ -2272,7 +2084,39 @@ Type(Type::unreachable), curr, "rethrow's type must be unreachable"); - noteRethrow(curr->target, curr); + shouldBeSubTypeOrFirstIsUnreachable( + curr->exnref->type, + Type::exnref, + curr->exnref, + "rethrow's argument must be exnref type or its subtype"); +} + +void FunctionValidator::visitBrOnExn(BrOnExn* curr) { + shouldBeTrue(getModule()->features.hasExceptionHandling(), + curr, + "br_on_exn requires exception-handling to be enabled"); + Event* event = getModule()->getEventOrNull(curr->event); + shouldBeTrue(event != nullptr, curr, "br_on_exn's event must exist"); + shouldBeTrue(event->sig.params == curr->sent, + curr, + "br_on_exn's event params and event's params are different"); + noteBreak(curr->name, curr->sent, curr); + shouldBeSubTypeOrFirstIsUnreachable( + curr->exnref->type, + Type::exnref, + curr, + "br_on_exn's argument must be unreachable or exnref type or its subtype"); + if (curr->exnref->type == Type::unreachable) { + shouldBeTrue(curr->type == Type::unreachable, + curr, + "If exnref argument's type is unreachable, br_on_exn should " + "be unreachable too"); + } else { + shouldBeTrue(curr->type == Type::exnref, + curr, + "br_on_exn's type should be exnref unless its exnref argument " + "is unreachable"); + } } void FunctionValidator::visitTupleMake(TupleMake* curr) { @@ -2326,31 +2170,34 @@ curr, "call_ref requires typed-function-references to be enabled"); if (curr->target->type != Type::unreachable) { - if (shouldBeTrue(curr->target->type.isFunction(), - curr, - "call_ref target must be a function reference")) { - validateCallParamsAndResult(curr, curr->target->type.getHeapType()); - } + shouldBeTrue(curr->target->type.isFunction(), + curr, + "call_ref target must be a function reference"); + validateCallParamsAndResult( + curr, curr->target->type.getHeapType().getSignature()); } } void FunctionValidator::visitI31New(I31New* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "i31.new requires gc to be enabled"); - shouldBeSubType(curr->value->type, - Type::i32, - curr->value, - "i31.new's argument should be i32"); + shouldBeSubTypeOrFirstIsUnreachable(curr->value->type, + Type::i32, + curr->value, + "i31.new's argument should be i32"); } void FunctionValidator::visitI31Get(I31Get* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, "i31.get_s/u requires gc to be enabled"); - shouldBeSubType(curr->i31->type, - Type::i31ref, - curr->i31, - "i31.get_s/u's argument should be i31ref"); + // FIXME: use i31ref here, which is non-nullable, when we support non- + // nullability. + shouldBeSubTypeOrFirstIsUnreachable( + curr->i31->type, + Type(HeapType::i31, Nullable), + curr->i31, + "i31.get_s/u's argument should be i31ref"); } void FunctionValidator::visitRefTest(RefTest* curr) { @@ -2360,22 +2207,9 @@ shouldBeTrue( curr->ref->type.isRef(), curr, "ref.test ref must have ref type"); } - if (curr->rtt) { - if (curr->rtt->type != Type::unreachable) { - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "ref.test rtt must have rtt type"); - } - shouldBeEqual(curr->intendedType, - HeapType(), - curr, - "dynamic ref.test must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.test must set intendedType field"); + if (curr->rtt->type != Type::unreachable) { shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.test must test a non-basic"); + curr->rtt->type.isRtt(), curr, "ref.test rtt must have rtt type"); } } @@ -2386,26 +2220,13 @@ shouldBeTrue( curr->ref->type.isRef(), curr, "ref.cast ref must have ref type"); } - if (curr->rtt) { - if (curr->rtt->type != Type::unreachable) { - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "ref.cast rtt must have rtt type"); - } - shouldBeEqual(curr->intendedType, - HeapType(), - curr, - "dynamic ref.cast must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.cast must set intendedType field"); + if (curr->rtt->type != Type::unreachable) { shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.cast must cast to a non-basic"); + curr->rtt->type.isRtt(), curr, "ref.cast rtt must have rtt type"); } } -void FunctionValidator::visitBrOn(BrOn* curr) { +void FunctionValidator::visitBrOnCast(BrOnCast* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, "br_on_cast requires gc to be enabled"); @@ -2413,35 +2234,15 @@ shouldBeTrue( curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type"); } - if (curr->op == BrOnCast || curr->op == BrOnCastFail) { - if (curr->rtt) { - // Note that an unreachable rtt is not supported: the text and binary - // formats do not provide the type, so if it's unreachable we should not - // even create a br_on_cast in such a case, as we'd have no idea what it - // casts to. - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "br_on_cast rtt must have rtt type"); - shouldBeEqual(curr->intendedType, - HeapType(), - curr, - "dynamic br_on_cast* must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static br_on_cast* must set intendedType field"); - shouldBeTrue(!curr->intendedType.isBasic(), - curr, - "br_on_cast* must cast to a non-basic"); - } - } else { - shouldBeTrue(curr->rtt == nullptr, curr, "non-cast BrOn must not have rtt"); - shouldBeEqual(curr->intendedType, - HeapType(), + if (curr->rtt->type != Type::unreachable) { + shouldBeTrue( + curr->rtt->type.isRtt(), curr, "br_on_cast rtt must have rtt type"); + shouldBeEqual(curr->rtt->type.getHeapType(), + curr->castType.getHeapType(), curr, - "non-cast br_on* must not set intendedType field"); + "br_on_cast rtt must have the proper heap type"); + noteBreak(curr->name, curr->castType, curr); } - noteBreak(curr->name, curr->getSentType(), curr); } void FunctionValidator::visitRttCanon(RttCanon* curr) { @@ -2449,10 +2250,7 @@ getModule()->features.hasGC(), curr, "rtt.canon requires gc to be enabled"); shouldBeTrue(curr->type.isRtt(), curr, "rtt.canon must have RTT type"); auto rtt = curr->type.getRtt(); - shouldBeEqual(rtt.depth, - Index(curr->type.getHeapType().getDepth()), - curr, - "rtt.canon must have the depth of its heap type"); + shouldBeEqual(rtt.depth, Index(0), curr, "rtt.canon has a depth of 0"); } void FunctionValidator::visitRttSub(RttSub* curr) { @@ -2470,9 +2268,6 @@ curr, "rtt.canon has a depth of 1 over the parent"); } - shouldBeTrue(HeapType::isSubType(rtt.heapType, parentRtt.heapType), - curr, - "rtt.sub parent must be a supertype"); } } @@ -2483,19 +2278,11 @@ if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) { - return; - } - } - auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "struct.new heap type must match rtt"); + if (!shouldBeTrue( + curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) { + return; } + auto heapType = curr->rtt->type.getHeapType(); if (!shouldBeTrue( heapType.isStruct(), curr, "struct.new heap type must be struct")) { return; @@ -2507,22 +2294,18 @@ "struct.new_with_default should have no operands"); // All the fields must be defaultable. for (const auto& field : fields) { - shouldBeTrue(field.type.isDefaultable(), + // TODO: add type.isDefaultable()? + shouldBeTrue(!field.type.isRef() || field.type.isNullable(), field, "struct.new_with_default value type must be defaultable"); } } else { - if (shouldBeEqual(curr->operands.size(), - fields.size(), + // All the fields must have the proper type. + for (Index i = 0; i < fields.size(); i++) { + shouldBeSubType(curr->operands[i]->type, + fields[i].type, curr, - "struct.new must have the right number of operands")) { - // All the fields must have the proper type. - for (Index i = 0; i < fields.size(); i++) { - shouldBeSubType(curr->operands[i]->type, - fields[i].type, - curr, - "struct.new operand must have proper type"); - } + "struct.new operand must have proper type"); } } } @@ -2531,14 +2314,6 @@ shouldBeTrue(getModule()->features.hasGC(), curr, "struct.get requires gc to be enabled"); - if (curr->ref->type == Type::unreachable) { - return; - } - if (!shouldBeTrue(curr->ref->type.isStruct(), - curr->ref, - "struct.get ref must be a struct")) { - return; - } const auto& fields = curr->ref->type.getHeapType().getStruct().fields; shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field"); auto field = fields[curr->index]; @@ -2558,24 +2333,13 @@ shouldBeTrue(getModule()->features.hasGC(), curr, "struct.set requires gc to be enabled"); - if (curr->ref->type == Type::unreachable) { - return; - } - if (!shouldBeTrue(curr->ref->type.isStruct(), - curr->ref, - "struct.set ref must be a struct")) { - return; - } if (curr->ref->type != Type::unreachable) { const auto& fields = curr->ref->type.getHeapType().getStruct().fields; shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field"); - auto& field = fields[curr->index]; - shouldBeSubType(curr->value->type, - field.type, - curr, - "struct.set must have the proper type"); - shouldBeEqual( - field.mutable_, Mutable, curr, "struct.set field must be mutable"); + shouldBeEqual(curr->value->type, + fields[curr->index].type, + curr, + "struct.set must have the proper type"); } } @@ -2587,19 +2351,11 @@ if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) { - return; - } - } - auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "array.new heap type must match rtt"); + if (!shouldBeTrue( + curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) { + return; } + auto heapType = curr->rtt->type.getHeapType(); if (!shouldBeTrue( heapType.isArray(), curr, "array.new heap type must be array")) { return; @@ -2609,7 +2365,8 @@ shouldBeTrue( !curr->init, curr, "array.new_with_default should have no init"); // The element must be defaultable. - shouldBeTrue(element.type.isDefaultable(), + // TODO: add type.isDefaultable()? + shouldBeTrue(!element.type.isRef() || element.type.isNullable(), element, "array.new_with_default value type must be defaultable"); } else { @@ -2622,39 +2379,6 @@ } } -void FunctionValidator::visitArrayInit(ArrayInit* curr) { - shouldBeTrue(getModule()->features.hasGC(), - curr, - "array.init requires gc to be enabled"); - if (curr->type == Type::unreachable) { - return; - } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "array.init rtt must be rtt")) { - return; - } - } - auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "array.init heap type must match rtt"); - } - if (!shouldBeTrue( - heapType.isArray(), curr, "array.init heap type must be array")) { - return; - } - const auto& element = heapType.getArray().element; - for (auto* value : curr->values) { - shouldBeSubType(value->type, - element.type, - curr, - "array.init value must have proper type"); - } -} - void FunctionValidator::visitArrayGet(ArrayGet* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "array.get requires gc to be enabled"); @@ -2682,11 +2406,10 @@ return; } const auto& element = curr->ref->type.getHeapType().getArray().element; - shouldBeSubType(curr->value->type, - element.type, - curr, - "array.set must have the proper type"); - shouldBeTrue(element.mutable_, curr, "array.set type must be mutable"); + shouldBeEqual(curr->value->type, + element.type, + curr, + "array.set must have the proper type"); } void FunctionValidator::visitArrayLen(ArrayLen* curr) { @@ -2696,52 +2419,25 @@ curr->type, Type(Type::i32), curr, "array.len result must be an i32"); } -void FunctionValidator::visitArrayCopy(ArrayCopy* curr) { - shouldBeTrue(getModule()->features.hasGC(), - curr, - "array.copy requires gc to be enabled"); - shouldBeEqualOrFirstIsUnreachable(curr->srcIndex->type, - Type(Type::i32), - curr, - "array.copy src index must be an i32"); - shouldBeEqualOrFirstIsUnreachable(curr->destIndex->type, - Type(Type::i32), - curr, - "array.copy dest index must be an i32"); - if (curr->type == Type::unreachable) { - return; - } - const auto& srcElement = curr->srcRef->type.getHeapType().getArray().element; - const auto& destElement = - curr->destRef->type.getHeapType().getArray().element; - shouldBeSubType(srcElement.type, - destElement.type, - curr, - "array.copy must have the proper types"); - shouldBeTrue(destElement.mutable_, curr, "array.copy type must be mutable"); -} - void FunctionValidator::visitFunction(Function* curr) { - if (curr->getResults().isTuple()) { + if (curr->sig.results.isTuple()) { shouldBeTrue(getModule()->features.hasMultivalue(), curr->body, "Multivalue function results (multivalue is not enabled)"); } FeatureSet features; - for (const auto& param : curr->getParams()) { + for (const auto& param : curr->sig.params) { features |= param.getFeatures(); shouldBeTrue(param.isConcrete(), curr, "params must be concretely typed"); } - for (const auto& result : curr->getResults()) { + for (const auto& result : curr->sig.results) { features |= result.getFeatures(); shouldBeTrue(result.isConcrete(), curr, "results must be concretely typed"); } for (const auto& var : curr->vars) { features |= var.getFeatures(); - bool valid = getModule()->features.hasGCNNLocals() - ? var.isDefaultableOrNonNullable() - : var.isDefaultable(); - shouldBeTrue(valid, var, "vars must be defaultable"); + shouldBeTrue(var.isConcrete(), curr, "vars must be concretely typed"); + // TODO: check for nullability } shouldBeTrue(features <= getModule()->features, curr->name, @@ -2752,45 +2448,38 @@ } // if function has no result, it is ignored // if body is unreachable, it might be e.g. a return - shouldBeSubType(curr->body->type, - curr->getResults(), - curr->body, - "function body type must match, if function returns"); + shouldBeSubTypeOrFirstIsUnreachable( + curr->body->type, + curr->sig.results, + curr->body, + "function body type must match, if function returns"); for (Type returnType : returnTypes) { - shouldBeSubType(returnType, - curr->getResults(), - curr->body, - "function result must match, if function has returns"); + shouldBeSubTypeOrFirstIsUnreachable( + returnType, + curr->sig.results, + curr->body, + "function result must match, if function has returns"); } - assert(breakTypes.empty()); - assert(delegateTargetNames.empty()); - assert(rethrowTargetNames.empty()); + shouldBeTrue( + breakInfos.empty(), curr->body, "all named break targets must exist"); returnTypes.clear(); labelNames.clear(); // validate optional local names - std::unordered_set seen; + std::set seen; for (auto& pair : curr->localNames) { Name name = pair.second; shouldBeTrue(seen.insert(name).second, name, "local names must be unique"); } } -static bool checkSegmentOffset(Expression* curr, - Address add, - Address max, - FeatureSet features) { - if (!Properties::isValidInConstantExpression(curr, features)) { - return false; +static bool checkSegmentOffset(Expression* curr, Address add, Address max) { + if (curr->is()) { + return true; } auto* c = curr->dynCast(); if (!c) { - // Unless the instruction is actually a const instruction, we don't - // currently try to evaluate it. - // TODO: Attempt to evaluate other expressions that might also be const - // such as `global.get` or more complex instruction sequences involving - // add/sub/mul/etc. - return true; + return false; } uint64_t raw = c->value.getInteger(); if (raw > std::numeric_limits::max()) { @@ -2841,10 +2530,11 @@ case Type::unreachable: break; case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("invalid type"); } @@ -2887,7 +2577,9 @@ } // check if a node is a duplicate - expressions must not be seen more than // once - if (!seen.insert(curr).second) { + bool inserted; + std::tie(std::ignore, inserted) = seen.insert(curr); + if (!inserted) { std::ostringstream ss; ss << "expression seen more than once in the tree in " << scope << " on " << curr << '\n'; @@ -2903,36 +2595,26 @@ static void validateImports(Module& module, ValidationInfo& info) { ModuleUtils::iterImportedFunctions(module, [&](Function* curr) { - if (curr->getResults().isTuple()) { + if (curr->sig.results.isTuple()) { info.shouldBeTrue(module.features.hasMultivalue(), curr->name, "Imported multivalue function " "(multivalue is not enabled)"); } if (info.validateWeb) { - for (const auto& param : curr->getParams()) { + for (const auto& param : curr->sig.params) { info.shouldBeUnequal(param, Type(Type::i64), curr->name, "Imported function must not have i64 parameters"); } - for (const auto& result : curr->getResults()) { + for (const auto& result : curr->sig.results) { info.shouldBeUnequal(result, Type(Type::i64), curr->name, "Imported function must not have i64 results"); } } - - if (Intrinsics(module).isCallWithoutEffects(curr)) { - auto lastParam = curr->getParams(); - if (lastParam.isTuple()) { - lastParam = lastParam.getTuple().types.back(); - } - info.shouldBeTrue(lastParam.isFunction(), - curr->name, - "call.if.used's last param must be a function"); - } }); ModuleUtils::iterImportedGlobals(module, [&](Global* curr) { if (!module.features.hasMutableGlobals()) { @@ -2949,14 +2631,14 @@ if (curr->kind == ExternalKind::Function) { if (info.validateWeb) { Function* f = module.getFunction(curr->value); - for (const auto& param : f->getParams()) { + for (const auto& param : f->sig.params) { info.shouldBeUnequal( param, Type(Type::i64), f->name, "Exported function must not have i64 parameters"); } - for (const auto& result : f->getResults()) { + for (const auto& result : f->sig.results) { info.shouldBeUnequal(result, Type(Type::i64), f->name, @@ -2986,16 +2668,17 @@ name, "module global exports must be found"); } else if (exp->kind == ExternalKind::Table) { - info.shouldBeTrue(module.getTableOrNull(name), + info.shouldBeTrue(name == Name("0") || name == module.table.name, name, "module table exports must be found"); } else if (exp->kind == ExternalKind::Memory) { info.shouldBeTrue(name == Name("0") || name == module.memory.name, name, "module memory exports must be found"); - } else if (exp->kind == ExternalKind::Tag) { - info.shouldBeTrue( - module.getTagOrNull(name), name, "module tag exports must be found"); + } else if (exp->kind == ExternalKind::Event) { + info.shouldBeTrue(module.getEventOrNull(name), + name, + "module event exports must be found"); } else { WASM_UNREACHABLE("invalid ExternalKind"); } @@ -3015,10 +2698,9 @@ info.shouldBeTrue( curr->init != nullptr, curr->name, "global init must be non-null"); assert(curr->init); - info.shouldBeTrue( - GlobalUtils::canInitializeGlobal(curr->init, module.features), - curr->name, - "global init must be valid"); + info.shouldBeTrue(GlobalUtils::canInitializeGlobal(curr->init), + curr->name, + "global init must be valid"); if (!info.shouldBeSubType(curr->init->type, curr->type, @@ -3027,7 +2709,6 @@ !info.quiet) { info.getStream(nullptr) << "(on global " << curr->name << ")\n"; } - FunctionValidator(module, &info).validate(curr->init); }); } @@ -3056,7 +2737,7 @@ "memory is shared, but atomics are disabled"); } for (auto& segment : curr.segments) { - auto size = segment.data.size(); + Index size = segment.data.size(); if (segment.isPassive) { info.shouldBeTrue(module.features.hasBulkMemory(), segment.offset, @@ -3066,35 +2747,24 @@ segment.offset, "passive segment should not have an offset"); } else { - if (curr.is64()) { - if (!info.shouldBeEqual(segment.offset->type, - Type(Type::i64), - segment.offset, - "segment offset should be i64")) { - continue; - } - } else { - if (!info.shouldBeEqual(segment.offset->type, - Type(Type::i32), - segment.offset, - "segment offset should be i32")) { - continue; - } + if (!info.shouldBeEqual(segment.offset->type, + Type(Type::i32), + segment.offset, + "segment offset should be i32")) { + continue; } info.shouldBeTrue(checkSegmentOffset(segment.offset, segment.data.size(), - curr.initial * Memory::kPageSize, - module.features), + curr.initial * Memory::kPageSize), segment.offset, "memory segment offset should be reasonable"); if (segment.offset->is()) { - auto start = segment.offset->cast()->value.getUnsigned(); - auto end = start + size; + Index start = segment.offset->cast()->value.geti32(); + Index end = start + size; info.shouldBeTrue(end <= curr.initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory (end)"); } - FunctionValidator(module, &info).validate(segment.offset); } // If the memory is imported we don't actually know its initial size. // Specifically wasm dll's import a zero sized memory which is perfectly @@ -3107,154 +2777,50 @@ } } -static void validateTables(Module& module, ValidationInfo& info) { - FunctionValidator validator(module, &info); - - if (!module.features.hasReferenceTypes()) { - info.shouldBeTrue(module.tables.size() <= 1, - "table", - "Only 1 table definition allowed in MVP (requires " - "--enable-reference-types)"); - if (!module.tables.empty()) { - auto& table = module.tables.front(); - info.shouldBeTrue(table->type == Type::funcref, - "table", - "Only funcref is valid for table type (when reference " - "types are disabled)"); - for (auto& segment : module.elementSegments) { - info.shouldBeTrue(segment->table == table->name, - "elem", - "all element segments should refer to a single table " - "in MVP."); - for (auto* expr : segment->data) { - info.shouldBeTrue( - expr->is(), - expr, - "all table elements must be non-null funcrefs in MVP."); - validator.validate(expr); - } - } - } - } - - for (auto& table : module.tables) { - info.shouldBeTrue(table->initial <= table->max, - "table", - "size minimum must not be greater than maximum"); - info.shouldBeTrue( - table->type.isNullable(), - "table", - "Non-nullable reference types are not yet supported for tables"); - if (!module.features.hasGC()) { - info.shouldBeTrue(table->type.isFunction() || table->type == Type::anyref, - "table", - "Only function reference types or anyref are valid " - "for table type (when GC is disabled)"); - } - if (!module.features.hasTypedFunctionReferences()) { - info.shouldBeTrue(table->type == Type::funcref || - table->type == Type::anyref, - "table", - "Only funcref and anyref are valid for table type " - "(when typed-function references are disabled)"); - } - } - - for (auto& segment : module.elementSegments) { - // Since element segment items need to be constant expressions, that leaves - // us with ref.null, ref.func and global.get. The GC proposal adds rtt.canon - // and rtt.sub to the list, but Binaryen doesn't consider RTTs as reference- - // types yet. As a result, the only possible type for element segments will - // be function references. - info.shouldBeTrue(segment->type.isFunction(), - "elem", - "element segment type must be of function type."); +static void validateTable(Module& module, ValidationInfo& info) { + auto& curr = module.table; + for (auto& segment : curr.segments) { + info.shouldBeEqual(segment.offset->type, + Type(Type::i32), + segment.offset, + "segment offset should be i32"); info.shouldBeTrue( - segment->type.isNullable(), - "elem", - "Non-nullable reference types are not yet supported for tables"); - - if (segment->table.is()) { - auto table = module.getTableOrNull(segment->table); - info.shouldBeTrue(table != nullptr, - "elem", - "element segment must have a valid table name"); - info.shouldBeTrue(!!segment->offset, - "elem", - "table segment offset should have an offset"); - info.shouldBeEqual(segment->offset->type, - Type(Type::i32), - segment->offset, - "element segment offset should be i32"); - info.shouldBeTrue(checkSegmentOffset(segment->offset, - segment->data.size(), - table->initial * Table::kPageSize, - module.features), - segment->offset, - "table segment offset should be reasonable"); - if (module.features.hasTypedFunctionReferences()) { - info.shouldBeTrue( - Type::isSubType(segment->type, table->type), - "elem", - "element segment type must be a subtype of the table type"); - } else { - info.shouldBeEqual( - segment->type, - table->type, - "elem", - "element segment type must be the same as the table type"); - } - validator.validate(segment->offset); - } else { - info.shouldBeTrue(!segment->offset, - "elem", - "non-table segment offset should have no offset"); - } - // Avoid double checking items - if (module.features.hasReferenceTypes()) { - for (auto* expr : segment->data) { - if (auto* globalExpr = expr->dynCast()) { - auto* global = module.getGlobal(globalExpr->name); - info.shouldBeFalse( - global->mutable_, expr, "expected a constant expression"); - } else { - info.shouldBeTrue(expr->is() || expr->is() || - expr->is(), - expr, - "element segment items must be one of global.get, " - "ref.func, ref.null func"); - } - info.shouldBeSubType(expr->type, - segment->type, - expr, - "element segment item expressions must return a " - "subtype of the segment type"); - validator.validate(expr); - } + checkSegmentOffset(segment.offset, + segment.data.size(), + module.table.initial * Table::kPageSize), + segment.offset, + "table segment offset should be reasonable"); + for (auto name : segment.data) { + info.shouldBeTrue( + module.getFunctionOrNull(name), name, "segment name should be valid"); } } } -static void validateTags(Module& module, ValidationInfo& info) { - if (!module.tags.empty()) { +static void validateEvents(Module& module, ValidationInfo& info) { + if (!module.events.empty()) { info.shouldBeTrue(module.features.hasExceptionHandling(), - module.tags[0]->name, - "Module has tags (exception-handling is disabled)"); + module.events[0]->name, + "Module has events (event-handling is disabled)"); } - for (auto& curr : module.tags) { + for (auto& curr : module.events) { + info.shouldBeEqual(curr->attribute, + (unsigned)0, + curr->attribute, + "Currently only attribute 0 is supported"); info.shouldBeEqual(curr->sig.results, Type(Type::none), curr->name, - "Tag type's result type should be none"); + "Event type's result type should be none"); if (curr->sig.params.isTuple()) { info.shouldBeTrue(module.features.hasMultivalue(), curr->name, - "Multivalue tag type (multivalue is not enabled)"); + "Multivalue event type (multivalue is not enabled)"); } for (const auto& param : curr->sig.params) { info.shouldBeTrue(param.isConcrete(), curr->name, - "Values in a tag should have concrete types"); + "Values in an event should have concrete types"); } } } @@ -3265,10 +2831,10 @@ auto func = module.getFunctionOrNull(module.start); if (info.shouldBeTrue( func != nullptr, module.start, "start must be found")) { - info.shouldBeTrue(func->getParams() == Type::none, + info.shouldBeTrue(func->sig.params == Type::none, module.start, "start must have 0 params"); - info.shouldBeTrue(func->getResults() == Type::none, + info.shouldBeTrue(func->sig.results == Type::none, module.start, "start must not return a value"); } @@ -3281,27 +2847,33 @@ module.features, "--enable-gc requires --enable-reference-types"); } + if (module.features.hasExceptionHandling()) { // implies exnref + info.shouldBeTrue( + module.features.hasReferenceTypes(), + module.features, + "--enable-exception-handling requires --enable-reference-types"); + } } // TODO: If we want the validator to be part of libwasm rather than libpasses, // then Using PassRunner::getPassDebug causes a circular dependence. We should // fix that, perhaps by moving some of the pass infrastructure into libsupport. bool WasmValidator::validate(Module& module, Flags flags) { - ValidationInfo info(module); + ValidationInfo info; info.validateWeb = (flags & Web) != 0; info.validateGlobally = (flags & Globally) != 0; info.quiet = (flags & Quiet) != 0; // parallel wasm logic validation PassRunner runner(&module); - FunctionValidator(module, &info).validate(&runner); + FunctionValidator(&info).run(&runner, &module); // validate globally if (info.validateGlobally) { validateImports(module, info); validateExports(module, info); validateGlobals(module, info); validateMemory(module, info); - validateTables(module, info); - validateTags(module, info); + validateTable(module, info); + validateEvents(module, info); validateModule(module, info); validateFeatures(module, info); } diff -Nru binaryen-108/src/wasm2js.h binaryen-99/src/wasm2js.h --- binaryen-108/src/wasm2js.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm2js.h 2021-01-07 20:01:06.000000000 +0000 @@ -32,7 +32,6 @@ #include "emscripten-optimizer/optimizer.h" #include "ir/branch-utils.h" #include "ir/effects.h" -#include "ir/element-utils.h" #include "ir/find_all.h" #include "ir/import-utils.h" #include "ir/load-utils.h" @@ -82,11 +81,11 @@ } bool isTableExported(Module& wasm) { - if (wasm.tables.empty() || wasm.tables[0]->imported()) { + if (!wasm.table.exists || wasm.table.imported()) { return false; } for (auto& ex : wasm.exports) { - if (ex->kind == ExternalKind::Table && ex->value == wasm.tables[0]->name) { + if (ex->kind == ExternalKind::Table && ex->value == wasm.table.name) { return true; } } @@ -145,13 +144,17 @@ // // Wasm2JSBuilder - converts a WebAssembly module's functions into JS // -// Wasm-to-JS is tricky because wasm doesn't distinguish -// statements and expressions, or in other words, things like `break` and `if` -// can show up in places where JS can't handle them, like inside an a loop's -// condition check. For that reason we use flat IR here. +// In general, JS (asm.js) => wasm is very straightforward, as can +// be seen in asm2wasm.h. Just a single pass, plus a little +// state bookkeeping (breakStack, etc.), and a few after-the +// fact corrections for imports, etc. However, wasm => JS +// is tricky because wasm has statements == expressions, or in +// other words, things like `break` and `if` can show up +// in places where JS can't handle them, like inside an +// a loop's condition check. For that reason we use flat IR here. // We do optimize it later, to allow some nesting, but we avoid -// non-JS-compatible nesting like block return values control flow in an if -// condition, etc. +// non-JS-compatible nesting like block return values control +// flow in an if condition, etc. // class Wasm2JSBuilder { @@ -290,7 +293,7 @@ // Mangled names cache by interned names. // Utilizes the usually reused underlying cstring's pointer as the key. - std::unordered_map + std::unordered_map wasmNameToMangledName[(int)NameScope::Max]; // Set of all mangled names in each scope. std::unordered_set mangledNames[(int)NameScope::Max]; @@ -322,8 +325,11 @@ functionsCallableFromOutside.insert(exp->value); } } - ElementUtils::iterAllElementFunctionNames( - wasm, [&](Name name) { functionsCallableFromOutside.insert(name); }); + for (auto& segment : wasm->table.segments) { + for (auto name : segment.data) { + functionsCallableFromOutside.insert(name); + } + } // Ensure the scratch memory helpers. // If later on they aren't needed, we'll clean them up. @@ -337,11 +343,6 @@ // TODO: only legalize if necessary - emscripten would already do so, and // likely other toolchains. but spec test suite needs that. runner.add("legalize-js-interface"); - // Before lowering non-JS operations we can optimize some instructions which - // may simplify next passes - if (options.optimizeLevel > 0) { - runner.add("optimize-for-js"); - } // First up remove as many non-JS operations we can, including things like // 64-bit integer multiplication/division, `f32.nearest` instructions, etc. // This may inject intrinsics which use i64 so it needs to be run before the @@ -457,15 +458,15 @@ } } - // add imported tables - ModuleUtils::iterImportedTables(*wasm, [&](Table* table) { + // add table import + if (wasm->table.exists && wasm->table.imported()) { Ref theVar = ValueBuilder::makeVar(); asmFunc[3]->push_back(theVar); ValueBuilder::appendToVar( theVar, FUNCTION_TABLE, - ValueBuilder::makeDot(ValueBuilder::makeName(ENV), table->base)); - }); + ValueBuilder::makeDot(ValueBuilder::makeName(ENV), wasm->table.base)); + } // create heaps, etc addBasics(asmFunc[3], wasm); @@ -614,14 +615,14 @@ Ref value = ValueBuilder::makeDot(module, fromName(import->base, NameScope::Top)); if (import->type == Type::i32) { - value = makeJsCoercion(value, JS_INT); + value = makeAsmCoercion(value, ASM_INT); } ValueBuilder::appendToVar( theVar, fromName(import->name, NameScope::Top), value); } void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) { - if (wasm->tables.size() == 0) { + if (!wasm->table.exists) { return; } @@ -630,81 +631,70 @@ // Emit a simple flat table as a JS array literal. Otherwise, // emit assignments separately for each index. Ref theArray = ValueBuilder::makeArray(); - for (auto& table : wasm->tables) { - if (!table->type.isFunction()) { - Fatal() << "wasm2js doesn't support non-function tables\n"; - } - - if (!table->imported()) { - TableUtils::FlatTable flat(*wasm, *table); - if (flat.valid) { - Name null("null"); - for (auto& name : flat.names) { - if (name.is()) { - name = fromName(name, NameScope::Top); - } else { - name = null; - } - ValueBuilder::appendToArray(theArray, ValueBuilder::makeName(name)); + if (!wasm->table.imported()) { + TableUtils::FlatTable flat(wasm->table); + if (flat.valid) { + Name null("null"); + for (auto& name : flat.names) { + if (name.is()) { + name = fromName(name, NameScope::Top); + } else { + name = null; } - } else { - perElementInit = true; - Ref initial = - ValueBuilder::makeInt(Address::address32_t(table->initial.addr)); - theArray = ValueBuilder::makeNew( - ValueBuilder::makeCall(IString("Array"), initial)); + ValueBuilder::appendToArray(theArray, ValueBuilder::makeName(name)); } } else { perElementInit = true; + Ref initial = + ValueBuilder::makeInt(Address::address32_t(wasm->table.initial.addr)); + theArray = ValueBuilder::makeNew( + ValueBuilder::makeCall(IString("Array"), initial)); } + } else { + perElementInit = true; + } - if (isTableExported(*wasm)) { - // If the table is exported use a fake WebAssembly.Table object - // We don't handle the case where a table is both imported and exported. - if (table->imported()) { - Fatal() << "wasm2js doesn't support a table that is both imported and " - "exported\n"; - } - Ref theVar = ValueBuilder::makeVar(); - ast->push_back(theVar); - - Ref table = ValueBuilder::makeCall(IString("Table"), theArray); - ValueBuilder::appendToVar(theVar, FUNCTION_TABLE, table); - } else if (!table->imported()) { - // Otherwise if the table is internal (neither imported not exported). - // Just use a plain array in this case, avoiding the Table. - Ref theVar = ValueBuilder::makeVar(); - ast->push_back(theVar); - ValueBuilder::appendToVar(theVar, FUNCTION_TABLE, theArray); + if (isTableExported(*wasm)) { + // If the table is exported use a fake WebAssembly.Table object + // We don't handle the case where a table is both imported and exported. + if (wasm->table.imported()) { + Fatal() << "wasm2js doesn't support a table that is both imported and " + "exported\n"; } + Ref theVar = ValueBuilder::makeVar(); + ast->push_back(theVar); - if (perElementInit) { - // TODO: optimize for size - ModuleUtils::iterTableSegments( - *wasm, table->name, [&](ElementSegment* segment) { - auto offset = segment->offset; - ElementUtils::iterElementSegmentFunctionNames( - segment, [&](Name entry, Index i) { - Ref index; - if (auto* c = offset->dynCast()) { - index = ValueBuilder::makeInt(c->value.geti32() + i); - } else if (auto* get = offset->dynCast()) { - index = ValueBuilder::makeBinary( - ValueBuilder::makeName( - stringToIString(asmangle(get->name.str))), - PLUS, - ValueBuilder::makeNum(i)); - } else { - WASM_UNREACHABLE("unexpected expr type"); - } - ast->push_back( - ValueBuilder::makeStatement(ValueBuilder::makeBinary( - ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE), - index), - SET, - ValueBuilder::makeName(fromName(entry, NameScope::Top))))); - }); - }); + Ref table = ValueBuilder::makeCall(IString("Table"), theArray); + ValueBuilder::appendToVar(theVar, FUNCTION_TABLE, table); + } else if (!wasm->table.imported()) { + // Otherwise if the table is internal (neither imported not exported). + // Just use a plain array in this case, avoiding the Table. + Ref theVar = ValueBuilder::makeVar(); + ast->push_back(theVar); + ValueBuilder::appendToVar(theVar, FUNCTION_TABLE, theArray); + } + + if (perElementInit) { + // TODO: optimize for size + for (auto& segment : wasm->table.segments) { + auto offset = segment.offset; + for (Index i = 0; i < segment.data.size(); i++) { + Ref index; + if (auto* c = offset->dynCast()) { + index = ValueBuilder::makeInt(c->value.geti32() + i); + } else if (auto* get = offset->dynCast()) { + index = ValueBuilder::makeBinary( + ValueBuilder::makeName(stringToIString(asmangle(get->name.str))), + PLUS, + ValueBuilder::makeNum(i)); + } else { + WASM_UNREACHABLE("unexpected expr type"); + } + ast->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary( + ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE), index), + SET, + ValueBuilder::makeName(fromName(segment.data[i], NameScope::Top))))); + } } } } @@ -764,43 +754,13 @@ break; } case ExternalKind::Global: { - Ref object = ValueBuilder::makeObject(); - - IString identName = fromName(export_->value, NameScope::Top); - - // getter - { - Ref block = ValueBuilder::makeBlock(); - - block[1]->push_back( - ValueBuilder::makeReturn(ValueBuilder::makeName(identName))); - - ValueBuilder::appendToObjectAsGetter(object, IString("value"), block); - } - - // setter - { - std::ostringstream buffer; - buffer << '_' << identName.c_str(); - auto setterParam = stringToIString(buffer.str()); - - auto block = ValueBuilder::makeBlock(); - - block[1]->push_back( - ValueBuilder::makeBinary(ValueBuilder::makeName(identName), - SET, - ValueBuilder::makeName(setterParam))); - - ValueBuilder::appendToObjectAsSetter( - object, IString("value"), setterParam, block); - } - ValueBuilder::appendToObjectWithQuotes( - exports, fromName(export_->name, NameScope::Export), object); - + exports, + fromName(export_->name, NameScope::Export), + ValueBuilder::makeName(fromName(export_->value, NameScope::Top))); break; } - case ExternalKind::Tag: + case ExternalKind::Event: case ExternalKind::Invalid: Fatal() << "unsupported export type: " << export_->name << "\n"; } @@ -824,13 +784,13 @@ case Type::f32: { theValue = ValueBuilder::makeCall( MATH_FROUND, - makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf32()), - JS_DOUBLE)); + makeAsmCoercion(ValueBuilder::makeDouble(const_->value.getf32()), + ASM_DOUBLE)); break; } case Type::f64: { - theValue = makeJsCoercion( - ValueBuilder::makeDouble(const_->value.getf64()), JS_DOUBLE); + theValue = makeAsmCoercion( + ValueBuilder::makeDouble(const_->value.getf64()), ASM_DOUBLE); break; } default: { @@ -890,8 +850,8 @@ ret[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary( ValueBuilder::makeName(name), SET, - makeJsCoercion(ValueBuilder::makeName(name), - wasmToJsType(func->getLocalType(i)))))); + makeAsmCoercion(ValueBuilder::makeName(name), + wasmToAsmType(func->getLocalType(i)))))); } } Ref theVar = ValueBuilder::makeVar(); @@ -904,7 +864,7 @@ ValueBuilder::appendToVar( theVar, fromName(func->getLocalNameOrGeneric(i), NameScope::Local), - makeJsCoercedZero(wasmToJsType(func->getLocalType(i)))); + makeAsmCoercedZero(wasmToAsmType(func->getLocalType(i)))); } if (theVar[1]->size() == 0) { ret[3]->splice(theVarIndex, 1); @@ -1217,7 +1177,7 @@ // nesting of a size that JS engines can't handle. Ref condition = visit(curr->condition, EXPRESSION_RESULT); Ref theSwitch = - ValueBuilder::makeSwitch(makeJsCoercion(condition, JS_INT)); + ValueBuilder::makeSwitch(makeAsmCoercion(condition, ASM_INT)); // First, group the switch targets. std::map> targetIndexes; for (size_t i = 0; i < curr->targets.size(); i++) { @@ -1262,7 +1222,9 @@ // Emit any remaining groups by just emitting branches to their code, // which will appear outside the switch. - for (auto& [target, indexes] : targetIndexes) { + for (auto& pair : targetIndexes) { + auto target = pair.first; + auto& indexes = pair.second; if (emittedTargets.count(target)) { continue; } @@ -1305,12 +1267,12 @@ for (auto operand : curr->operands) { auto value = visit(operand, EXPRESSION_RESULT); if (needCoercions) { - value = makeJsCoercion(value, wasmToJsType(operand->type)); + value = makeAsmCoercion(value, wasmToAsmType(operand->type)); } theCall[2]->push_back(value); } if (needCoercions) { - theCall = makeJsCoercion(theCall, wasmToJsType(curr->type)); + theCall = makeAsmCoercion(theCall, wasmToAsmType(curr->type)); } return theCall; } @@ -1322,11 +1284,12 @@ // If the target has effects that interact with the operands, we must // reorder it to the start. bool mustReorder = false; - EffectAnalyzer targetEffects(parent->options, *module, curr->target); + EffectAnalyzer targetEffects( + parent->options, module->features, curr->target); if (targetEffects.hasAnything()) { for (auto* operand : curr->operands) { if (targetEffects.invalidates( - EffectAnalyzer(parent->options, *module, operand))) { + EffectAnalyzer(parent->options, module->features, operand))) { mustReorder = true; break; } @@ -1339,7 +1302,7 @@ // because FUNCTION_TABLE is just a normal JS object, not a typed array // or a mathematical operation (all of which coerce to a number for us). auto target = visit(curr->target, EXPRESSION_RESULT); - target = makeJsCoercion(target, JS_INT); + target = makeAsmCoercion(target, ASM_INT); if (mustReorder) { Ref ret; ScopedTemp idx(Type::i32, parent, func); @@ -1357,10 +1320,10 @@ for (size_t i = 0; i < temps.size(); i++) { IString temp = temps[i]->temp; auto& operand = curr->operands[i]; - theCall[2]->push_back(makeJsCoercion(ValueBuilder::makeName(temp), - wasmToJsType(operand->type))); + theCall[2]->push_back(makeAsmCoercion(ValueBuilder::makeName(temp), + wasmToAsmType(operand->type))); } - theCall = makeJsCoercion(theCall, wasmToJsType(curr->type)); + theCall = makeAsmCoercion(theCall, wasmToAsmType(curr->type)); sequenceAppend(ret, theCall); for (auto temp : temps) { delete temp; @@ -1373,7 +1336,7 @@ for (auto* operand : curr->operands) { theCall[2]->push_back(visit(operand, EXPRESSION_RESULT)); } - theCall = makeJsCoercion(theCall, wasmToJsType(curr->type)); + theCall = makeAsmCoercion(theCall, wasmToAsmType(curr->type)); return theCall; } } @@ -1468,7 +1431,7 @@ bool needCoercions = parent->options.optimizeLevel == 0 || standaloneFunction; if (needCoercions) { - ret = makeJsCoercion(ret, wasmToJsType(curr->type)); + ret = makeAsmCoercion(ret, wasmToAsmType(curr->type)); } return ret; } @@ -1674,8 +1637,9 @@ RSHIFT, ValueBuilder::makeNum(16)); } - default: - WASM_UNREACHABLE("unhandled unary"); + default: { + Fatal() << "Unhandled unary i32 operator: " << curr; + } } } case Type::f32: @@ -1713,11 +1677,11 @@ MATH_SQRT, visit(curr->value, EXPRESSION_RESULT)); break; case PromoteFloat32: - return makeJsCoercion(visit(curr->value, EXPRESSION_RESULT), - JS_DOUBLE); + return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT), + ASM_DOUBLE); case DemoteFloat64: - return makeJsCoercion(visit(curr->value, EXPRESSION_RESULT), - JS_FLOAT); + return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT), + ASM_FLOAT); case ReinterpretInt32: { ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::SCRATCH_STORE_I32); @@ -1736,27 +1700,27 @@ } // Coerce the integer to a float as emscripten does case ConvertSInt32ToFloat32: - return makeJsCoercion( - makeJsCoercion(visit(curr->value, EXPRESSION_RESULT), JS_INT), - JS_FLOAT); + return makeAsmCoercion( + makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT), ASM_INT), + ASM_FLOAT); case ConvertSInt32ToFloat64: - return makeJsCoercion( - makeJsCoercion(visit(curr->value, EXPRESSION_RESULT), JS_INT), - JS_DOUBLE); + return makeAsmCoercion( + makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT), ASM_INT), + ASM_DOUBLE); // Generate (expr >>> 0), followed by a coercion case ConvertUInt32ToFloat32: - return makeJsCoercion( + return makeAsmCoercion( ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT), TRSHIFT, ValueBuilder::makeInt(0)), - JS_FLOAT); + ASM_FLOAT); case ConvertUInt32ToFloat64: - return makeJsCoercion( + return makeAsmCoercion( ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT), TRSHIFT, ValueBuilder::makeInt(0)), - JS_DOUBLE); + ASM_DOUBLE); // TODO: more complex unary conversions case NearestFloat32: case NearestFloat64: @@ -1767,7 +1731,7 @@ WASM_UNREACHABLE("unhandled unary float operator"); } if (curr->type == Type::f32) { // doubles need much less coercing - return makeJsCoercion(ret, JS_FLOAT); + return makeAsmCoercion(ret, ASM_FLOAT); } return ret; } @@ -1800,24 +1764,24 @@ } } case DivSInt32: - ret = ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); break; case DivUInt32: - ret = ValueBuilder::makeBinary(makeSigning(left, JS_UNSIGNED), + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV, - makeSigning(right, JS_UNSIGNED)); + makeSigning(right, ASM_UNSIGNED)); break; case RemSInt32: - ret = ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); break; case RemUInt32: - ret = ValueBuilder::makeBinary(makeSigning(left, JS_UNSIGNED), + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD, - makeSigning(right, JS_UNSIGNED)); + makeSigning(right, ASM_UNSIGNED)); break; case AndInt32: ret = ValueBuilder::makeBinary(left, AND, right); @@ -1838,47 +1802,47 @@ ret = ValueBuilder::makeBinary(left, RSHIFT, right); break; case EqInt32: { - return ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); } case NeInt32: { - return ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); } case LtSInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); case LtUInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_UNSIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT, - makeSigning(right, JS_UNSIGNED)); + makeSigning(right, ASM_UNSIGNED)); case LeSInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); case LeUInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_UNSIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE, - makeSigning(right, JS_UNSIGNED)); + makeSigning(right, ASM_UNSIGNED)); case GtSInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); case GtUInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_UNSIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT, - makeSigning(right, JS_UNSIGNED)); + makeSigning(right, ASM_UNSIGNED)); case GeSInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_SIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE, - makeSigning(right, JS_SIGNED)); + makeSigning(right, ASM_SIGNED)); case GeUInt32: - return ValueBuilder::makeBinary(makeSigning(left, JS_UNSIGNED), + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE, - makeSigning(right, JS_UNSIGNED)); + makeSigning(right, ASM_UNSIGNED)); case EqFloat32: case EqFloat64: return ValueBuilder::makeBinary(left, EQ, right); @@ -1938,13 +1902,13 @@ Fatal() << "Unhandled binary float operator: "; } if (curr->type == Type::f32) { - return makeJsCoercion(ret, JS_FLOAT); + return makeAsmCoercion(ret, ASM_FLOAT); } return ret; default: Fatal() << "Unhandled type in binary: " << curr; } - return makeJsCoercion(ret, wasmToJsType(curr->type)); + return makeAsmCoercion(ret, wasmToAsmType(curr->type)); } Ref visitSelect(Select* curr) { @@ -1953,9 +1917,11 @@ // side effects, as a JS conditional does not visit both sides. bool useLocals = false; EffectAnalyzer conditionEffects( - parent->options, *module, curr->condition); - EffectAnalyzer ifTrueEffects(parent->options, *module, curr->ifTrue); - EffectAnalyzer ifFalseEffects(parent->options, *module, curr->ifFalse); + parent->options, module->features, curr->condition); + EffectAnalyzer ifTrueEffects( + parent->options, module->features, curr->ifTrue); + EffectAnalyzer ifFalseEffects( + parent->options, module->features, curr->ifFalse); if (conditionEffects.invalidates(ifTrueEffects) || conditionEffects.invalidates(ifFalseEffects) || ifTrueEffects.hasSideEffects() || ifFalseEffects.hasSideEffects()) { @@ -1996,7 +1962,7 @@ parent->options.optimizeLevel == 0 || standaloneFunction || parent->functionsCallableFromOutside.count(func->name); if (needCoercion) { - val = makeJsCoercion(val, wasmToJsType(curr->value->type)); + val = makeAsmCoercion(val, wasmToAsmType(curr->value->type)); } return ValueBuilder::makeReturn(val); } @@ -2010,14 +1976,16 @@ module->memory.max > module->memory.initial) { return ValueBuilder::makeCall( WASM_MEMORY_GROW, - makeJsCoercion(visit(curr->delta, EXPRESSION_RESULT), - wasmToJsType(curr->delta->type))); + makeAsmCoercion(visit(curr->delta, EXPRESSION_RESULT), + wasmToAsmType(curr->delta->type))); } else { return ValueBuilder::makeCall(ABORT_FUNC); } } Ref visitNop(Nop* curr) { return ValueBuilder::makeToplevel(); } + Ref visitPrefetch(Prefetch* curr) { return ValueBuilder::makeToplevel(); } + Ref visitUnreachable(Unreachable* curr) { return ValueBuilder::makeCall(ABORT_FUNC); } @@ -2097,7 +2065,7 @@ ValueBuilder::appendToCall(call, hap.ptr); ValueBuilder::appendToCall(call, expected); ValueBuilder::appendToCall(call, replacement); - return makeJsCoercion(call, wasmToJsType(curr->type)); + return makeAsmCoercion(call, wasmToAsmType(curr->type)); } Ref visitAtomicWait(AtomicWait* curr) { @@ -2183,7 +2151,7 @@ unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitRefIs(RefIs* curr) { + Ref visitRefIsNull(RefIsNull* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); } @@ -2195,22 +2163,6 @@ unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitTableGet(TableGet* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitTableSet(TableSet* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitTableSize(TableSize* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitTableGrow(TableGrow* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitTry(Try* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); @@ -2223,6 +2175,10 @@ unimplemented(curr); WASM_UNREACHABLE("unimp"); } + Ref visitBrOnExn(BrOnExn* curr) { + unimplemented(curr); + WASM_UNREACHABLE("unimp"); + } Ref visitPop(Pop* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); @@ -2255,7 +2211,7 @@ unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitBrOn(BrOn* curr) { + Ref visitBrOnCast(BrOnCast* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); } @@ -2283,10 +2239,6 @@ unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitArrayInit(ArrayInit* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } Ref visitArrayGet(ArrayGet* curr) { unimplemented(curr); WASM_UNREACHABLE("unimp"); @@ -2299,28 +2251,20 @@ unimplemented(curr); WASM_UNREACHABLE("unimp"); } - Ref visitArrayCopy(ArrayCopy* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } - Ref visitRefAs(RefAs* curr) { - unimplemented(curr); - WASM_UNREACHABLE("unimp"); - } private: Ref makePointer(Expression* ptr, Address offset) { auto ret = visit(ptr, EXPRESSION_RESULT); if (offset) { - ret = makeJsCoercion( + ret = makeAsmCoercion( ValueBuilder::makeBinary(ret, PLUS, ValueBuilder::makeNum(offset)), - JS_INT); + ASM_INT); } return ret; } void unimplemented(Expression* curr) { - Fatal() << "wasm2js cannot convert " << *curr; + Fatal() << "wasm2js cannot convert " << getExpressionName(curr); } }; @@ -2330,12 +2274,12 @@ void Wasm2JSBuilder::addMemoryFuncs(Ref ast, Module* wasm) { Ref memorySizeFunc = ValueBuilder::makeFunction(WASM_MEMORY_SIZE); memorySizeFunc[3]->push_back(ValueBuilder::makeReturn( - makeJsCoercion(ValueBuilder::makeBinary( - ValueBuilder::makeDot(ValueBuilder::makeName(BUFFER), - IString("byteLength")), - DIV, - ValueBuilder::makeInt(Memory::kPageSize)), - JsType::JS_INT))); + makeAsmCoercion(ValueBuilder::makeBinary( + ValueBuilder::makeDot(ValueBuilder::makeName(BUFFER), + IString("byteLength")), + DIV, + ValueBuilder::makeInt(Memory::kPageSize)), + AsmType::ASM_INT))); ast->push_back(memorySizeFunc); if (wasm->memory.max > wasm->memory.initial) { @@ -2351,26 +2295,27 @@ ValueBuilder::makeStatement(ValueBuilder::makeBinary( ValueBuilder::makeName(IString("pagesToAdd")), SET, - makeJsCoercion(ValueBuilder::makeName(IString("pagesToAdd")), - JsType::JS_INT)))); + makeAsmCoercion(ValueBuilder::makeName(IString("pagesToAdd")), + AsmType::ASM_INT)))); Ref oldPages = ValueBuilder::makeVar(); memoryGrowFunc[3]->push_back(oldPages); ValueBuilder::appendToVar( oldPages, IString("oldPages"), - makeJsCoercion(ValueBuilder::makeCall(WASM_MEMORY_SIZE), JsType::JS_INT)); + makeAsmCoercion(ValueBuilder::makeCall(WASM_MEMORY_SIZE), + AsmType::ASM_INT)); Ref newPages = ValueBuilder::makeVar(); memoryGrowFunc[3]->push_back(newPages); ValueBuilder::appendToVar( newPages, IString("newPages"), - makeJsCoercion( + makeAsmCoercion( ValueBuilder::makeBinary(ValueBuilder::makeName(IString("oldPages")), PLUS, ValueBuilder::makeName(IString("pagesToAdd"))), - JsType::JS_INT)); + AsmType::ASM_INT)); Ref block = ValueBuilder::makeBlock(); memoryGrowFunc[3]->push_back(ValueBuilder::makeIf( @@ -2500,7 +2445,7 @@ if (isTableExported(wasm)) { out << "function Table(ret) {\n"; - if (wasm.tables[0]->initial == wasm.tables[0]->max) { + if (wasm.table.initial == wasm.table.max) { out << " // grow method not included; table is not growable\n"; } else { out << " ret.grow = function(by) {\n" @@ -2630,7 +2575,6 @@ for (auto& exp : wasm.exports) { switch (exp->kind) { case ExternalKind::Function: - case ExternalKind::Global: case ExternalKind::Memory: break; @@ -2887,14 +2831,9 @@ } else if (import->base == ABI::wasm2js::ATOMIC_WAIT_I32) { out << R"( function wasm2js_atomic_wait_i32(ptr, expected, timeoutLow, timeoutHigh) { - var timeout = Infinity; - if (timeoutHigh >= 0) { - // Convert from nanoseconds to milliseconds - // Taken from convertI32PairToI53 in emscripten's library_int53.js - timeout = ((timeoutLow >>> 0) / 1e6) + timeoutHigh * (4294967296 / 1e6); - } + if (timeoutLow != -1 || timeoutHigh != -1) throw 'unsupported timeout'; var view = new Int32Array(bufferView.buffer); // TODO cache - var result = Atomics.wait(view, ptr >> 2, expected, timeout); + var result = Atomics.wait(view, ptr, expected); if (result == 'ok') return 0; if (result == 'not-equal') return 1; if (result == 'timed-out') return 2; @@ -2904,7 +2843,7 @@ } else if (import->base == ABI::wasm2js::ATOMIC_RMW_I64) { out << R"( function wasm2js_atomic_rmw_i64(op, bytes, offset, ptr, valueLow, valueHigh) { - // TODO: support bytes=1, 2, 4 as well as 8. + assert(bytes == 8); // TODO: support 1, 2, 4 as well var view = new BigInt64Array(bufferView.buffer); // TODO cache ptr = (ptr + offset) >> 3; var value = BigInt(valueLow >>> 0) | (BigInt(valueHigh >>> 0) << BigInt(32)); diff -Nru binaryen-108/src/wasm-binary.h binaryen-99/src/wasm-binary.h --- binaryen-108/src/wasm-binary.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-binary.h 2021-01-07 20:01:06.000000000 +0000 @@ -326,30 +326,10 @@ Code = 10, Data = 11, DataCount = 12, - Tag = 13 + Event = 13 }; -// A passive segment is a segment that will not be automatically copied into a -// memory or table on instantiation, and must instead be applied manually -// using the instructions memory.init or table.init. -// An active segment is equivalent to a passive segment, but with an implicit -// memory.init followed by a data.drop (or table.init followed by a elem.drop) -// that is prepended to the module's start function. -// A declarative element segment is not available at runtime but merely serves -// to forward-declare references that are formed in code with instructions -// like ref.func. -enum SegmentFlag { - // Bit 0: 0 = active, 1 = passive - IsPassive = 1 << 0, - // Bit 1 if passive: 0 = passive, 1 = declarative - IsDeclarative = 1 << 1, - // Bit 1 if active: 0 = index 0, 1 = index given - HasIndex = 1 << 1, - // Table element segments only: - // Bit 2: 0 = elemType is funcref and a vector of func indexes given - // 1 = elemType is given and a vector of ref expressions is given - UsesExpressions = 1 << 2 -}; +enum SegmentFlag { IsPassive = 0x01, HasMemIndex = 0x02 }; enum EncodedType { // value_type @@ -362,8 +342,10 @@ i16 = -0x7, // 0x79 // function reference type funcref = -0x10, // 0x70 - // top type of references, including host references - anyref = -0x11, // 0x6f + // opaque host reference type + externref = -0x11, // 0x6f + // any reference type + anyref = -0x12, // 0x6e // comparable reference type eqref = -0x13, // 0x6d // nullable typed function reference type, with parameter @@ -375,36 +357,30 @@ // run-time type info type, with depth index n rtt_n = -0x17, // 0x69 // run-time type info type, without depth index n - rtt = -0x18, // 0x68 - dataref = -0x19, // 0x67 - // type forms + rtt = -0x18, // 0x68 + // exception reference type TODO remove; the code for now is incorrect + exnref = -0x19, // 0x67 + // func_type form Func = -0x20, // 0x60 Struct = -0x21, // 0x5f Array = -0x22, // 0x5e - Sub = -0x30, // 0x50 - // prototype nominal forms we still parse - FuncSubtype = -0x23, // 0x5d - StructSubtype = -0x24, // 0x5c - ArraySubtype = -0x25, // 0x5b - // isorecursive recursion groups - Rec = -0x31, // 0x4f // block_type Empty = -0x40 // 0x40 }; enum EncodedHeapType { - func = -0x10, // 0x70 - any = -0x11, // 0x6f - eq = -0x13, // 0x6d - i31 = -0x16, // 0x6a - data = -0x19, // 0x67 + func = -0x10, // 0x70 + extern_ = -0x11, // 0x6f + any = -0x12, // 0x6e + eq = -0x13, // 0x6d + i31 = -0x17, // 0x69, != i31ref + exn = -0x18, // 0x68 }; namespace UserSections { extern const char* Name; extern const char* SourceMapUrl; extern const char* Dylink; -extern const char* Dylink0; extern const char* Linking; extern const char* Producers; extern const char* TargetFeatures; @@ -423,8 +399,6 @@ extern const char* GCFeature; extern const char* Memory64Feature; extern const char* TypedFunctionReferencesFeature; -extern const char* RelaxedSIMDFeature; -extern const char* ExtendedConstFeature; enum Subsection { NameModule = 0, @@ -437,12 +411,7 @@ NameMemory = 6, NameGlobal = 7, NameElem = 8, - NameData = 9, - // see: https://github.com/WebAssembly/gc/issues/193 - NameField = 10, - - DylinkMemInfo = 1, - DylinkNeeded = 2, + NameData = 9 }; } // namespace UserSections @@ -476,9 +445,6 @@ GlobalGet = 0x23, GlobalSet = 0x24, - TableGet = 0x25, - TableSet = 0x26, - I32LoadMem = 0x28, I64LoadMem = 0x29, F32LoadMem = 0x2a, @@ -748,21 +714,21 @@ // SIMD opcodes V128Load = 0x00, - V128Load8x8S = 0x01, - V128Load8x8U = 0x02, - V128Load16x4S = 0x03, - V128Load16x4U = 0x04, - V128Load32x2S = 0x05, - V128Load32x2U = 0x06, - V128Load8Splat = 0x07, - V128Load16Splat = 0x08, - V128Load32Splat = 0x09, - V128Load64Splat = 0x0a, + I16x8LoadExtSVec8x8 = 0x01, + I16x8LoadExtUVec8x8 = 0x02, + I32x4LoadExtSVec16x4 = 0x03, + I32x4LoadExtUVec16x4 = 0x04, + I64x2LoadExtSVec32x2 = 0x05, + I64x2LoadExtUVec32x2 = 0x06, + V8x16LoadSplat = 0x07, + V16x8LoadSplat = 0x08, + V32x4LoadSplat = 0x09, + V64x2LoadSplat = 0x0a, V128Store = 0x0b, V128Const = 0x0c, - I8x16Shuffle = 0x0d, - I8x16Swizzle = 0x0e, + V8x16Shuffle = 0x0d, + V8x16Swizzle = 0x0e, I8x16Splat = 0x0f, I16x8Splat = 0x10, @@ -816,6 +782,7 @@ I32x4LeU = 0x3e, I32x4GeS = 0x3f, I32x4GeU = 0x40, + I64x2Eq = 0xc0, F32x4Eq = 0x41, F32x4Ne = 0x42, F32x4Lt = 0x43, @@ -831,37 +798,32 @@ V128Not = 0x4d, V128And = 0x4e, - V128Andnot = 0x4f, + V128AndNot = 0x4f, V128Or = 0x50, V128Xor = 0x51, V128Bitselect = 0x52, - V128AnyTrue = 0x53, - V128Load8Lane = 0x54, - V128Load16Lane = 0x55, - V128Load32Lane = 0x56, - V128Load64Lane = 0x57, - V128Store8Lane = 0x58, - V128Store16Lane = 0x59, - V128Store32Lane = 0x5a, - V128Store64Lane = 0x5b, - V128Load32Zero = 0x5c, - V128Load64Zero = 0x5d, - - F32x4DemoteF64x2Zero = 0x5e, - F64x2PromoteLowF32x4 = 0x5f, + V8x16SignSelect = 0x7d, + V16x8SignSelect = 0x7e, + V32x4SignSelect = 0x7f, + V64x2SignSelect = 0x94, + + V128Load8Lane = 0x58, + V128Load16Lane = 0x59, + V128Load32Lane = 0x5a, + V128Load64Lane = 0x5b, + V128Store8Lane = 0x5c, + V128Store16Lane = 0x5d, + V128Store32Lane = 0x5e, + V128Store64Lane = 0x5f, I8x16Abs = 0x60, I8x16Neg = 0x61, - I8x16Popcnt = 0x62, + I8x16AnyTrue = 0x62, I8x16AllTrue = 0x63, I8x16Bitmask = 0x64, - I8x16NarrowI16x8S = 0x65, - I8x16NarrowI16x8U = 0x66, - F32x4Ceil = 0x67, - F32x4Floor = 0x68, - F32x4Trunc = 0x69, - F32x4Nearest = 0x6a, + I8x16NarrowSI16x8 = 0x65, + I8x16NarrowUI16x8 = 0x66, I8x16Shl = 0x6b, I8x16ShrS = 0x6c, I8x16ShrU = 0x6d, @@ -871,30 +833,26 @@ I8x16Sub = 0x71, I8x16SubSatS = 0x72, I8x16SubSatU = 0x73, - F64x2Ceil = 0x74, - F64x2Floor = 0x75, + I8x16Mul = 0x75, I8x16MinS = 0x76, I8x16MinU = 0x77, I8x16MaxS = 0x78, I8x16MaxU = 0x79, - F64x2Trunc = 0x7a, I8x16AvgrU = 0x7b, - I16x8ExtaddPairwiseI8x16S = 0x7c, - I16x8ExtaddPairwiseI8x16U = 0x7d, - I32x4ExtaddPairwiseI16x8S = 0x7e, - I32x4ExtaddPairwiseI16x8U = 0x7f, + + I8x16Popcnt = 0x7c, I16x8Abs = 0x80, I16x8Neg = 0x81, - I16x8Q15MulrSatS = 0x82, + I16x8AnyTrue = 0x82, I16x8AllTrue = 0x83, I16x8Bitmask = 0x84, - I16x8NarrowI32x4S = 0x85, - I16x8NarrowI32x4U = 0x86, - I16x8ExtendLowI8x16S = 0x87, - I16x8ExtendHighI8x16S = 0x88, - I16x8ExtendLowI8x16U = 0x89, - I16x8ExtendHighI8x16U = 0x8a, + I16x8NarrowSI32x4 = 0x85, + I16x8NarrowUI32x4 = 0x86, + I16x8WidenLowSI8x16 = 0x87, + I16x8WidenHighSI8x16 = 0x88, + I16x8WidenLowUI8x16 = 0x89, + I16x8WidenHighUI8x16 = 0x8a, I16x8Shl = 0x8b, I16x8ShrS = 0x8c, I16x8ShrU = 0x8d, @@ -904,88 +862,50 @@ I16x8Sub = 0x91, I16x8SubSatS = 0x92, I16x8SubSatU = 0x93, - F64x2Nearest = 0x94, I16x8Mul = 0x95, I16x8MinS = 0x96, I16x8MinU = 0x97, I16x8MaxS = 0x98, I16x8MaxU = 0x99, - // 0x9a unused I16x8AvgrU = 0x9b, - I16x8ExtmulLowI8x16S = 0x9c, - I16x8ExtmulHighI8x16S = 0x9d, - I16x8ExtmulLowI8x16U = 0x9e, - I16x8ExtmulHighI8x16U = 0x9f, + I16x8Q15MulrSatS = 0x9c, I32x4Abs = 0xa0, I32x4Neg = 0xa1, - // 0xa2 for relaxed SIMD + I32x4AnyTrue = 0xa2, I32x4AllTrue = 0xa3, I32x4Bitmask = 0xa4, - // 0xa5 for relaxed SIMD - // 0xa6 for relaxed SIMD - I32x4ExtendLowI16x8S = 0xa7, - I32x4ExtendHighI16x8S = 0xa8, - I32x4ExtendLowI16x8U = 0xa9, - I32x4ExtendHighI16x8U = 0xaa, + I32x4WidenLowSI16x8 = 0xa7, + I32x4WidenHighSI16x8 = 0xa8, + I32x4WidenLowUI16x8 = 0xa9, + I32x4WidenHighUI16x8 = 0xaa, I32x4Shl = 0xab, I32x4ShrS = 0xac, I32x4ShrU = 0xad, I32x4Add = 0xae, - // 0xaf for relaxed SIMD - // 0xb0 for relaxed SIMD I32x4Sub = 0xb1, - // 0xb2 for relaxed SIMD - // 0xb3 for relaxed SIMD - // 0xb4 for relaxed SIMD I32x4Mul = 0xb5, I32x4MinS = 0xb6, I32x4MinU = 0xb7, I32x4MaxS = 0xb8, I32x4MaxU = 0xb9, - I32x4DotI16x8S = 0xba, - // 0xbb unused - I32x4ExtmulLowI16x8S = 0xbc, - I32x4ExtmulHighI16x8S = 0xbd, - I32x4ExtmulLowI16x8U = 0xbe, - I32x4ExtmulHighI16x8U = 0xbf, + I32x4DotSVecI16x8 = 0xba, - I64x2Abs = 0xc0, - I64x2Neg = 0xc1, - // 0xc2 unused - I64x2AllTrue = 0xc3, I64x2Bitmask = 0xc4, - // 0xc5 for relaxed SIMD - // 0xc6 for relaxed SIMD - I64x2ExtendLowI32x4S = 0xc7, - I64x2ExtendHighI32x4S = 0xc8, - I64x2ExtendLowI32x4U = 0xc9, - I64x2ExtendHighI32x4U = 0xca, + I64x2WidenLowSI32x4 = 0xc7, + I64x2WidenHighSI32x4 = 0xc8, + I64x2WidenLowUI32x4 = 0xc9, + I64x2WidenHighUI32x4 = 0xca, + I64x2Neg = 0xc1, I64x2Shl = 0xcb, I64x2ShrS = 0xcc, I64x2ShrU = 0xcd, I64x2Add = 0xce, - // 0xcf for relaxed SIMD - // 0xd0 for relaxed SIMD I64x2Sub = 0xd1, - // 0xd2 for relaxed SIMD - // 0xd3 for relaxed SIMD - // 0xd4 for relaxed SIMD I64x2Mul = 0xd5, - I64x2Eq = 0xd6, - I64x2Ne = 0xd7, - I64x2LtS = 0xd8, - I64x2GtS = 0xd9, - I64x2LeS = 0xda, - I64x2GeS = 0xdb, - I64x2ExtmulLowI32x4S = 0xdc, - I64x2ExtmulHighI32x4S = 0xdd, - I64x2ExtmulLowI32x4U = 0xde, - I64x2ExtmulHighI32x4U = 0xdf, F32x4Abs = 0xe0, F32x4Neg = 0xe1, - // 0xe2 for relaxed SIMD F32x4Sqrt = 0xe3, F32x4Add = 0xe4, F32x4Sub = 0xe5, @@ -993,12 +913,20 @@ F32x4Div = 0xe7, F32x4Min = 0xe8, F32x4Max = 0xe9, - F32x4Pmin = 0xea, - F32x4Pmax = 0xeb, + F32x4PMin = 0xea, + F32x4PMax = 0xeb, + + F32x4Ceil = 0xd8, + F32x4Floor = 0xd9, + F32x4Trunc = 0xda, + F32x4Nearest = 0xdb, + F64x2Ceil = 0xdc, + F64x2Floor = 0xdd, + F64x2Trunc = 0xde, + F64x2Nearest = 0xdf, F64x2Abs = 0xec, F64x2Neg = 0xed, - // 0xee for relaxed SIMD F64x2Sqrt = 0xef, F64x2Add = 0xf0, F64x2Sub = 0xf1, @@ -1006,41 +934,49 @@ F64x2Div = 0xf3, F64x2Min = 0xf4, F64x2Max = 0xf5, - F64x2Pmin = 0xf6, - F64x2Pmax = 0xf7, + F64x2PMin = 0xf6, + F64x2PMax = 0xf7, + + I16x8ExtAddPairWiseSI8x16 = 0xc2, + I16x8ExtAddPairWiseUI8x16 = 0xc3, + I32x4ExtAddPairWiseSI16x8 = 0xa5, + I32x4ExtAddPairWiseUI16x8 = 0xa6, + + I32x4TruncSatSF32x4 = 0xf8, + I32x4TruncSatUF32x4 = 0xf9, + F32x4ConvertSI32x4 = 0xfa, + F32x4ConvertUI32x4 = 0xfb, + + V128Load32Zero = 0xfc, + V128Load64Zero = 0xfd, + + F32x4QFMA = 0xb4, + F32x4QFMS = 0xd4, + F64x2QFMA = 0xfe, + F64x2QFMS = 0xff, + + I64x2TruncSatSF64x2 = 0x0100, + I64x2TruncSatUF64x2 = 0x0101, + F64x2ConvertSI64x2 = 0x0102, + F64x2ConvertUI64x2 = 0x0103, + + I16x8ExtMulLowSI8x16 = 0x9a, + I16x8ExtMulHighSI8x16 = 0x9d, + I16x8ExtMulLowUI8x16 = 0x9e, + I16x8ExtMulHighUI8x16 = 0x9f, + I32x4ExtMulLowSI16x8 = 0xbb, + I32x4ExtMulHighSI16x8 = 0xbd, + I32x4ExtMulLowUI16x8 = 0xbe, + I32x4ExtMulHighUI16x8 = 0xbf, + I64x2ExtMulLowSI32x4 = 0xd2, + I64x2ExtMulHighSI32x4 = 0xd3, + I64x2ExtMulLowUI32x4 = 0xd6, + I64x2ExtMulHighUI32x4 = 0xd7, - I32x4TruncSatF32x4S = 0xf8, - I32x4TruncSatF32x4U = 0xf9, - F32x4ConvertI32x4S = 0xfa, - F32x4ConvertI32x4U = 0xfb, - I32x4TruncSatF64x2SZero = 0xfc, - I32x4TruncSatF64x2UZero = 0xfd, - F64x2ConvertLowI32x4S = 0xfe, - F64x2ConvertLowI32x4U = 0xff, - - // relaxed SIMD opcodes - I8x16RelaxedSwizzle = 0xa2, - I32x4RelaxedTruncF32x4S = 0xa5, - I32x4RelaxedTruncF32x4U = 0xa6, - I32x4RelaxedTruncF64x2SZero = 0xc5, - I32x4RelaxedTruncF64x2UZero = 0xc6, - F32x4RelaxedFma = 0xaf, - F32x4RelaxedFms = 0xb0, - F64x2RelaxedFma = 0xcf, - F64x2RelaxedFms = 0xd0, - I8x16Laneselect = 0xb2, - I16x8Laneselect = 0xb3, - I32x4Laneselect = 0xd2, - I64x2Laneselect = 0xd3, - F32x4RelaxedMin = 0xb4, - F32x4RelaxedMax = 0xe2, - F64x2RelaxedMin = 0xd4, - F64x2RelaxedMax = 0xee, - I16x8RelaxedQ15MulrS = 0x111, - I16x8DotI8x16I7x16S = 0x112, - I16x8DotI8x16I7x16U = 0x113, - I32x4DotI8x16I7x16AddS = 0x114, - I32x4DotI8x16I7x16AddU = 0x115, + // prefetch opcodes + + PrefetchT = 0xc5, + PrefetchNT = 0xc6, // bulk memory opcodes @@ -1051,29 +987,22 @@ // reference types opcodes - TableGrow = 0x0f, - TableSize = 0x10, RefNull = 0xd0, RefIsNull = 0xd1, RefFunc = 0xd2, - RefAsNonNull = 0xd3, - BrOnNull = 0xd4, - BrOnNonNull = 0xd6, // exception handling opcodes Try = 0x06, Catch = 0x07, - CatchAll = 0x19, - Delegate = 0x18, Throw = 0x08, Rethrow = 0x09, + BrOnExn = 0x0a, // typed function references opcodes CallRef = 0x14, RetCallRef = 0x15, - Let = 0x17, // gc opcodes @@ -1084,8 +1013,6 @@ StructGetS = 0x04, StructGetU = 0x05, StructSet = 0x06, - StructNew = 0x07, - StructNewDefault = 0x08, ArrayNewWithRtt = 0x11, ArrayNewDefaultWithRtt = 0x12, ArrayGet = 0x13, @@ -1093,38 +1020,14 @@ ArrayGetU = 0x15, ArraySet = 0x16, ArrayLen = 0x17, - ArrayCopy = 0x18, - ArrayInit = 0x19, - ArrayInitStatic = 0x1a, - ArrayNew = 0x1b, - ArrayNewDefault = 0x1c, I31New = 0x20, I31GetS = 0x21, I31GetU = 0x22, RttCanon = 0x30, RttSub = 0x31, - RttFreshSub = 0x32, RefTest = 0x40, RefCast = 0x41, - BrOnCast = 0x42, - BrOnCastFail = 0x43, - RefTestStatic = 0x44, - RefCastStatic = 0x45, - BrOnCastStatic = 0x46, - BrOnCastStaticFail = 0x47, - RefCastNopStatic = 0x48, - RefIsFunc = 0x50, - RefIsData = 0x51, - RefIsI31 = 0x52, - RefAsFunc = 0x58, - RefAsData = 0x59, - RefAsI31 = 0x5a, - BrOnFunc = 0x60, - BrOnData = 0x61, - BrOnI31 = 0x62, - BrOnNonFunc = 0x63, - BrOnNonData = 0x64, - BrOnNonI31 = 0x65, + BrOnCast = 0x42 }; enum MemoryAccess { @@ -1143,9 +1046,6 @@ } // namespace BinaryConsts -// (local index in IR, tuple index) => binary local index -using MappedLocals = std::unordered_map, size_t>; - // Writes out wasm to the binary format class WasmBinaryWriter { @@ -1156,10 +1056,8 @@ // just use them directly). struct BinaryIndexes { std::unordered_map functionIndexes; - std::unordered_map tagIndexes; + std::unordered_map eventIndexes; std::unordered_map globalIndexes; - std::unordered_map tableIndexes; - std::unordered_map elemIndexes; BinaryIndexes(Module& wasm) { auto addIndexes = [&](auto& source, auto& indexes) { @@ -1179,13 +1077,7 @@ } }; addIndexes(wasm.functions, functionIndexes); - addIndexes(wasm.tags, tagIndexes); - addIndexes(wasm.tables, tableIndexes); - - for (auto& curr : wasm.elementSegments) { - auto index = elemIndexes.size(); - elemIndexes[curr->name] = index; - } + addIndexes(wasm.events, eventIndexes); // Globals may have tuple types in the IR, in which case they lower to // multiple globals, one for each tuple element, in the binary. Tuple @@ -1227,11 +1119,7 @@ std::vector functionBodies; } tableOfContents; - void setNamesSection(bool set) { - debugInfo = set; - emitModuleName = set; - } - void setEmitModuleName(bool set) { emitModuleName = set; } + void setNamesSection(bool set) { debugInfo = set; } void setSourceMap(std::ostream* set, std::string url) { sourceMap = set; sourceMapUrl = url; @@ -1259,16 +1147,15 @@ void writeExports(); void writeDataCount(); void writeDataSegments(); - void writeTags(); + void writeEvents(); uint32_t getFunctionIndex(Name name) const; - uint32_t getTableIndex(Name name) const; uint32_t getGlobalIndex(Name name) const; - uint32_t getTagIndex(Name name) const; + uint32_t getEventIndex(Name name) const; uint32_t getTypeIndex(HeapType type) const; - void writeTableDeclarations(); - void writeElementSegments(); + void writeFunctionTableDeclaration(); + void writeTableElements(); void writeNames(); void writeSourceMapUrl(); void writeSymbolMap(); @@ -1276,7 +1163,6 @@ void writeUserSection(const UserSection& section); void writeFeaturesSection(); void writeDylinkSection(); - void writeLegacyDylinkSection(); void initializeDebugInfo(); void writeSourceMapProlog(); @@ -1284,13 +1170,14 @@ void writeDebugLocation(const Function::DebugLocation& loc); void writeDebugLocation(Expression* curr, Function* func); void writeDebugLocationEnd(Expression* curr, Function* func); - void writeExtraDebugLocation(Expression* curr, Function* func, size_t id); + void writeExtraDebugLocation(Expression* curr, + Function* func, + BinaryLocations::DelimiterId id); // helpers void writeInlineString(const char* name); void writeEscapedName(const char* name); void writeInlineBuffer(const char* data, size_t size); - void writeData(const char* data, size_t size); struct Buffer { const char* data; @@ -1300,34 +1187,26 @@ : data(data), size(size), pointerLocation(pointerLocation) {} }; + std::vector buffersToWrite; + + void emitBuffer(const char* data, size_t size); + void emitString(const char* str); + void finishUp(); + Module* getModule() { return wasm; } void writeType(Type type); - - // Writes an arbitrary heap type, which may be indexed or one of the - // basic types like funcref. void writeHeapType(HeapType type); - // Writes an indexed heap type. Note that this is encoded differently than a - // general heap type because it does not allow negative values for basic heap - // types. - void writeIndexedHeapType(HeapType type); - void writeField(const Field& field); private: Module* wasm; BufferWithRandomAccess& o; BinaryIndexes indexes; - ModuleUtils::IndexedHeapTypes indexedTypes; + std::unordered_map typeIndices; + std::vector types; bool debugInfo = true; - - // TODO: Remove `emitModuleName` in the future once there are better ways to - // ensure modules have meaningful names in stack traces.For example, using - // ObjectURLs works in FireFox, but not Chrome. See - // https://bugs.chromium.org/p/v8/issues/detail?id=11808. - bool emitModuleName = true; - std::ostream* sourceMap = nullptr; std::string sourceMapUrl; std::string symbolMap; @@ -1351,11 +1230,6 @@ // the function is written out. std::vector binaryLocationTrackedExpressionsForFunc; - // Maps function names to their mapped locals. This is used when we emit the - // local names section: we map the locals when writing the function, save that - // info here, and then use it when writing the names. - std::unordered_map funcMappedLocals; - void prepare(); }; @@ -1365,9 +1239,7 @@ const std::vector& input; std::istream* sourceMap; std::pair nextDebugLocation; - bool debugInfo = true; bool DWARF = false; - bool skipFunctionBodies = false; size_t pos = 0; Index startIndex = -1; @@ -1380,21 +1252,16 @@ std::vector types; public: - WasmBinaryBuilder(Module& wasm, - FeatureSet features, - const std::vector& input); + WasmBinaryBuilder(Module& wasm, const std::vector& input) + : wasm(wasm), allocator(wasm.allocator), input(input), sourceMap(nullptr), + nextDebugLocation(0, {0, 0, 0}), debugLocation() {} - void setDebugInfo(bool value) { debugInfo = value; } void setDWARF(bool value) { DWARF = value; } - void setSkipFunctionBodies(bool skipFunctionBodies_) { - skipFunctionBodies = skipFunctionBodies_; - } void read(); void readUserSection(size_t payloadLen); bool more() { return pos < input.size(); } - std::pair getByteView(size_t size); uint8_t getInt8(); uint16_t getInt16(); uint32_t getInt32(); @@ -1411,15 +1278,14 @@ int64_t getS64LEB(); uint64_t getUPtrLEB(); - bool getBasicType(int32_t code, Type& out); - bool getBasicHeapType(int64_t code, HeapType& out); // Read a value and get a type for it. Type getType(); // Get a type given the initial S32LEB has already been read, and is provided. Type getType(int initial); - HeapType getHeapType(); - HeapType getIndexedHeapType(); + HeapType getHeapType(); + Mutability getMutability(); + Field getField(); Type getConcreteType(); Name getInlineString(); void verifyInt8(int8_t x); @@ -1433,9 +1299,8 @@ // gets a name in the combined import+defined space Name getFunctionName(Index index); - Name getTableName(Index index); Name getGlobalName(Index index); - Name getTagName(Index index); + Name getEventName(Index index); void getResizableLimits(Address& initial, Address& max, @@ -1444,16 +1309,12 @@ Address defaultIfNoMax); void readImports(); - // The signatures of each function, including imported functions, given in the - // import and function sections. Store HeapTypes instead of Signatures because - // reconstructing the HeapTypes from the Signatures is expensive. - std::vector functionTypes; + // The signatures of each function, given in the function section + std::vector functionSignatures; void readFunctionSignatures(); - HeapType getTypeByIndex(Index index); - HeapType getTypeByFunctionIndex(Index index); - Signature getSignatureByTypeIndex(Index index); Signature getSignatureByFunctionIndex(Index index); + Signature getSignatureByTypeIndex(Index index); size_t nextLabel; @@ -1474,20 +1335,6 @@ // function to check Index endOfFunction = -1; - // we store tables here before wasm.addTable after we know their names - std::vector> tables; - // we store table imports here before wasm.addTableImport after we know - // their names - std::vector tableImports; - // at index i we have all references to the table i - std::map> tableRefs; - - std::map elemTables; - - // we store elems here after being read from binary, until when we know their - // names - std::vector> elementSegments; - // we store globals here before wasm.addGlobal after we know their names std::vector> globals; // we store global imports here before wasm.addGlobalImport after we know @@ -1500,7 +1347,6 @@ void requireFunctionContext(const char* error); void readFunctions(); - void readVars(); std::map exportIndices; std::vector exportOrder; @@ -1518,34 +1364,9 @@ // the names that breaks target. this lets us know if a block has breaks to it // or not. std::unordered_set breakTargetNames; - // the names that delegates target. - std::unordered_set exceptionTargetNames; std::vector expressionStack; - // Each let block in the binary adds new locals to the bottom of the index - // space. That is, all previously-existing indexes are bumped to higher - // indexes. getAbsoluteLocalIndex does this computation. - // Note that we must track not just the number of locals added in each let, - // but also the absolute index from which they were allocated, as binaryen - // will add new locals as it goes for things like stacky code and tuples (so - // there isn't a simple way to get to the absolute index from a relative one). - // Hence each entry here is a pair of the number of items, and the absolute - // index they begin at. - struct LetData { - // How many items are defined in this let. - Index num; - // The absolute index from which they are allocated from. That is, if num is - // 5 and absoluteStart is 10, then we use indexes 10-14. - Index absoluteStart; - }; - std::vector letStack; - - // Given a relative index of a local (the one used in the wasm binary), get - // the absolute one which takes into account lets, and is the one used in - // Binaryen IR. - Index getAbsoluteLocalIndex(Index index); - // Control flow structure parsing: these have not just the normal binary // data for an instruction, but also some bytes later on like "end" or "else". // We must be aware of the connection between those things, for debug info. @@ -1554,6 +1375,10 @@ // Called when we parse the beginning of a control flow structure. void startControlFlow(Expression* curr); + // Called when we parse a later part of a control flow structure, like "end" + // or "else". + void continueControlFlow(BinaryLocations::DelimiterId id, BinaryLocation pos); + // set when we know code is unreachable in the sense of the wasm spec: we are // in a block and after an unreachable element. this helps parse stacky wasm // code, which can be unsuitable for our IR when unreachable. @@ -1594,16 +1419,17 @@ void readDataSegments(); void readDataCount(); - void readTableDeclarations(); - void readElementSegments(); + std::map> functionTable; - void readTags(); + void readFunctionTableDeclaration(); + void readTableElements(); + + void readEvents(); static Name escape(Name name); void readNames(size_t); void readFeatures(size_t); void readDylink(size_t); - void readDylink0(size_t); // Debug information reading helpers void setDebugLocations(std::istream* sourceMap_) { sourceMap = sourceMap_; } @@ -1611,6 +1437,8 @@ void readNextDebugLocation(); void readSourceMapHeader(); + void handleBrOnExnNotTaken(Expression* curr); + // AST reading int depth = 0; // only for debugging @@ -1622,7 +1450,6 @@ Expression* getBlockOrSingleton(Type type); BreakTarget getBreakTarget(int32_t offset); - Name getExceptionTargetName(int32_t offset); void readMemoryAccess(Address& alignment, Address& offset); @@ -1659,28 +1486,25 @@ bool maybeVisitSIMDShift(Expression*& out, uint32_t code); bool maybeVisitSIMDLoad(Expression*& out, uint32_t code); bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code); + bool maybeVisitPrefetch(Expression*& out, uint32_t code); bool maybeVisitMemoryInit(Expression*& out, uint32_t code); bool maybeVisitDataDrop(Expression*& out, uint32_t code); bool maybeVisitMemoryCopy(Expression*& out, uint32_t code); bool maybeVisitMemoryFill(Expression*& out, uint32_t code); - bool maybeVisitTableSize(Expression*& out, uint32_t code); - bool maybeVisitTableGrow(Expression*& out, uint32_t code); bool maybeVisitI31New(Expression*& out, uint32_t code); bool maybeVisitI31Get(Expression*& out, uint32_t code); bool maybeVisitRefTest(Expression*& out, uint32_t code); bool maybeVisitRefCast(Expression*& out, uint32_t code); - bool maybeVisitBrOn(Expression*& out, uint32_t code); + bool maybeVisitBrOnCast(Expression*& out, uint32_t code); bool maybeVisitRttCanon(Expression*& out, uint32_t code); bool maybeVisitRttSub(Expression*& out, uint32_t code); bool maybeVisitStructNew(Expression*& out, uint32_t code); bool maybeVisitStructGet(Expression*& out, uint32_t code); bool maybeVisitStructSet(Expression*& out, uint32_t code); bool maybeVisitArrayNew(Expression*& out, uint32_t code); - bool maybeVisitArrayInit(Expression*& out, uint32_t code); bool maybeVisitArrayGet(Expression*& out, uint32_t code); bool maybeVisitArraySet(Expression*& out, uint32_t code); bool maybeVisitArrayLen(Expression*& out, uint32_t code); - bool maybeVisitArrayCopy(Expression*& out, uint32_t code); void visitSelect(Select* curr, uint8_t code); void visitReturn(Return* curr); void visitMemorySize(MemorySize* curr); @@ -1689,18 +1513,14 @@ void visitUnreachable(Unreachable* curr); void visitDrop(Drop* curr); void visitRefNull(RefNull* curr); - void visitRefIs(RefIs* curr, uint8_t code); + void visitRefIsNull(RefIsNull* curr); void visitRefFunc(RefFunc* curr); void visitRefEq(RefEq* curr); - void visitTableGet(TableGet* curr); - void visitTableSet(TableSet* curr); void visitTryOrTryInBlock(Expression*& out); void visitThrow(Throw* curr); void visitRethrow(Rethrow* curr); + void visitBrOnExn(BrOnExn* curr); void visitCallRef(CallRef* curr); - void visitRefAs(RefAs* curr, uint8_t code); - // Let is lowered into a block. - void visitLet(Block* curr); void throwError(std::string text); diff -Nru binaryen-108/src/wasm-builder.h binaryen-99/src/wasm-builder.h --- binaryen-108/src/wasm-builder.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-builder.h 2021-01-07 20:01:06.000000000 +0000 @@ -18,7 +18,6 @@ #define wasm_wasm_builder_h #include "ir/manipulation.h" -#include "parsing.h" #include "wasm.h" namespace wasm { @@ -40,16 +39,15 @@ public: Builder(Module& wasm) : wasm(wasm) {} - // make* functions create an expression instance. + // make* functions, other globals static std::unique_ptr makeFunction(Name name, - HeapType type, + Signature sig, std::vector&& vars, Expression* body = nullptr) { - assert(type.isSignature()); auto func = std::make_unique(); func->name = name; - func->type = type; + func->sig = sig; func->body = body; func->vars.swap(vars); return func; @@ -57,21 +55,20 @@ static std::unique_ptr makeFunction(Name name, std::vector&& params, - HeapType type, + Type resultType, std::vector&& vars, Expression* body = nullptr) { - assert(type.isSignature()); auto func = std::make_unique(); func->name = name; - func->type = type; func->body = body; - for (size_t i = 0; i < params.size(); ++i) { - NameType& param = params[i]; - assert(func->getParams()[i] == param.type); + std::vector paramVec; + for (auto& param : params) { + paramVec.push_back(param.type); Index index = func->localNames.size(); func->localIndices[param.name] = index; func->localNames[index] = param.name; } + func->sig = Signature(Type(paramVec), resultType); for (auto& var : vars) { func->vars.push_back(var.type); Index index = func->localNames.size(); @@ -81,31 +78,6 @@ return func; } - static std::unique_ptr
makeTable(Name name, - Type type = Type::funcref, - Address initial = 0, - Address max = Table::kMaxSize) { - auto table = std::make_unique
(); - table->name = name; - table->type = type; - table->initial = initial; - table->max = max; - return table; - } - - static std::unique_ptr - makeElementSegment(Name name, - Name table, - Expression* offset = nullptr, - Type type = Type::funcref) { - auto seg = std::make_unique(); - seg->name = name; - seg->table = table; - seg->offset = offset; - seg->type = type; - return seg; - } - static std::unique_ptr makeExport(Name name, Name value, ExternalKind kind) { auto export_ = std::make_unique(); @@ -127,11 +99,13 @@ return glob; } - static std::unique_ptr makeTag(Name name, Signature sig) { - auto tag = std::make_unique(); - tag->name = name; - tag->sig = sig; - return tag; + static std::unique_ptr + makeEvent(Name name, uint32_t attribute, Signature sig) { + auto event = std::make_unique(); + event->name = name; + event->attribute = attribute; + event->sig = sig; + return event; } // IR nodes @@ -270,16 +244,13 @@ return call; } template - CallIndirect* makeCallIndirect(const Name table, - Expression* target, + CallIndirect* makeCallIndirect(Expression* target, const T& args, - HeapType heapType, + Signature sig, bool isReturn = false) { - assert(heapType.isSignature()); auto* call = wasm.allocator.alloc(); - call->table = table; - call->heapType = heapType; - call->type = heapType.getSignature().results; + call->sig = sig; + call->type = sig.results; call->target = target; call->operands.set(args); call->isReturn = isReturn; @@ -515,6 +486,16 @@ ret->finalize(); return ret; } + Prefetch* + makePrefetch(PrefetchOp op, Address offset, Address align, Expression* ptr) { + auto* ret = wasm.allocator.alloc(); + ret->op = op; + ret->offset = offset; + ret->align = align; + ret->ptr = ptr; + ret->finalize(); + return ret; + } MemoryInit* makeMemoryInit(uint32_t segment, Expression* dest, Expression* offset, @@ -619,27 +600,21 @@ ret->finalize(); return ret; } - RefNull* makeRefNull(HeapType type) { - auto* ret = wasm.allocator.alloc(); - ret->finalize(Type(type, Nullable)); - return ret; - } RefNull* makeRefNull(Type type) { auto* ret = wasm.allocator.alloc(); ret->finalize(type); return ret; } - RefIs* makeRefIs(RefIsOp op, Expression* value) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; + RefIsNull* makeRefIsNull(Expression* value) { + auto* ret = wasm.allocator.alloc(); ret->value = value; ret->finalize(); return ret; } - RefFunc* makeRefFunc(Name func, HeapType heapType) { + RefFunc* makeRefFunc(Name func, Type type) { auto* ret = wasm.allocator.alloc(); ret->func = func; - ret->finalize(Type(heapType, NonNullable)); + ret->finalize(type); return ret; } RefEq* makeRefEq(Expression* left, Expression* right) { @@ -649,110 +624,47 @@ ret->finalize(); return ret; } - TableGet* makeTableGet(Name table, Expression* index, Type type) { - auto* ret = wasm.allocator.alloc(); - ret->table = table; - ret->index = index; - ret->type = type; - ret->finalize(); - return ret; - } - TableSet* makeTableSet(Name table, Expression* index, Expression* value) { - auto* ret = wasm.allocator.alloc(); - ret->table = table; - ret->index = index; - ret->value = value; - ret->finalize(); - return ret; - } - TableSize* makeTableSize(Name table) { - auto* ret = wasm.allocator.alloc(); - ret->table = table; - ret->finalize(); - return ret; - } - TableGrow* makeTableGrow(Name table, Expression* value, Expression* delta) { - auto* ret = wasm.allocator.alloc(); - ret->table = table; - ret->value = value; - ret->delta = delta; + Try* makeTry(Expression* body, Expression* catchBody) { + auto* ret = wasm.allocator.alloc(); + ret->body = body; + ret->catchBody = catchBody; ret->finalize(); return ret; } - -private: - Try* makeTry(Name name, - Expression* body, - const std::vector& catchTags, - const std::vector& catchBodies, - Name delegateTarget, - Type type, - bool hasType) { // differentiate whether a type was passed in + Try* makeTry(Expression* body, Expression* catchBody, Type type) { auto* ret = wasm.allocator.alloc(); - ret->name = name; ret->body = body; - ret->catchTags.set(catchTags); - ret->catchBodies.set(catchBodies); - if (hasType) { - ret->finalize(type); - } else { - ret->finalize(); - } + ret->catchBody = catchBody; + ret->finalize(type); return ret; } - -public: - Try* makeTry(Expression* body, - const std::vector& catchTags, - const std::vector& catchBodies) { - return makeTry( - Name(), body, catchTags, catchBodies, Name(), Type::none, false); - } - Try* makeTry(Expression* body, - const std::vector& catchTags, - const std::vector& catchBodies, - Type type) { - return makeTry(Name(), body, catchTags, catchBodies, Name(), type, true); - } - Try* makeTry(Name name, - Expression* body, - const std::vector& catchTags, - const std::vector& catchBodies) { - return makeTry( - name, body, catchTags, catchBodies, Name(), Type::none, false); - } - Try* makeTry(Name name, - Expression* body, - const std::vector& catchTags, - const std::vector& catchBodies, - Type type) { - return makeTry(name, body, catchTags, catchBodies, Name(), type, true); - } - Try* makeTry(Expression* body, Name delegateTarget) { - return makeTry(Name(), body, {}, {}, delegateTarget, Type::none, false); - } - Try* makeTry(Expression* body, Name delegateTarget, Type type) { - return makeTry(Name(), body, {}, {}, delegateTarget, type, true); - } - Try* makeTry(Name name, Expression* body, Name delegateTarget) { - return makeTry(name, body, {}, {}, delegateTarget, Type::none, false); - } - Try* makeTry(Name name, Expression* body, Name delegateTarget, Type type) { - return makeTry(name, body, {}, {}, delegateTarget, type, true); + Throw* makeThrow(Event* event, const std::vector& args) { + return makeThrow(event->name, args); } - Throw* makeThrow(Tag* tag, const std::vector& args) { - return makeThrow(tag->name, args); - } - Throw* makeThrow(Name tag, const std::vector& args) { + Throw* makeThrow(Name event, const std::vector& args) { auto* ret = wasm.allocator.alloc(); - ret->tag = tag; + ret->event = event; ret->operands.set(args); ret->finalize(); return ret; } - Rethrow* makeRethrow(Name target) { + Rethrow* makeRethrow(Expression* exnref) { auto* ret = wasm.allocator.alloc(); - ret->target = target; + ret->exnref = exnref; + ret->finalize(); + return ret; + } + BrOnExn* makeBrOnExn(Name name, Event* event, Expression* exnref) { + return makeBrOnExn(name, event->name, exnref, event->sig.params); + } + BrOnExn* makeBrOnExn(Name name, Name event, Expression* exnref, Type sent) { + auto* ret = wasm.allocator.alloc(); + ret->name = name; + ret->event = event; + ret->exnref = exnref; + // Copy params info into BrOnExn, because it is necessary when BrOnExn is + // refinalized without the module. + ret->sent = sent; ret->finalize(); return ret; } @@ -796,13 +708,6 @@ ret->finalize(); return ret; } - RefTest* makeRefTest(Expression* ref, HeapType intendedType) { - auto* ret = wasm.allocator.alloc(); - ret->ref = ref; - ret->intendedType = intendedType; - ret->finalize(); - return ret; - } RefCast* makeRefCast(Expression* ref, Expression* rtt) { auto* ret = wasm.allocator.alloc(); ret->ref = ref; @@ -810,38 +715,19 @@ ret->finalize(); return ret; } - - RefCast* - makeRefCast(Expression* ref, HeapType intendedType, RefCast::Safety safety) { - auto* ret = wasm.allocator.alloc(); - ret->ref = ref; - ret->intendedType = intendedType; - ret->safety = safety; - ret->finalize(); - return ret; - } - BrOn* - makeBrOn(BrOnOp op, Name name, Expression* ref, Expression* rtt = nullptr) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; + BrOnCast* + makeBrOnCast(Name name, HeapType heapType, Expression* ref, Expression* rtt) { + auto* ret = wasm.allocator.alloc(); ret->name = name; + ret->castType = Type(heapType, Nullable); ret->ref = ref; ret->rtt = rtt; ret->finalize(); return ret; } - BrOn* makeBrOn(BrOnOp op, Name name, Expression* ref, HeapType intendedType) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; - ret->name = name; - ret->ref = ref; - ret->intendedType = intendedType; - ret->finalize(); - return ret; - } RttCanon* makeRttCanon(HeapType heapType) { auto* ret = wasm.allocator.alloc(); - ret->type = Type(Rtt(heapType.getDepth(), heapType)); + ret->type = Type(Rtt(0, heapType)); ret->finalize(); return ret; } @@ -857,11 +743,6 @@ ret->finalize(); return ret; } - RttSub* makeRttFreshSub(HeapType heapType, Expression* parent) { - auto* ret = makeRttSub(heapType, parent); - ret->fresh = true; - return ret; - } template StructNew* makeStructNew(Expression* rtt, const T& args) { auto* ret = wasm.allocator.alloc(); @@ -870,13 +751,6 @@ ret->finalize(); return ret; } - template StructNew* makeStructNew(HeapType type, const T& args) { - auto* ret = wasm.allocator.alloc(); - ret->operands.set(args); - ret->type = Type(type, NonNullable); - ret->finalize(); - return ret; - } StructGet* makeStructGet(Index index, Expression* ref, Type type, bool signed_ = false) { auto* ret = wasm.allocator.alloc(); @@ -904,31 +778,6 @@ ret->finalize(); return ret; } - ArrayNew* - makeArrayNew(HeapType type, Expression* size, Expression* init = nullptr) { - auto* ret = wasm.allocator.alloc(); - ret->size = size; - ret->init = init; - ret->type = Type(type, NonNullable); - ret->finalize(); - return ret; - } - ArrayInit* makeArrayInit(Expression* rtt, - const std::vector& values) { - auto* ret = wasm.allocator.alloc(); - ret->rtt = rtt; - ret->values.set(values); - ret->finalize(); - return ret; - } - ArrayInit* makeArrayInit(HeapType type, - const std::vector& values) { - auto* ret = wasm.allocator.alloc(); - ret->values.set(values); - ret->type = Type(type, NonNullable); - ret->finalize(); - return ret; - } ArrayGet* makeArrayGet(Expression* ref, Expression* index, bool signed_ = false) { auto* ret = wasm.allocator.alloc(); @@ -953,27 +802,6 @@ ret->finalize(); return ret; } - ArrayCopy* makeArrayCopy(Expression* destRef, - Expression* destIndex, - Expression* srcRef, - Expression* srcIndex, - Expression* length) { - auto* ret = wasm.allocator.alloc(); - ret->destRef = destRef; - ret->destIndex = destIndex; - ret->srcRef = srcRef; - ret->srcIndex = srcIndex; - ret->length = length; - ret->finalize(); - return ret; - } - RefAs* makeRefAs(RefAsOp op, Expression* value) { - auto* ret = wasm.allocator.alloc(); - ret->op = op; - ret->value = value; - ret->finalize(); - return ret; - } // Additional helpers @@ -995,13 +823,12 @@ return makeRefNull(type); } if (type.isFunction()) { - return makeRefFunc(value.getFunc(), type.getHeapType()); - } - if (type.isRtt()) { - return makeRtt(value.type); + return makeRefFunc(value.getFunc(), type); } TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { + case Type::externref: + case Type::exnref: // TODO: ExceptionPackage? case Type::anyref: case Type::eqref: assert(value.isNull() && "unexpected non-null reference type literal"); @@ -1026,29 +853,16 @@ } } - // Given a type, creates an RTT expression of that type, using a combination - // of rtt.canon and rtt.subs. - Expression* makeRtt(Type type) { - Expression* ret = makeRttCanon(type.getHeapType()); - if (type.getRtt().hasDepth()) { - for (Index i = 0; i < type.getRtt().depth; i++) { - ret = makeRttSub(type.getHeapType(), ret); - } - } - return ret; - } - // Additional utility functions for building on top of nodes // Convenient to have these on Builder, as it has allocation built in static Index addParam(Function* func, Name name, Type type) { // only ok to add a param if no vars, otherwise indices are invalidated - assert(func->localIndices.size() == func->getParams().size()); + assert(func->localIndices.size() == func->sig.params.size()); assert(name.is()); - Signature sig = func->getSig(); - std::vector params(sig.params.begin(), sig.params.end()); + std::vector params(func->sig.params.begin(), func->sig.params.end()); params.push_back(type); - func->type = Signature(Type(params), sig.results); + func->sig.params = Type(params); Index index = func->localNames.size(); func->localIndices[name] = index; func->localNames[index] = name; @@ -1076,6 +890,12 @@ func->localIndices.clear(); } + static void clearLocals(Function* func) { + func->sig.params = Type::none; + func->vars.clear(); + clearLocalNames(func); + } + // ensure a node is a block, if it isn't already, and optionally append to the // block Block* blockify(Expression* any, Expression* append = nullptr) { @@ -1134,6 +954,33 @@ return block; } + // Grab a slice out of a block, replacing it with nops, and returning + // either another block with the contents (if more than 1) or a single + // expression + Expression* stealSlice(Block* input, Index from, Index to) { + Expression* ret; + if (to == from + 1) { + // just one + ret = input->list[from]; + } else { + auto* block = wasm.allocator.alloc(); + for (Index i = from; i < to; i++) { + block->list.push_back(input->list[i]); + } + block->finalize(); + ret = block; + } + if (to == input->list.size()) { + input->list.resize(from); + } else { + for (Index i = from; i < to; i++) { + input->list[i] = wasm.allocator.alloc(); + } + } + input->finalize(); + return ret; + } + // Drop an expression if it has a concrete type Expression* dropIfConcretelyTyped(Expression* curr) { if (!curr->type.isConcrete()) { @@ -1147,21 +994,23 @@ iff->condition = makeUnary(EqZInt32, iff->condition); } - // Returns a replacement with the precise same type, and with minimal contents - // as best we can. As a replacement, this may reuse the input node. + // returns a replacement with the precise same type, and with + // minimal contents. as a replacement, this may reuse the + // input node template Expression* replaceWithIdenticalType(T* curr) { - if (curr->type.isTuple() && curr->type.isDefaultable()) { + if (curr->type.isTuple()) { return makeConstantExpression(Literal::makeZeros(curr->type)); } if (curr->type.isNullable()) { return ExpressionManipulator::refNull(curr, curr->type); } - if (curr->type.isFunction() || !curr->type.isBasic()) { + if (curr->type.isFunction()) { // We can't do any better, keep the original. return curr; } Literal value; // TODO: reuse node conditionally when possible for literals + TODO_SINGLE_COMPOUND(curr->type); switch (curr->type.getBasic()) { case Type::i32: value = Literal(int32_t(0)); @@ -1183,13 +1032,13 @@ } case Type::funcref: WASM_UNREACHABLE("handled above"); + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: return ExpressionManipulator::refNull(curr, curr->type); case Type::i31ref: return makeI31New(makeConst(0)); - case Type::dataref: - return curr; case Type::none: return ExpressionManipulator::nop(curr); case Type::unreachable: @@ -1199,65 +1048,6 @@ } }; -// This class adds methods that first inspect the input. They may not have fully -// comprehensive error checking, when that can be left to the validator; the -// benefit of the validate* methods is that they can share code between the -// text and binary format parsers, for handling certain situations in the -// input which preclude even creating valid IR, which the validator depends -// on. -class ValidatingBuilder : public Builder { - size_t line = -1, col = -1; - -public: - ValidatingBuilder(Module& wasm, size_t line) : Builder(wasm), line(line) {} - ValidatingBuilder(Module& wasm, size_t line, size_t col) - : Builder(wasm), line(line), col(col) {} - - Expression* validateAndMakeBrOn(BrOnOp op, - Name name, - Expression* ref, - Expression* rtt = nullptr) { - if (op == BrOnCast) { - if (rtt->type == Type::unreachable) { - // An unreachable rtt is not supported: the text and binary formats do - // not provide the type, so if it's unreachable we should not even - // create a br_on_cast in such a case, as we'd have no idea what it - // casts to. - return makeSequence(makeDrop(ref), rtt); - } - } - if (op == BrOnNull) { - if (!ref->type.isRef() && ref->type != Type::unreachable) { - throw ParseException("Invalid ref for br_on_null", line, col); - } - } - return makeBrOn(op, name, ref, rtt); - } - - template - Expression* validateAndMakeCallRef(Expression* target, - const T& args, - bool isReturn = false) { - if (!target->type.isRef()) { - if (target->type == Type::unreachable) { - // An unreachable target is not supported. Similiar to br_on_cast, just - // emit an unreachable sequence, since we don't have enough information - // to create a full call_ref. - auto* block = makeBlock(args); - block->list.push_back(target); - block->finalize(Type::unreachable); - return block; - } - throw ParseException("Non-reference type for a call_ref", line, col); - } - auto heapType = target->type.getHeapType(); - if (!heapType.isSignature()) { - throw ParseException("Invalid reference type for a call_ref", line, col); - } - return makeCallRef(target, args, heapType.getSignature().results, isReturn); - } -}; - } // namespace wasm #endif // wasm_wasm_builder_h diff -Nru binaryen-108/src/wasm-debug.h binaryen-99/src/wasm-debug.h --- binaryen-108/src/wasm-debug.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-debug.h 2021-01-07 20:01:06.000000000 +0000 @@ -23,10 +23,11 @@ #include -#include "pass.h" #include "wasm.h" -namespace wasm::Debug { +namespace wasm { + +namespace Debug { bool isDWARFSection(Name name); @@ -35,14 +36,12 @@ // Dump the DWARF sections to stdout. void dumpDWARF(const Module& wasm); -// Check whether we should preserve valid DWARF while optimizing. (If so, we -// will disable optimizations that currently cause issues with debug info.) -bool shouldPreserveDWARF(PassOptions& options, Module& wasm); - // Update the DWARF sections. void writeDWARFSections(Module& wasm, const BinaryLocations& newLocations); -} // namespace wasm::Debug +} // namespace Debug + +} // namespace wasm #undef DEBUG_TYPE diff -Nru binaryen-108/src/wasm-delegations.def binaryen-99/src/wasm-delegations.def --- binaryen-108/src/wasm-delegations.def 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-delegations.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright 2020 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -DELEGATE(Nop); -DELEGATE(Block); -DELEGATE(If); -DELEGATE(Loop); -DELEGATE(Break); -DELEGATE(Switch); -DELEGATE(Call); -DELEGATE(CallIndirect); -DELEGATE(LocalGet); -DELEGATE(LocalSet); -DELEGATE(GlobalGet); -DELEGATE(GlobalSet); -DELEGATE(Load); -DELEGATE(Store); -DELEGATE(AtomicRMW); -DELEGATE(AtomicCmpxchg); -DELEGATE(AtomicWait); -DELEGATE(AtomicNotify); -DELEGATE(AtomicFence); -DELEGATE(SIMDExtract); -DELEGATE(SIMDReplace); -DELEGATE(SIMDShuffle); -DELEGATE(SIMDTernary); -DELEGATE(SIMDShift); -DELEGATE(SIMDLoad); -DELEGATE(SIMDLoadStoreLane); -DELEGATE(MemoryInit); -DELEGATE(DataDrop); -DELEGATE(MemoryCopy); -DELEGATE(MemoryFill); -DELEGATE(Const); -DELEGATE(Unary); -DELEGATE(Binary); -DELEGATE(Select); -DELEGATE(Drop); -DELEGATE(Return); -DELEGATE(MemorySize); -DELEGATE(MemoryGrow); -DELEGATE(Unreachable); -DELEGATE(Pop); -DELEGATE(RefNull); -DELEGATE(RefIs); -DELEGATE(RefFunc); -DELEGATE(RefEq); -DELEGATE(TableGet); -DELEGATE(TableSet); -DELEGATE(TableSize); -DELEGATE(TableGrow); -DELEGATE(Try); -DELEGATE(Throw); -DELEGATE(Rethrow); -DELEGATE(TupleMake); -DELEGATE(TupleExtract); -DELEGATE(I31New); -DELEGATE(I31Get); -DELEGATE(CallRef); -DELEGATE(RefTest); -DELEGATE(RefCast); -DELEGATE(BrOn); -DELEGATE(RttCanon); -DELEGATE(RttSub); -DELEGATE(StructNew); -DELEGATE(StructGet); -DELEGATE(StructSet); -DELEGATE(ArrayNew); -DELEGATE(ArrayInit); -DELEGATE(ArrayGet); -DELEGATE(ArraySet); -DELEGATE(ArrayLen); -DELEGATE(ArrayCopy); -DELEGATE(RefAs); - -#undef DELEGATE diff -Nru binaryen-108/src/wasm-delegations-fields.def binaryen-99/src/wasm-delegations-fields.def --- binaryen-108/src/wasm-delegations-fields.def 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-delegations-fields.def 1970-01-01 00:00:00.000000000 +0000 @@ -1,735 +0,0 @@ -/* - * Copyright 2020 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Implements a switch on an expression class ID, and has a case for each id -// in which it runs delegates on the fields and immediates. You should include -// this file after defining the relevant DELEGATE_* macros. -// -// All defines used here are undefed automatically at the end for you. -// -// Most of the defines are necessary, and you will get an error if you forget -// them, but some are optional and some imply others, see below. -// -// The defines are as follows: -// -// DELEGATE_START(id) - called at the start of a case for an expression class. -// -// DELEGATE_END(id) - called at the end of a case. -// -// DELEGATE_GET_FIELD(id, field) - called to get a field by its name. This must -// know the object on which to get it, so it is just useful for the case -// where you operate on a single such object, but in that case it is nice -// because then other things can be defined automatically for you, see later. -// -// DELEGATE_FIELD_CHILD(id, field) - called for each child field (note: children -// are visited in reverse order, which is convenient for walking by pushing -// them to a stack first). -// -// DELEGATE_FIELD_OPTIONAL_CHILD(id, field) - called for a child that may not be -// present (like a Return's value). If you do not define this then -// DELEGATE_FIELD_CHILD is called. -// -// DELEGATE_FIELD_CHILD_VECTOR(id, field) - called for a variable-sized vector -// of child pointers. If this is not defined, and DELEGATE_GET_FIELD is, then -// DELEGATE_FIELD_CHILD is called on them. -// -// DELEGATE_FIELD_INT(id, field) - called for an integer field (bool, enum, -// Index, int32, or int64). -// -// DELEGATE_FIELD_INT_ARRAY(id, field) - called for a std::array of fixed size -// of integer values (like a SIMD mask). If this is not defined, and -// DELEGATE_GET_FIELD is, then DELEGATE_FIELD_INT is called on them. -// -// DELEGATE_FIELD_LITERAL(id, field) - called for a Literal. -// -// DELEGATE_FIELD_NAME(id, field) - called for a Name. -// -// DELEGATE_FIELD_NAME_VECTOR(id, field) - called for a variable-sized vector of -// names (like try's catch tag names). If this is not defined, and -// DELEGATE_GET_FIELD is, then DELEGATE_FIELD_CHILD is called on them. -// -// DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) - called for a scope name definition -// (like a block's name). -// -// DELEGATE_FIELD_SCOPE_NAME_USE(id, field) - called for a scope name use (like -// a break's target). -// -// DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) - called for a variable-sized -// vector of scope names (like a switch's targets). If this is not defined, -// and DELEGATE_GET_FIELD is, then DELEGATE_FIELD_SCOPE_NAME_USE is called on -// them. -// -// DELEGATE_FIELD_TYPE(id, field) - called for a Type. -// -// DELEGATE_FIELD_HEAPTYPE(id, field) - called for a HeapType. -// -// DELEGATE_FIELD_ADDRESS(id, field) - called for an Address. - -#ifndef DELEGATE_START -#define DELEGATE_START(id) -#endif - -#ifndef DELEGATE_END -#define DELEGATE_END(id) -#endif - -#ifndef DELEGATE_FIELD_CHILD -#error please define DELEGATE_FIELD_CHILD(id, field) -#endif - -#ifndef DELEGATE_FIELD_OPTIONAL_CHILD -#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field) DELEGATE_FIELD_CHILD(id, field) -#endif - -#ifndef DELEGATE_FIELD_CHILD_VECTOR -#ifdef DELEGATE_GET_FIELD -#define DELEGATE_FIELD_CHILD_VECTOR(id, field) \ - for (int i = int((DELEGATE_GET_FIELD(id, field)).size()) - 1; i >= 0; i--) { \ - DELEGATE_FIELD_CHILD(id, field[i]); \ - } -#else -#error please define DELEGATE_FIELD_CHILD_VECTOR(id, field) -#endif -#endif - -#ifndef DELEGATE_FIELD_INT -#error please define DELEGATE_FIELD_INT(id, field) -#endif - -#ifndef DELEGATE_FIELD_INT_ARRAY -#ifdef DELEGATE_GET_FIELD -#define DELEGATE_FIELD_INT_ARRAY(id, field) \ - for (Index i = 0; i < (DELEGATE_GET_FIELD(id, field)).size(); i++) { \ - DELEGATE_FIELD_INT(id, field[i]); \ - } -#else -#error please define DELEGATE_FIELD_INT_ARRAY(id, field) -#endif -#endif - -#ifndef DELEGATE_FIELD_LITERAL -#error please define DELEGATE_FIELD_LITERAL(id, field) -#endif - -#ifndef DELEGATE_FIELD_NAME -#error please define DELEGATE_FIELD_NAME(id, field) -#endif - -#ifndef DELEGATE_FIELD_NAME_VECTOR -#ifdef DELEGATE_GET_FIELD -#define DELEGATE_FIELD_NAME_VECTOR(id, field) \ - for (Index i = 0; i < (DELEGATE_GET_FIELD(id, field)).size(); i++) { \ - DELEGATE_FIELD_NAME(id, field[i]); \ - } -#else -#error please define DELEGATE_FIELD_NAME_VECTOR(id, field) -#endif -#endif - -#ifndef DELEGATE_FIELD_SCOPE_NAME_DEF -#error please define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) -#endif - -#ifndef DELEGATE_FIELD_SCOPE_NAME_USE -#error please define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) -#endif - -#ifndef DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR -#ifdef DELEGATE_GET_FIELD -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) \ - for (Index i = 0; i < (DELEGATE_GET_FIELD(id, field)).size(); i++) { \ - DELEGATE_FIELD_SCOPE_NAME_USE(id, field[i]); \ - } -#else -#error please define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) -#endif -#endif - -#ifndef DELEGATE_FIELD_TYPE -#error please define DELEGATE_FIELD_TYPE(id, field) -#endif - -#ifndef DELEGATE_FIELD_HEAPTYPE -#error please define DELEGATE_FIELD_HEAPTYPE(id, field) -#endif - -#ifndef DELEGATE_FIELD_ADDRESS -#error please define DELEGATE_FIELD_ADDRESS(id, field) -#endif - -switch (DELEGATE_ID) { - case Expression::Id::InvalidId: - case Expression::Id::NumExpressionIds: { - WASM_UNREACHABLE("unexpected expression type"); - } - case Expression::Id::BlockId: { - DELEGATE_START(Block); - DELEGATE_FIELD_CHILD_VECTOR(Block, list); - DELEGATE_FIELD_SCOPE_NAME_DEF(Block, name); - DELEGATE_END(Block); - break; - } - case Expression::Id::IfId: { - DELEGATE_START(If); - DELEGATE_FIELD_OPTIONAL_CHILD(If, ifFalse); - DELEGATE_FIELD_CHILD(If, ifTrue); - DELEGATE_FIELD_CHILD(If, condition); - DELEGATE_END(If); - break; - } - case Expression::Id::LoopId: { - DELEGATE_START(Loop); - DELEGATE_FIELD_CHILD(Loop, body); - DELEGATE_FIELD_SCOPE_NAME_DEF(Loop, name); - DELEGATE_END(Loop); - break; - } - case Expression::Id::BreakId: { - DELEGATE_START(Break); - DELEGATE_FIELD_OPTIONAL_CHILD(Break, condition); - DELEGATE_FIELD_OPTIONAL_CHILD(Break, value); - DELEGATE_FIELD_SCOPE_NAME_USE(Break, name); - DELEGATE_END(Break); - break; - } - case Expression::Id::SwitchId: { - DELEGATE_START(Switch); - DELEGATE_FIELD_CHILD(Switch, condition); - DELEGATE_FIELD_OPTIONAL_CHILD(Switch, value); - DELEGATE_FIELD_SCOPE_NAME_USE(Switch, default_); - DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(Switch, targets); - DELEGATE_END(Switch); - break; - } - case Expression::Id::CallId: { - DELEGATE_START(Call); - DELEGATE_FIELD_CHILD_VECTOR(Call, operands); - DELEGATE_FIELD_NAME(Call, target); - DELEGATE_FIELD_INT(Call, isReturn); - DELEGATE_END(Call); - break; - } - case Expression::Id::CallIndirectId: { - DELEGATE_START(CallIndirect); - DELEGATE_FIELD_CHILD(CallIndirect, target); - DELEGATE_FIELD_NAME(CallIndirect, table); - DELEGATE_FIELD_CHILD_VECTOR(CallIndirect, operands); - DELEGATE_FIELD_HEAPTYPE(CallIndirect, heapType); - DELEGATE_FIELD_INT(CallIndirect, isReturn); - DELEGATE_END(CallIndirect); - break; - } - case Expression::Id::LocalGetId: { - DELEGATE_START(LocalGet); - DELEGATE_FIELD_INT(LocalGet, index); - DELEGATE_END(LocalGet); - break; - } - case Expression::Id::LocalSetId: { - DELEGATE_START(LocalSet); - DELEGATE_FIELD_CHILD(LocalSet, value); - DELEGATE_FIELD_INT(LocalSet, index); - DELEGATE_END(LocalSet); - break; - } - case Expression::Id::GlobalGetId: { - DELEGATE_START(GlobalGet); - DELEGATE_FIELD_INT(GlobalGet, name); - DELEGATE_END(GlobalGet); - break; - } - case Expression::Id::GlobalSetId: { - DELEGATE_START(GlobalSet); - DELEGATE_FIELD_CHILD(GlobalSet, value); - DELEGATE_FIELD_INT(GlobalSet, name); - DELEGATE_END(GlobalSet); - break; - } - case Expression::Id::LoadId: { - DELEGATE_START(Load); - DELEGATE_FIELD_CHILD(Load, ptr); - DELEGATE_FIELD_INT(Load, bytes); - DELEGATE_FIELD_INT(Load, signed_); - DELEGATE_FIELD_ADDRESS(Load, offset); - DELEGATE_FIELD_ADDRESS(Load, align); - DELEGATE_FIELD_INT(Load, isAtomic); - DELEGATE_END(Load); - break; - } - case Expression::Id::StoreId: { - DELEGATE_START(Store); - DELEGATE_FIELD_CHILD(Store, value); - DELEGATE_FIELD_CHILD(Store, ptr); - DELEGATE_FIELD_INT(Store, bytes); - DELEGATE_FIELD_ADDRESS(Store, offset); - DELEGATE_FIELD_ADDRESS(Store, align); - DELEGATE_FIELD_INT(Store, isAtomic); - DELEGATE_FIELD_TYPE(Store, valueType); - DELEGATE_END(Store); - break; - } - case Expression::Id::AtomicRMWId: { - DELEGATE_START(AtomicRMW); - DELEGATE_FIELD_CHILD(AtomicRMW, value); - DELEGATE_FIELD_CHILD(AtomicRMW, ptr); - DELEGATE_FIELD_INT(AtomicRMW, op); - DELEGATE_FIELD_INT(AtomicRMW, bytes); - DELEGATE_FIELD_ADDRESS(AtomicRMW, offset); - DELEGATE_END(AtomicRMW); - break; - } - case Expression::Id::AtomicCmpxchgId: { - DELEGATE_START(AtomicCmpxchg); - DELEGATE_FIELD_CHILD(AtomicCmpxchg, replacement); - DELEGATE_FIELD_CHILD(AtomicCmpxchg, expected); - DELEGATE_FIELD_CHILD(AtomicCmpxchg, ptr); - DELEGATE_FIELD_INT(AtomicCmpxchg, bytes); - DELEGATE_FIELD_ADDRESS(AtomicCmpxchg, offset); - DELEGATE_END(AtomicCmpxchg); - break; - } - case Expression::Id::AtomicWaitId: { - DELEGATE_START(AtomicWait); - DELEGATE_FIELD_CHILD(AtomicWait, timeout); - DELEGATE_FIELD_CHILD(AtomicWait, expected); - DELEGATE_FIELD_CHILD(AtomicWait, ptr); - DELEGATE_FIELD_ADDRESS(AtomicWait, offset); - DELEGATE_FIELD_TYPE(AtomicWait, expectedType); - DELEGATE_END(AtomicWait); - break; - } - case Expression::Id::AtomicNotifyId: { - DELEGATE_START(AtomicNotify); - DELEGATE_FIELD_CHILD(AtomicNotify, notifyCount); - DELEGATE_FIELD_CHILD(AtomicNotify, ptr); - DELEGATE_FIELD_ADDRESS(AtomicNotify, offset); - DELEGATE_END(AtomicNotify); - break; - } - case Expression::Id::AtomicFenceId: { - DELEGATE_START(AtomicFence); - DELEGATE_FIELD_INT(AtomicFence, order); - DELEGATE_END(AtomicFence); - break; - } - case Expression::Id::SIMDExtractId: { - DELEGATE_START(SIMDExtract); - DELEGATE_FIELD_CHILD(SIMDExtract, vec); - DELEGATE_FIELD_INT(SIMDExtract, op); - DELEGATE_FIELD_INT(SIMDExtract, index); - DELEGATE_END(SIMDExtract); - break; - } - case Expression::Id::SIMDReplaceId: { - DELEGATE_START(SIMDReplace); - DELEGATE_FIELD_CHILD(SIMDReplace, value); - DELEGATE_FIELD_CHILD(SIMDReplace, vec); - DELEGATE_FIELD_INT(SIMDReplace, op); - DELEGATE_FIELD_INT(SIMDReplace, index); - DELEGATE_END(SIMDReplace); - break; - } - case Expression::Id::SIMDShuffleId: { - DELEGATE_START(SIMDShuffle); - DELEGATE_FIELD_CHILD(SIMDShuffle, right); - DELEGATE_FIELD_CHILD(SIMDShuffle, left); - DELEGATE_FIELD_INT_ARRAY(SIMDShuffle, mask); - DELEGATE_END(SIMDShuffle); - break; - } - case Expression::Id::SIMDTernaryId: { - DELEGATE_START(SIMDTernary); - DELEGATE_FIELD_CHILD(SIMDTernary, c); - DELEGATE_FIELD_CHILD(SIMDTernary, b); - DELEGATE_FIELD_CHILD(SIMDTernary, a); - DELEGATE_FIELD_INT(SIMDTernary, op); - DELEGATE_END(SIMDTernary); - break; - } - case Expression::Id::SIMDShiftId: { - DELEGATE_START(SIMDShift); - DELEGATE_FIELD_CHILD(SIMDShift, shift); - DELEGATE_FIELD_CHILD(SIMDShift, vec); - DELEGATE_FIELD_INT(SIMDShift, op); - DELEGATE_END(SIMDShift); - break; - } - case Expression::Id::SIMDLoadId: { - DELEGATE_START(SIMDLoad); - DELEGATE_FIELD_CHILD(SIMDLoad, ptr); - DELEGATE_FIELD_INT(SIMDLoad, op); - DELEGATE_FIELD_ADDRESS(SIMDLoad, offset); - DELEGATE_FIELD_ADDRESS(SIMDLoad, align); - DELEGATE_END(SIMDLoad); - break; - } - case Expression::Id::SIMDLoadStoreLaneId: { - DELEGATE_START(SIMDLoadStoreLane); - DELEGATE_FIELD_CHILD(SIMDLoadStoreLane, vec); - DELEGATE_FIELD_CHILD(SIMDLoadStoreLane, ptr); - DELEGATE_FIELD_INT(SIMDLoadStoreLane, op); - DELEGATE_FIELD_ADDRESS(SIMDLoadStoreLane, offset); - DELEGATE_FIELD_ADDRESS(SIMDLoadStoreLane, align); - DELEGATE_FIELD_INT(SIMDLoadStoreLane, index); - DELEGATE_END(SIMDLoadStoreLane); - break; - } - case Expression::Id::MemoryInitId: { - DELEGATE_START(MemoryInit); - DELEGATE_FIELD_CHILD(MemoryInit, size); - DELEGATE_FIELD_CHILD(MemoryInit, offset); - DELEGATE_FIELD_CHILD(MemoryInit, dest); - DELEGATE_FIELD_INT(MemoryInit, segment); - DELEGATE_END(MemoryInit); - break; - } - case Expression::Id::DataDropId: { - DELEGATE_START(DataDrop); - DELEGATE_FIELD_INT(DataDrop, segment); - DELEGATE_END(DataDrop); - break; - } - case Expression::Id::MemoryCopyId: { - DELEGATE_START(MemoryCopy); - DELEGATE_FIELD_CHILD(MemoryCopy, size); - DELEGATE_FIELD_CHILD(MemoryCopy, source); - DELEGATE_FIELD_CHILD(MemoryCopy, dest); - DELEGATE_END(MemoryCopy); - break; - } - case Expression::Id::MemoryFillId: { - DELEGATE_START(MemoryFill); - DELEGATE_FIELD_CHILD(MemoryFill, size); - DELEGATE_FIELD_CHILD(MemoryFill, value); - DELEGATE_FIELD_CHILD(MemoryFill, dest); - DELEGATE_END(MemoryFill); - break; - } - case Expression::Id::ConstId: { - DELEGATE_START(Const); - DELEGATE_FIELD_LITERAL(Const, value); - DELEGATE_END(Const); - break; - } - case Expression::Id::UnaryId: { - DELEGATE_START(Unary); - DELEGATE_FIELD_CHILD(Unary, value); - DELEGATE_FIELD_INT(Unary, op); - DELEGATE_END(Unary); - break; - } - case Expression::Id::BinaryId: { - DELEGATE_START(Binary); - DELEGATE_FIELD_CHILD(Binary, right); - DELEGATE_FIELD_CHILD(Binary, left); - DELEGATE_FIELD_INT(Binary, op); - DELEGATE_END(Binary); - break; - } - case Expression::Id::SelectId: { - DELEGATE_START(Select); - DELEGATE_FIELD_CHILD(Select, condition); - DELEGATE_FIELD_CHILD(Select, ifFalse); - DELEGATE_FIELD_CHILD(Select, ifTrue); - DELEGATE_END(Select); - break; - } - case Expression::Id::DropId: { - DELEGATE_START(Drop); - DELEGATE_FIELD_CHILD(Drop, value); - DELEGATE_END(Drop); - break; - } - case Expression::Id::ReturnId: { - DELEGATE_START(Return); - DELEGATE_FIELD_OPTIONAL_CHILD(Return, value); - DELEGATE_END(Return); - break; - } - case Expression::Id::MemorySizeId: { - DELEGATE_START(MemorySize); - DELEGATE_FIELD_TYPE(MemorySize, ptrType); - DELEGATE_END(MemorySize); - break; - } - case Expression::Id::MemoryGrowId: { - DELEGATE_START(MemoryGrow); - DELEGATE_FIELD_TYPE(MemoryGrow, ptrType); - DELEGATE_FIELD_CHILD(MemoryGrow, delta); - DELEGATE_END(MemoryGrow); - break; - } - case Expression::Id::RefNullId: { - DELEGATE_START(RefNull); - DELEGATE_END(RefNull); - break; - } - case Expression::Id::RefIsId: { - DELEGATE_START(RefIs); - DELEGATE_FIELD_INT(RefIs, op); - DELEGATE_FIELD_CHILD(RefIs, value); - DELEGATE_END(RefIs); - break; - } - case Expression::Id::RefFuncId: { - DELEGATE_START(RefFunc); - DELEGATE_FIELD_NAME(RefFunc, func); - DELEGATE_END(RefFunc); - break; - } - case Expression::Id::RefEqId: { - DELEGATE_START(RefEq); - DELEGATE_FIELD_CHILD(RefEq, right); - DELEGATE_FIELD_CHILD(RefEq, left); - DELEGATE_END(RefEq); - break; - } - case Expression::Id::TableGetId: { - DELEGATE_START(TableGet); - DELEGATE_FIELD_CHILD(TableGet, index); - DELEGATE_FIELD_NAME(TableGet, table); - DELEGATE_END(TableGet); - break; - } - case Expression::Id::TableSetId: { - DELEGATE_START(TableSet); - DELEGATE_FIELD_CHILD(TableSet, value); - DELEGATE_FIELD_CHILD(TableSet, index); - DELEGATE_FIELD_NAME(TableSet, table); - DELEGATE_END(TableSet); - break; - } - case Expression::Id::TableSizeId: { - DELEGATE_START(TableSize); - DELEGATE_FIELD_NAME(TableSize, table); - DELEGATE_END(TableSize); - break; - } - case Expression::Id::TableGrowId: { - DELEGATE_START(TableGrow); - DELEGATE_FIELD_CHILD(TableGrow, delta); - DELEGATE_FIELD_CHILD(TableGrow, value); - DELEGATE_FIELD_NAME(TableGrow, table); - DELEGATE_END(TableGrow); - break; - } - case Expression::Id::TryId: { - DELEGATE_START(Try); - DELEGATE_FIELD_SCOPE_NAME_USE(Try, delegateTarget); - DELEGATE_FIELD_CHILD_VECTOR(Try, catchBodies); - DELEGATE_FIELD_NAME_VECTOR(Try, catchTags); - DELEGATE_FIELD_SCOPE_NAME_DEF(Try, name); - DELEGATE_FIELD_CHILD(Try, body); - DELEGATE_END(Try); - break; - } - case Expression::Id::ThrowId: { - DELEGATE_START(Throw); - DELEGATE_FIELD_CHILD_VECTOR(Throw, operands); - DELEGATE_FIELD_NAME(Throw, tag); - DELEGATE_END(Throw); - break; - } - case Expression::Id::RethrowId: { - DELEGATE_START(Rethrow); - DELEGATE_FIELD_SCOPE_NAME_USE(Rethrow, target); - DELEGATE_END(Rethrow); - break; - } - case Expression::Id::NopId: { - DELEGATE_START(Nop); - DELEGATE_END(Nop); - break; - } - case Expression::Id::UnreachableId: { - DELEGATE_START(Unreachable); - DELEGATE_END(Unreachable); - break; - } - case Expression::Id::PopId: { - DELEGATE_START(Pop); - DELEGATE_END(Pop); - break; - } - case Expression::Id::TupleMakeId: { - DELEGATE_START(TupleMake); - DELEGATE_FIELD_CHILD_VECTOR(Tuple, operands); - DELEGATE_END(TupleMake); - break; - } - case Expression::Id::TupleExtractId: { - DELEGATE_START(TupleExtract); - DELEGATE_FIELD_CHILD(TupleExtract, tuple); - DELEGATE_FIELD_INT(TupleExtract, index); - DELEGATE_END(TupleExtract); - break; - } - case Expression::Id::I31NewId: { - DELEGATE_START(I31New); - DELEGATE_FIELD_CHILD(I31New, value); - DELEGATE_END(I31New); - break; - } - case Expression::Id::I31GetId: { - DELEGATE_START(I31Get); - DELEGATE_FIELD_CHILD(I31Get, i31); - DELEGATE_FIELD_INT(I31Get, signed_); - DELEGATE_END(I31Get); - break; - } - case Expression::Id::CallRefId: { - DELEGATE_START(CallRef); - DELEGATE_FIELD_CHILD(CallRef, target); - DELEGATE_FIELD_CHILD_VECTOR(CallRef, operands); - DELEGATE_FIELD_INT(CallRef, isReturn); - DELEGATE_END(CallRef); - break; - } - case Expression::Id::RefTestId: { - DELEGATE_START(RefTest); - DELEGATE_FIELD_HEAPTYPE(RefTest, intendedType); - DELEGATE_FIELD_OPTIONAL_CHILD(RefTest, rtt); - DELEGATE_FIELD_CHILD(RefTest, ref); - DELEGATE_END(RefTest); - break; - } - case Expression::Id::RefCastId: { - DELEGATE_START(RefCast); - DELEGATE_FIELD_HEAPTYPE(RefCast, intendedType); - DELEGATE_FIELD_OPTIONAL_CHILD(RefCast, rtt); - DELEGATE_FIELD_CHILD(RefCast, ref); - DELEGATE_END(RefCast); - break; - } - case Expression::Id::BrOnId: { - DELEGATE_START(BrOn); - DELEGATE_FIELD_INT(BrOn, op); - DELEGATE_FIELD_SCOPE_NAME_USE(BrOn, name); - DELEGATE_FIELD_HEAPTYPE(BrOn, intendedType); - DELEGATE_FIELD_OPTIONAL_CHILD(BrOn, rtt); - DELEGATE_FIELD_CHILD(BrOn, ref); - DELEGATE_END(BrOn); - break; - } - case Expression::Id::RttCanonId: { - DELEGATE_START(RttCanon); - DELEGATE_END(RttCanon); - break; - } - case Expression::Id::RttSubId: { - DELEGATE_START(RttSub); - DELEGATE_FIELD_CHILD(RttSub, parent); - DELEGATE_FIELD_INT(RttSub, fresh); - DELEGATE_END(RttSub); - break; - } - case Expression::Id::StructNewId: { - DELEGATE_START(StructNew); - DELEGATE_FIELD_OPTIONAL_CHILD(StructNew, rtt); - DELEGATE_FIELD_CHILD_VECTOR(StructNew, operands); - DELEGATE_END(StructNew); - break; - } - case Expression::Id::StructGetId: { - DELEGATE_START(StructGet); - DELEGATE_FIELD_INT(StructGet, index); - DELEGATE_FIELD_CHILD(StructGet, ref); - DELEGATE_FIELD_INT(StructGet, signed_); - DELEGATE_END(StructGet); - break; - } - case Expression::Id::StructSetId: { - DELEGATE_START(StructSet); - DELEGATE_FIELD_INT(StructSet, index); - DELEGATE_FIELD_CHILD(StructSet, value); - DELEGATE_FIELD_CHILD(StructSet, ref); - DELEGATE_END(StructSet); - break; - } - case Expression::Id::ArrayNewId: { - DELEGATE_START(ArrayNew); - DELEGATE_FIELD_OPTIONAL_CHILD(ArrayNew, rtt); - DELEGATE_FIELD_CHILD(ArrayNew, size); - DELEGATE_FIELD_OPTIONAL_CHILD(ArrayNew, init); - DELEGATE_END(ArrayNew); - break; - } - case Expression::Id::ArrayInitId: { - DELEGATE_START(ArrayInit); - DELEGATE_FIELD_OPTIONAL_CHILD(ArrayInit, rtt); - DELEGATE_FIELD_CHILD_VECTOR(ArrayInit, values); - DELEGATE_END(ArrayInit); - break; - } - case Expression::Id::ArrayGetId: { - DELEGATE_START(ArrayGet); - DELEGATE_FIELD_CHILD(ArrayGet, index); - DELEGATE_FIELD_CHILD(ArrayGet, ref); - DELEGATE_FIELD_INT(ArrayGet, signed_); - DELEGATE_END(ArrayGet); - break; - } - case Expression::Id::ArraySetId: { - DELEGATE_START(ArraySet); - DELEGATE_FIELD_CHILD(ArrayGet, value); - DELEGATE_FIELD_CHILD(ArrayGet, index); - DELEGATE_FIELD_CHILD(ArrayGet, ref); - DELEGATE_END(ArraySet); - break; - } - case Expression::Id::ArrayLenId: { - DELEGATE_START(ArrayLen); - DELEGATE_FIELD_CHILD(ArrayLen, ref); - DELEGATE_END(ArrayLen); - break; - } - case Expression::Id::ArrayCopyId: { - DELEGATE_START(ArrayCopy); - DELEGATE_FIELD_CHILD(ArrayCopy, length); - DELEGATE_FIELD_CHILD(ArrayCopy, srcIndex); - DELEGATE_FIELD_CHILD(ArrayCopy, srcRef); - DELEGATE_FIELD_CHILD(ArrayCopy, destIndex); - DELEGATE_FIELD_CHILD(ArrayCopy, destRef); - DELEGATE_END(ArrayCopy); - break; - } - case Expression::Id::RefAsId: { - DELEGATE_START(RefAs); - DELEGATE_FIELD_INT(RefAs, op); - DELEGATE_FIELD_CHILD(RefAs, value); - DELEGATE_END(RefAs); - break; - } -} - -#undef DELEGATE_ID -#undef DELEGATE_START -#undef DELEGATE_END -#undef DELEGATE_FIELD_CHILD -#undef DELEGATE_FIELD_OPTIONAL_CHILD -#undef DELEGATE_FIELD_CHILD_VECTOR -#undef DELEGATE_FIELD_INT -#undef DELEGATE_FIELD_INT_ARRAY -#undef DELEGATE_FIELD_LITERAL -#undef DELEGATE_FIELD_NAME -#undef DELEGATE_FIELD_NAME_VECTOR -#undef DELEGATE_FIELD_SCOPE_NAME_DEF -#undef DELEGATE_FIELD_SCOPE_NAME_USE -#undef DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR -#undef DELEGATE_FIELD_TYPE -#undef DELEGATE_FIELD_HEAPTYPE -#undef DELEGATE_FIELD_ADDRESS -#undef DELEGATE_GET_FIELD diff -Nru binaryen-108/src/wasm-delegations-fields.h binaryen-99/src/wasm-delegations-fields.h --- binaryen-108/src/wasm-delegations-fields.h 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/src/wasm-delegations-fields.h 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,674 @@ +/* + * Copyright 2020 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Implements a switch on an expression class ID, and has a case for each id +// in which it runs delegates on the fields and immediates. You should include +// this file after defining the relevant DELEGATE_* macros. +// +// All defines used here are undefed automatically at the end for you. +// +// Most of the defines are necessary, and you will get an error if you forget +// them, but some are optional and some imply others, see below. +// +// The defines are as follows: +// +// DELEGATE_START(id) - called at the start of a case for an expression class. +// +// DELEGATE_END(id) - called at the end of a case. +// +// DELEGATE_GET_FIELD(id, name) - called to get a field by its name. This must +// know the object on which to get it, so it is just useful for the case +// where you operate on a single such object, but in that case it is nice +// because then other things can be defined automatically for you, see later. +// +// DELEGATE_FIELD_CHILD(id, name) - called for each child field (note: children +// are visited in reverse order, which is convenient for walking by pushing +// them to a stack first). +// +// DELEGATE_FIELD_OPTIONAL_CHILD(id, name) - called for a child that may not be +// present (like a Return's value). If you do not define this then +// DELEGATE_FIELD_CHILD is called. +// +// DELEGATE_FIELD_CHILD_VECTOR(id, name) - called for a variable-sized vector of +// child pointers. If this is not defined, and DELEGATE_GET_FIELD is, then +// DELEGATE_FIELD_CHILD is called on them. +// +// DELEGATE_FIELD_INT(id, name) - called for an integer field (bool, enum, +// Index, int32, or int64). +// +// DELEGATE_FIELD_INT_ARRAY(id, name) - called for a std::array of fixed size of +// integer values (like a SIMD mask). If this is not defined, and +// DELEGATE_GET_FIELD is, then DELEGATE_FIELD_INT is called on them. +// +// DELEGATE_FIELD_LITERAL(id, name) - called for a Literal. +// +// DELEGATE_FIELD_NAME(id, name) - called for a Name. +// +// DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) - called for a scope name definition +// (like a block's name). +// +// DELEGATE_FIELD_SCOPE_NAME_USE(id, name) - called for a scope name use (like +// a break's target). +// +// DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) - called for a variable-sized +// vector of scope names (like a switch's targets). If this is not defined, +// and DELEGATE_GET_FIELD is, then DELEGATE_FIELD_SCOPE_NAME_USE is called on +// them. +// +// DELEGATE_FIELD_SIGNATURE(id, name) - called for a Signature. +// +// DELEGATE_FIELD_TYPE(id, name) - called for a Type. +// +// DELEGATE_FIELD_ADDRESS(id, name) - called for an Address. + +#ifndef DELEGATE_START +#define DELEGATE_START(id) +#endif + +#ifndef DELEGATE_END +#define DELEGATE_END(id) +#endif + +#ifndef DELEGATE_FIELD_CHILD +#error please define DELEGATE_FIELD_CHILD(id, name) +#endif + +#ifndef DELEGATE_FIELD_OPTIONAL_CHILD +#define DELEGATE_FIELD_OPTIONAL_CHILD(id, name) DELEGATE_FIELD_CHILD(id, name) +#endif + +#ifndef DELEGATE_FIELD_CHILD_VECTOR +#ifdef DELEGATE_GET_FIELD +#define DELEGATE_FIELD_CHILD_VECTOR(id, name) \ + for (int i = int((DELEGATE_GET_FIELD(id, name)).size()) - 1; i >= 0; i--) { \ + DELEGATE_FIELD_CHILD(id, name[i]); \ + } +#else +#error please define DELEGATE_FIELD_CHILD_VECTOR(id, name) +#endif +#endif + +#ifndef DELEGATE_FIELD_INT +#error please define DELEGATE_FIELD_INT(id, name) +#endif + +#ifndef DELEGATE_FIELD_INT_ARRAY +#ifdef DELEGATE_GET_FIELD +#define DELEGATE_FIELD_INT_ARRAY(id, name) \ + for (Index i = 0; i < (DELEGATE_GET_FIELD(id, name)).size(); i++) { \ + DELEGATE_FIELD_INT(id, name[i]); \ + } +#else +#error please define DELEGATE_FIELD_INT_ARRAY(id, name) +#endif +#endif + +#ifndef DELEGATE_FIELD_LITERAL +#error please define DELEGATE_FIELD_LITERAL(id, name) +#endif + +#ifndef DELEGATE_FIELD_NAME +#error please define DELEGATE_FIELD_NAME(id, name) +#endif + +#ifndef DELEGATE_FIELD_SCOPE_NAME_DEF +#error please define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) +#endif + +#ifndef DELEGATE_FIELD_SCOPE_NAME_USE +#error please define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) +#endif + +#ifndef DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR +#ifdef DELEGATE_GET_FIELD +#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) \ + for (Index i = 0; i < (DELEGATE_GET_FIELD(id, name)).size(); i++) { \ + DELEGATE_FIELD_SCOPE_NAME_USE(id, name[i]); \ + } +#else +#error please define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) +#endif +#endif + +#ifndef DELEGATE_FIELD_SIGNATURE +#error please define DELEGATE_FIELD_SIGNATURE(id, name) +#endif + +#ifndef DELEGATE_FIELD_TYPE +#error please define DELEGATE_FIELD_TYPE(id, name) +#endif + +#ifndef DELEGATE_FIELD_ADDRESS +#error please define DELEGATE_FIELD_ADDRESS(id, name) +#endif + +switch (DELEGATE_ID) { + case Expression::Id::InvalidId: + case Expression::Id::NumExpressionIds: { + WASM_UNREACHABLE("unexpected expression type"); + } + case Expression::Id::BlockId: { + DELEGATE_START(Block); + DELEGATE_FIELD_CHILD_VECTOR(Block, list); + DELEGATE_FIELD_SCOPE_NAME_DEF(Block, name); + DELEGATE_END(Block); + break; + } + case Expression::Id::IfId: { + DELEGATE_START(If); + DELEGATE_FIELD_OPTIONAL_CHILD(If, ifFalse); + DELEGATE_FIELD_CHILD(If, ifTrue); + DELEGATE_FIELD_CHILD(If, condition); + DELEGATE_END(If); + break; + } + case Expression::Id::LoopId: { + DELEGATE_START(Loop); + DELEGATE_FIELD_CHILD(Loop, body); + DELEGATE_FIELD_SCOPE_NAME_DEF(Loop, name); + DELEGATE_END(Loop); + break; + } + case Expression::Id::BreakId: { + DELEGATE_START(Break); + DELEGATE_FIELD_OPTIONAL_CHILD(Break, condition); + DELEGATE_FIELD_OPTIONAL_CHILD(Break, value); + DELEGATE_FIELD_SCOPE_NAME_USE(Break, name); + DELEGATE_END(Break); + break; + } + case Expression::Id::SwitchId: { + DELEGATE_START(Switch); + DELEGATE_FIELD_CHILD(Switch, condition); + DELEGATE_FIELD_OPTIONAL_CHILD(Switch, value); + DELEGATE_FIELD_SCOPE_NAME_USE(Switch, default_); + DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(Switch, targets); + DELEGATE_END(Switch); + break; + } + case Expression::Id::CallId: { + DELEGATE_START(Call); + DELEGATE_FIELD_CHILD_VECTOR(Call, operands); + DELEGATE_FIELD_NAME(Call, target); + DELEGATE_FIELD_INT(Call, isReturn); + DELEGATE_END(Call); + break; + } + case Expression::Id::CallIndirectId: { + DELEGATE_START(CallIndirect); + DELEGATE_FIELD_CHILD(CallIndirect, target); + DELEGATE_FIELD_CHILD_VECTOR(CallIndirect, operands); + DELEGATE_FIELD_SIGNATURE(CallIndirect, sig); + DELEGATE_FIELD_INT(CallIndirect, isReturn); + DELEGATE_END(CallIndirect); + break; + } + case Expression::Id::LocalGetId: { + DELEGATE_START(LocalGet); + DELEGATE_FIELD_INT(LocalGet, index); + DELEGATE_END(LocalGet); + break; + } + case Expression::Id::LocalSetId: { + DELEGATE_START(LocalSet); + DELEGATE_FIELD_CHILD(LocalSet, value); + DELEGATE_FIELD_INT(LocalSet, index); + DELEGATE_END(LocalSet); + break; + } + case Expression::Id::GlobalGetId: { + DELEGATE_START(GlobalGet); + DELEGATE_FIELD_INT(GlobalGet, name); + DELEGATE_END(GlobalGet); + break; + } + case Expression::Id::GlobalSetId: { + DELEGATE_START(GlobalSet); + DELEGATE_FIELD_CHILD(GlobalSet, value); + DELEGATE_FIELD_INT(GlobalSet, name); + DELEGATE_END(GlobalSet); + break; + } + case Expression::Id::LoadId: { + DELEGATE_START(Load); + DELEGATE_FIELD_CHILD(Load, ptr); + DELEGATE_FIELD_INT(Load, bytes); + DELEGATE_FIELD_INT(Load, signed_); + DELEGATE_FIELD_ADDRESS(Load, offset); + DELEGATE_FIELD_ADDRESS(Load, align); + DELEGATE_FIELD_INT(Load, isAtomic); + DELEGATE_END(Load); + break; + } + case Expression::Id::StoreId: { + DELEGATE_START(Store); + DELEGATE_FIELD_CHILD(Store, value); + DELEGATE_FIELD_CHILD(Store, ptr); + DELEGATE_FIELD_INT(Store, bytes); + DELEGATE_FIELD_ADDRESS(Store, offset); + DELEGATE_FIELD_ADDRESS(Store, align); + DELEGATE_FIELD_INT(Store, isAtomic); + DELEGATE_FIELD_TYPE(Store, valueType); + DELEGATE_END(Store); + break; + } + case Expression::Id::AtomicRMWId: { + DELEGATE_START(AtomicRMW); + DELEGATE_FIELD_CHILD(AtomicRMW, value); + DELEGATE_FIELD_CHILD(AtomicRMW, ptr); + DELEGATE_FIELD_INT(AtomicRMW, op); + DELEGATE_FIELD_INT(AtomicRMW, bytes); + DELEGATE_FIELD_ADDRESS(AtomicRMW, offset); + DELEGATE_END(AtomicRMW); + break; + } + case Expression::Id::AtomicCmpxchgId: { + DELEGATE_START(AtomicCmpxchg); + DELEGATE_FIELD_CHILD(AtomicCmpxchg, replacement); + DELEGATE_FIELD_CHILD(AtomicCmpxchg, expected); + DELEGATE_FIELD_CHILD(AtomicCmpxchg, ptr); + DELEGATE_FIELD_INT(AtomicCmpxchg, bytes); + DELEGATE_FIELD_ADDRESS(AtomicCmpxchg, offset); + DELEGATE_END(AtomicCmpxchgId); + break; + } + case Expression::Id::AtomicWaitId: { + DELEGATE_START(AtomicWait); + DELEGATE_FIELD_CHILD(AtomicWait, timeout); + DELEGATE_FIELD_CHILD(AtomicWait, expected); + DELEGATE_FIELD_CHILD(AtomicWait, ptr); + DELEGATE_FIELD_ADDRESS(AtomicWait, offset); + DELEGATE_FIELD_TYPE(AtomicWait, expectedType); + DELEGATE_END(AtomicWait); + break; + } + case Expression::Id::AtomicNotifyId: { + DELEGATE_START(AtomicNotify); + DELEGATE_FIELD_CHILD(AtomicNotify, notifyCount); + DELEGATE_FIELD_CHILD(AtomicNotify, ptr); + DELEGATE_FIELD_ADDRESS(AtomicNotify, offset); + DELEGATE_END(AtomicNotify); + break; + } + case Expression::Id::AtomicFenceId: { + DELEGATE_START(AtomicFence); + DELEGATE_FIELD_INT(AtomicFence, order); + DELEGATE_END(AtomicFence); + break; + } + case Expression::Id::SIMDExtractId: { + DELEGATE_START(SIMDExtract); + DELEGATE_FIELD_CHILD(SIMDExtract, vec); + DELEGATE_FIELD_INT(SIMDExtract, op); + DELEGATE_FIELD_INT(SIMDExtract, index); + DELEGATE_END(SIMDExtract); + break; + } + case Expression::Id::SIMDReplaceId: { + DELEGATE_START(SIMDReplace); + DELEGATE_FIELD_CHILD(SIMDReplace, value); + DELEGATE_FIELD_CHILD(SIMDReplace, vec); + DELEGATE_FIELD_INT(SIMDReplace, op); + DELEGATE_FIELD_INT(SIMDReplace, index); + DELEGATE_END(SIMDReplace); + break; + } + case Expression::Id::SIMDShuffleId: { + DELEGATE_START(SIMDShuffle); + DELEGATE_FIELD_CHILD(SIMDShuffle, right); + DELEGATE_FIELD_CHILD(SIMDShuffle, left); + DELEGATE_FIELD_INT_ARRAY(SIMDShuffle, mask); + DELEGATE_END(SIMDShuffle); + break; + } + case Expression::Id::SIMDTernaryId: { + DELEGATE_START(SIMDTernary); + DELEGATE_FIELD_CHILD(SIMDTernary, c); + DELEGATE_FIELD_CHILD(SIMDTernary, b); + DELEGATE_FIELD_CHILD(SIMDTernary, a); + DELEGATE_FIELD_INT(SIMDTernary, op); + DELEGATE_END(SIMDTernary); + break; + } + case Expression::Id::SIMDShiftId: { + DELEGATE_START(SIMDShift); + DELEGATE_FIELD_CHILD(SIMDShift, shift); + DELEGATE_FIELD_CHILD(SIMDShift, vec); + DELEGATE_FIELD_INT(SIMDShift, op); + DELEGATE_END(SIMDShift); + break; + } + case Expression::Id::SIMDLoadId: { + DELEGATE_START(SIMDLoad); + DELEGATE_FIELD_CHILD(SIMDLoad, ptr); + DELEGATE_FIELD_INT(SIMDLoad, op); + DELEGATE_FIELD_ADDRESS(SIMDLoad, offset); + DELEGATE_FIELD_ADDRESS(SIMDLoad, align); + DELEGATE_END(SIMDLoad); + break; + } + case Expression::Id::SIMDLoadStoreLaneId: { + DELEGATE_START(SIMDLoadStoreLane); + DELEGATE_FIELD_CHILD(SIMDLoadStoreLane, vec); + DELEGATE_FIELD_CHILD(SIMDLoadStoreLane, ptr); + DELEGATE_FIELD_INT(SIMDLoadStoreLane, op); + DELEGATE_FIELD_ADDRESS(SIMDLoadStoreLane, offset); + DELEGATE_FIELD_ADDRESS(SIMDLoadStoreLane, align); + DELEGATE_FIELD_INT(SIMDLoadStoreLane, index); + DELEGATE_END(SIMDLoadStoreLane); + break; + } + case Expression::Id::PrefetchId: { + DELEGATE_START(Prefetch); + DELEGATE_FIELD_CHILD(Prefetch, ptr); + DELEGATE_FIELD_INT(Prefetch, op); + DELEGATE_FIELD_ADDRESS(Prefetch, offset); + DELEGATE_FIELD_ADDRESS(Prefetch, align); + DELEGATE_END(Prefetch); + break; + } + case Expression::Id::MemoryInitId: { + DELEGATE_START(MemoryInit); + DELEGATE_FIELD_CHILD(MemoryInit, size); + DELEGATE_FIELD_CHILD(MemoryInit, offset); + DELEGATE_FIELD_CHILD(MemoryInit, dest); + DELEGATE_FIELD_INT(MemoryInit, segment); + DELEGATE_END(MemoryInit); + break; + } + case Expression::Id::DataDropId: { + DELEGATE_START(DataDrop); + DELEGATE_FIELD_INT(DataDrop, segment); + DELEGATE_END(DataDrop); + break; + } + case Expression::Id::MemoryCopyId: { + DELEGATE_START(MemoryCopy); + DELEGATE_FIELD_CHILD(MemoryCopy, size); + DELEGATE_FIELD_CHILD(MemoryCopy, source); + DELEGATE_FIELD_CHILD(MemoryCopy, dest); + DELEGATE_END(MemoryCopy); + break; + } + case Expression::Id::MemoryFillId: { + DELEGATE_START(MemoryFill); + DELEGATE_FIELD_CHILD(MemoryFill, size); + DELEGATE_FIELD_CHILD(MemoryFill, value); + DELEGATE_FIELD_CHILD(MemoryFill, dest); + DELEGATE_END(MemoryFill); + break; + } + case Expression::Id::ConstId: { + DELEGATE_START(Const); + DELEGATE_FIELD_LITERAL(Const, value); + DELEGATE_END(Const); + break; + } + case Expression::Id::UnaryId: { + DELEGATE_START(Unary); + DELEGATE_FIELD_CHILD(Unary, value); + DELEGATE_FIELD_INT(Unary, op); + DELEGATE_END(Unary); + break; + } + case Expression::Id::BinaryId: { + DELEGATE_START(Binary); + DELEGATE_FIELD_CHILD(Binary, right); + DELEGATE_FIELD_CHILD(Binary, left); + DELEGATE_FIELD_INT(Binary, op); + DELEGATE_END(Binary); + break; + } + case Expression::Id::SelectId: { + DELEGATE_START(Select); + DELEGATE_FIELD_CHILD(Select, condition); + DELEGATE_FIELD_CHILD(Select, ifFalse); + DELEGATE_FIELD_CHILD(Select, ifTrue); + DELEGATE_END(Select); + break; + } + case Expression::Id::DropId: { + DELEGATE_START(Drop); + DELEGATE_FIELD_CHILD(Drop, value); + DELEGATE_END(Drop); + break; + } + case Expression::Id::ReturnId: { + DELEGATE_START(Return); + DELEGATE_FIELD_OPTIONAL_CHILD(Return, value); + DELEGATE_END(Return); + break; + } + case Expression::Id::MemorySizeId: { + DELEGATE_START(MemorySize); + DELEGATE_END(MemorySize); + break; + } + case Expression::Id::MemoryGrowId: { + DELEGATE_START(MemoryGrow); + DELEGATE_FIELD_CHILD(MemoryGrow, delta); + DELEGATE_END(MemoryGrow); + break; + } + case Expression::Id::RefNullId: { + DELEGATE_START(RefNull); + DELEGATE_FIELD_TYPE(RefNull, type); + DELEGATE_END(RefNull); + break; + } + case Expression::Id::RefIsNullId: { + DELEGATE_START(RefIsNull); + DELEGATE_FIELD_CHILD(RefIsNull, value); + DELEGATE_END(RefIsNull); + break; + } + case Expression::Id::RefFuncId: { + DELEGATE_START(RefFunc); + DELEGATE_FIELD_NAME(RefFunc, func); + DELEGATE_END(RefFunc); + break; + } + case Expression::Id::RefEqId: { + DELEGATE_START(RefEq); + DELEGATE_FIELD_CHILD(RefEq, right); + DELEGATE_FIELD_CHILD(RefEq, left); + DELEGATE_END(RefEq); + break; + } + case Expression::Id::TryId: { + DELEGATE_START(Try); + DELEGATE_FIELD_CHILD(Try, catchBody); + DELEGATE_FIELD_CHILD(Try, body); + DELEGATE_END(Try); + break; + } + case Expression::Id::ThrowId: { + DELEGATE_START(Throw); + DELEGATE_FIELD_CHILD_VECTOR(Throw, operands); + DELEGATE_FIELD_NAME(Throw, event); + DELEGATE_END(Throw); + break; + } + case Expression::Id::RethrowId: { + DELEGATE_START(Rethrow); + DELEGATE_FIELD_CHILD(Rethrow, exnref); + DELEGATE_END(Rethrow); + break; + } + case Expression::Id::BrOnExnId: { + DELEGATE_START(BrOnExn); + DELEGATE_FIELD_CHILD(BrOnExn, exnref); + DELEGATE_FIELD_SCOPE_NAME_USE(BrOnExn, name); + DELEGATE_FIELD_NAME(BrOnExn, event); + DELEGATE_FIELD_TYPE(BrOnExn, sent); + DELEGATE_END(BrOnExn); + break; + } + case Expression::Id::NopId: { + DELEGATE_START(Nop); + DELEGATE_END(Nop); + break; + } + case Expression::Id::UnreachableId: { + DELEGATE_START(Unreachable); + DELEGATE_END(Unreachable); + break; + } + case Expression::Id::PopId: { + DELEGATE_START(Pop); + DELEGATE_END(Pop); + break; + } + case Expression::Id::TupleMakeId: { + DELEGATE_START(TupleMake); + DELEGATE_FIELD_CHILD_VECTOR(Tuple, operands); + DELEGATE_END(TupleMake); + break; + } + case Expression::Id::TupleExtractId: { + DELEGATE_START(TupleExtract); + DELEGATE_FIELD_CHILD(TupleExtract, tuple); + DELEGATE_FIELD_INT(TupleExtract, index); + DELEGATE_END(TupleExtract); + break; + } + case Expression::Id::I31NewId: { + DELEGATE_START(I31New); + DELEGATE_FIELD_CHILD(I31New, value); + DELEGATE_END(I31New); + break; + } + case Expression::Id::I31GetId: { + DELEGATE_START(I31Get); + DELEGATE_FIELD_CHILD(I31Get, i31); + DELEGATE_FIELD_INT(I31Get, signed_); + DELEGATE_END(I31Get); + break; + } + case Expression::Id::CallRefId: { + DELEGATE_START(CallRef); + DELEGATE_FIELD_CHILD(CallRef, target); + DELEGATE_FIELD_CHILD_VECTOR(CallRef, operands); + DELEGATE_FIELD_INT(CallRef, isReturn); + DELEGATE_END(CallRef); + break; + } + case Expression::Id::RefTestId: { + DELEGATE_START(RefTest); + DELEGATE_FIELD_CHILD(RefTest, ref); + DELEGATE_FIELD_CHILD(RefTest, rtt); + DELEGATE_END(RefTest); + break; + } + case Expression::Id::RefCastId: { + DELEGATE_START(RefCast); + DELEGATE_FIELD_CHILD(RefCast, ref); + DELEGATE_FIELD_CHILD(RefCast, rtt); + DELEGATE_END(RefCast); + break; + } + case Expression::Id::BrOnCastId: { + DELEGATE_START(BrOnCast); + DELEGATE_FIELD_SCOPE_NAME_USE(BrOnCast, name); + DELEGATE_FIELD_TYPE(BrOnCast, castType); + DELEGATE_FIELD_CHILD(BrOnCast, ref); + DELEGATE_FIELD_CHILD(BrOnCast, rtt); + DELEGATE_END(BrOnCast); + break; + } + case Expression::Id::RttCanonId: { + DELEGATE_START(RttCanon); + DELEGATE_END(RttCanon); + break; + } + case Expression::Id::RttSubId: { + DELEGATE_START(RttSub); + DELEGATE_FIELD_CHILD(RttSub, parent); + DELEGATE_END(RttSub); + break; + } + case Expression::Id::StructNewId: { + DELEGATE_START(StructNew); + DELEGATE_FIELD_CHILD(StructNew, rtt); + DELEGATE_FIELD_CHILD_VECTOR(StructNew, operands); + DELEGATE_END(StructNew); + break; + } + case Expression::Id::StructGetId: { + DELEGATE_START(StructGet); + DELEGATE_FIELD_INT(StructGet, index); + DELEGATE_FIELD_CHILD(StructGet, ref); + DELEGATE_FIELD_INT(StructGet, signed_); + DELEGATE_END(StructGet); + break; + } + case Expression::Id::StructSetId: { + DELEGATE_START(StructSet); + DELEGATE_FIELD_INT(StructSet, index); + DELEGATE_FIELD_CHILD(StructSet, ref); + DELEGATE_FIELD_CHILD(StructSet, value); + DELEGATE_END(StructSet); + break; + } + case Expression::Id::ArrayNewId: { + DELEGATE_START(ArrayNew); + DELEGATE_FIELD_CHILD(ArrayNew, rtt); + DELEGATE_FIELD_CHILD(ArrayNew, size); + DELEGATE_FIELD_OPTIONAL_CHILD(ArrayNew, init); + DELEGATE_END(ArrayNew); + break; + } + case Expression::Id::ArrayGetId: { + DELEGATE_START(ArrayGet); + DELEGATE_FIELD_CHILD(ArrayGet, ref); + DELEGATE_FIELD_CHILD(ArrayGet, index); + DELEGATE_FIELD_INT(ArrayGet, signed_); + DELEGATE_END(ArrayGet); + break; + } + case Expression::Id::ArraySetId: { + DELEGATE_START(ArraySet); + DELEGATE_FIELD_CHILD(ArrayGet, ref); + DELEGATE_FIELD_CHILD(ArrayGet, index); + DELEGATE_FIELD_CHILD(ArrayGet, value); + DELEGATE_END(ArraySet); + break; + } + case Expression::Id::ArrayLenId: { + DELEGATE_START(ArrayLen); + DELEGATE_FIELD_CHILD(ArrayLen, ref); + DELEGATE_END(ArrayLen); + break; + } +} + +#undef DELEGATE_ID +#undef DELEGATE_START +#undef DELEGATE_END +#undef DELEGATE_FIELD_CHILD +#undef DELEGATE_FIELD_OPTIONAL_CHILD +#undef DELEGATE_FIELD_CHILD_VECTOR +#undef DELEGATE_FIELD_INT +#undef DELEGATE_FIELD_INT_ARRAY +#undef DELEGATE_FIELD_LITERAL +#undef DELEGATE_FIELD_NAME +#undef DELEGATE_FIELD_SCOPE_NAME_DEF +#undef DELEGATE_FIELD_SCOPE_NAME_USE +#undef DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR +#undef DELEGATE_FIELD_SIGNATURE +#undef DELEGATE_FIELD_TYPE +#undef DELEGATE_FIELD_ADDRESS +#undef DELEGATE_GET_FIELD diff -Nru binaryen-108/src/wasm-delegations.h binaryen-99/src/wasm-delegations.h --- binaryen-108/src/wasm-delegations.h 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/src/wasm-delegations.h 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright 2020 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +DELEGATE(Nop); +DELEGATE(Block); +DELEGATE(If); +DELEGATE(Loop); +DELEGATE(Break); +DELEGATE(Switch); +DELEGATE(Call); +DELEGATE(CallIndirect); +DELEGATE(LocalGet); +DELEGATE(LocalSet); +DELEGATE(GlobalGet); +DELEGATE(GlobalSet); +DELEGATE(Load); +DELEGATE(Store); +DELEGATE(AtomicRMW); +DELEGATE(AtomicCmpxchg); +DELEGATE(AtomicWait); +DELEGATE(AtomicNotify); +DELEGATE(AtomicFence); +DELEGATE(SIMDExtract); +DELEGATE(SIMDReplace); +DELEGATE(SIMDShuffle); +DELEGATE(SIMDTernary); +DELEGATE(SIMDShift); +DELEGATE(SIMDLoad); +DELEGATE(SIMDLoadStoreLane); +DELEGATE(Prefetch); +DELEGATE(MemoryInit); +DELEGATE(DataDrop); +DELEGATE(MemoryCopy); +DELEGATE(MemoryFill); +DELEGATE(Const); +DELEGATE(Unary); +DELEGATE(Binary); +DELEGATE(Select); +DELEGATE(Drop); +DELEGATE(Return); +DELEGATE(MemorySize); +DELEGATE(MemoryGrow); +DELEGATE(Unreachable); +DELEGATE(Pop); +DELEGATE(RefNull); +DELEGATE(RefIsNull); +DELEGATE(RefFunc); +DELEGATE(RefEq); +DELEGATE(Try); +DELEGATE(Throw); +DELEGATE(Rethrow); +DELEGATE(BrOnExn); +DELEGATE(TupleMake); +DELEGATE(TupleExtract); +DELEGATE(I31New); +DELEGATE(I31Get); +DELEGATE(CallRef); +DELEGATE(RefTest); +DELEGATE(RefCast); +DELEGATE(BrOnCast); +DELEGATE(RttCanon); +DELEGATE(RttSub); +DELEGATE(StructNew); +DELEGATE(StructGet); +DELEGATE(StructSet); +DELEGATE(ArrayNew); +DELEGATE(ArrayGet); +DELEGATE(ArraySet); +DELEGATE(ArrayLen); + +#undef DELEGATE diff -Nru binaryen-108/src/wasm-emscripten.h binaryen-99/src/wasm-emscripten.h --- binaryen-108/src/wasm-emscripten.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-emscripten.h 2021-01-07 20:01:06.000000000 +0000 @@ -33,7 +33,7 @@ : wasm(wasm), builder(wasm), stackPointerOffset(stackPointerOffset), useStackPointerGlobal(stackPointerOffset == 0) {} - std::string generateEmscriptenMetadata(); + std::string generateEmscriptenMetadata(Name initializer); void fixInvokeFunctionNames(); diff -Nru binaryen-108/src/wasm-features.h binaryen-99/src/wasm-features.h --- binaryen-108/src/wasm-features.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-features.h 2021-01-07 20:01:06.000000000 +0000 @@ -39,15 +39,7 @@ GC = 1 << 10, Memory64 = 1 << 11, TypedFunctionReferences = 1 << 12, - // TODO: Remove this feature when the wasm spec stabilizes. - GCNNLocals = 1 << 13, - RelaxedSIMD = 1 << 14, - ExtendedConst = 1 << 15, - // GCNNLocals are opt-in: merely asking for "All" does not apply them. To - // get all possible values use AllPossible. See setAll() below for more - // details. - All = ((1 << 16) - 1) & ~GCNNLocals, - AllPossible = (1 << 16) - 1, + All = (1 << 13) - 1 }; static std::string toString(Feature f) { @@ -78,38 +70,17 @@ return "memory64"; case TypedFunctionReferences: return "typed-function-references"; - case GCNNLocals: - return "gc-nn-locals"; - case RelaxedSIMD: - return "relaxed-simd"; - case ExtendedConst: - return "extended-const"; default: WASM_UNREACHABLE("unexpected feature"); } } - std::string toString() const { - std::string ret; - uint32_t x = 1; - while (x & Feature::AllPossible) { - if (features & x) { - if (!ret.empty()) { - ret += ", "; - } - ret += toString(Feature(x)); - } - x <<= 1; - } - return ret; - } - FeatureSet() : features(MVP) {} FeatureSet(uint32_t features) : features(features) {} operator uint32_t() const { return features; } bool isMVP() const { return features == MVP; } - bool has(FeatureSet f) const { return (features & f) == f.features; } + bool has(FeatureSet f) { return (features & f) == f; } bool hasAtomics() const { return (features & Atomics) != 0; } bool hasMutableGlobals() const { return (features & MutableGlobals) != 0; } bool hasTruncSat() const { return (features & TruncSat) != 0; } @@ -127,11 +98,9 @@ bool hasTypedFunctionReferences() const { return (features & TypedFunctionReferences) != 0; } - bool hasGCNNLocals() const { return (features & GCNNLocals) != 0; } - bool hasRelaxedSIMD() const { return (features & RelaxedSIMD) != 0; } - bool hasExtendedConst() const { return (features & ExtendedConst) != 0; } - bool hasAll() const { return (features & AllPossible) != 0; } + bool hasAll() const { return (features & All) != 0; } + void makeMVP() { features = MVP; } void set(FeatureSet f, bool v = true) { features = v ? (features | f) : (features & ~f); } @@ -150,32 +119,15 @@ void setTypedFunctionReferences(bool v = true) { set(TypedFunctionReferences, v); } - void setGCNNLocals(bool v = true) { set(GCNNLocals, v); } - void setRelaxedSIMD(bool v = true) { set(RelaxedSIMD, v); } - void setExtendedConst(bool v = true) { set(ExtendedConst, v); } - void setMVP() { features = MVP; } - void setAll() { - // Do not set GCNNLocals, which forces the user to opt in to that feature - // explicitly. That is, wasm-opt -all will enable GC but *not* enable - // non-nullable locals. To get them, do wasm-opt -all --enable-gc-nn-locals - // FIXME: When the wasm spec stabilizes, this feature will go away, as the - // non-nullable locals experiment will either become the standard, - // or it will go away. - // Leave the old GCNNLocals value unmodified. This makes things like - // --enable-gc-nn-locals -all work (that is, if we enable the feature, - // then -all does not disable it; it simply does not enable it by itself). - auto oldGCNNLocals = hasGCNNLocals(); - features = AllPossible; - setGCNNLocals(oldGCNNLocals); - } + void setAll(bool v = true) { features = v ? All : MVP; } void enable(const FeatureSet& other) { features |= other.features; } void disable(const FeatureSet& other) { - features = features & ~other.features & AllPossible; + features = features & ~other.features & All; } - template void iterFeatures(F f) const { - for (uint32_t feature = MVP + 1; feature < AllPossible; feature <<= 1) { + template void iterFeatures(F f) { + for (uint32_t feature = MVP + 1; feature < All; feature <<= 1) { if (has(feature)) { f(static_cast(feature)); } diff -Nru binaryen-108/src/wasm.h binaryen-99/src/wasm.h --- binaryen-108/src/wasm.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm.h 2021-01-07 20:01:06.000000000 +0000 @@ -34,7 +34,6 @@ #include "literal.h" #include "mixed_arena.h" -#include "support/index.h" #include "support/name.h" #include "wasm-features.h" #include "wasm-type.h" @@ -49,14 +48,14 @@ typedef uint32_t address32_t; typedef uint64_t address64_t; address64_t addr; - constexpr Address() : addr(0) {} - constexpr Address(uint64_t a) : addr(a) {} + Address() : addr(0) {} + Address(uint64_t a) : addr(a) {} Address& operator=(uint64_t a) { addr = a; return *this; } operator address64_t() const { return addr; } - Address& operator++(int) { + Address& operator++() { ++addr; return *this; } @@ -158,23 +157,23 @@ // SIMD arithmetic NotVec128, - AnyTrueVec128, AbsVecI8x16, NegVecI8x16, + AnyTrueVecI8x16, AllTrueVecI8x16, BitmaskVecI8x16, PopcntVecI8x16, AbsVecI16x8, NegVecI16x8, + AnyTrueVecI16x8, AllTrueVecI16x8, BitmaskVecI16x8, AbsVecI32x4, NegVecI32x4, + AnyTrueVecI32x4, AllTrueVecI32x4, BitmaskVecI32x4, - AbsVecI64x2, NegVecI64x2, - AllTrueVecI64x2, BitmaskVecI64x2, AbsVecF32x4, NegVecF32x4, @@ -198,33 +197,24 @@ // SIMD conversions TruncSatSVecF32x4ToVecI32x4, TruncSatUVecF32x4ToVecI32x4, + TruncSatSVecF64x2ToVecI64x2, + TruncSatUVecF64x2ToVecI64x2, ConvertSVecI32x4ToVecF32x4, ConvertUVecI32x4ToVecF32x4, - ExtendLowSVecI8x16ToVecI16x8, - ExtendHighSVecI8x16ToVecI16x8, - ExtendLowUVecI8x16ToVecI16x8, - ExtendHighUVecI8x16ToVecI16x8, - ExtendLowSVecI16x8ToVecI32x4, - ExtendHighSVecI16x8ToVecI32x4, - ExtendLowUVecI16x8ToVecI32x4, - ExtendHighUVecI16x8ToVecI32x4, - ExtendLowSVecI32x4ToVecI64x2, - ExtendHighSVecI32x4ToVecI64x2, - ExtendLowUVecI32x4ToVecI64x2, - ExtendHighUVecI32x4ToVecI64x2, - - ConvertLowSVecI32x4ToVecF64x2, - ConvertLowUVecI32x4ToVecF64x2, - TruncSatZeroSVecF64x2ToVecI32x4, - TruncSatZeroUVecF64x2ToVecI32x4, - DemoteZeroVecF64x2ToVecF32x4, - PromoteLowVecF32x4ToVecF64x2, - - // Relaxed SIMD - RelaxedTruncSVecF32x4ToVecI32x4, - RelaxedTruncUVecF32x4ToVecI32x4, - RelaxedTruncZeroSVecF64x2ToVecI32x4, - RelaxedTruncZeroUVecF64x2ToVecI32x4, + ConvertSVecI64x2ToVecF64x2, + ConvertUVecI64x2ToVecF64x2, + WidenLowSVecI8x16ToVecI16x8, + WidenHighSVecI8x16ToVecI16x8, + WidenLowUVecI8x16ToVecI16x8, + WidenHighUVecI8x16ToVecI16x8, + WidenLowSVecI16x8ToVecI32x4, + WidenHighSVecI16x8ToVecI32x4, + WidenLowUVecI16x8ToVecI32x4, + WidenHighUVecI16x8ToVecI32x4, + WidenLowSVecI32x4ToVecI64x2, + WidenHighSVecI32x4ToVecI64x2, + WidenLowUVecI32x4ToVecI64x2, + WidenHighUVecI32x4ToVecI64x2, InvalidUnary }; @@ -370,11 +360,6 @@ GeSVecI32x4, GeUVecI32x4, EqVecI64x2, - NeVecI64x2, - LtSVecI64x2, - GtSVecI64x2, - LeSVecI64x2, - GeSVecI64x2, EqVecF32x4, NeVecF32x4, LtVecF32x4, @@ -399,6 +384,7 @@ SubVecI8x16, SubSatSVecI8x16, SubSatUVecI8x16, + MulVecI8x16, MinSVecI8x16, MinUVecI8x16, MaxSVecI8x16, @@ -464,17 +450,7 @@ NarrowUVecI32x4ToVecI16x8, // SIMD Swizzle - SwizzleVecI8x16, - - // Relaxed SIMD - RelaxedSwizzleVecI8x16, - RelaxedMinVecF32x4, - RelaxedMaxVecF32x4, - RelaxedMinVecF64x2, - RelaxedMaxVecF64x2, - RelaxedQ15MulrSVecI16x8, - DotI8x16I7x16SToVecI16x8, - DotI8x16I7x16UToVecI16x8, + SwizzleVec8x16, InvalidBinary }; @@ -498,7 +474,7 @@ ReplaceLaneVecI32x4, ReplaceLaneVecI64x2, ReplaceLaneVecF32x4, - ReplaceLaneVecF64x2, + ReplaceLaneVecF64x2 }; enum SIMDShiftOp { @@ -517,81 +493,56 @@ }; enum SIMDLoadOp { - Load8SplatVec128, - Load16SplatVec128, - Load32SplatVec128, - Load64SplatVec128, - Load8x8SVec128, - Load8x8UVec128, - Load16x4SVec128, - Load16x4UVec128, - Load32x2SVec128, - Load32x2UVec128, - Load32ZeroVec128, - Load64ZeroVec128, + LoadSplatVec8x16, + LoadSplatVec16x8, + LoadSplatVec32x4, + LoadSplatVec64x2, + LoadExtSVec8x8ToVecI16x8, + LoadExtUVec8x8ToVecI16x8, + LoadExtSVec16x4ToVecI32x4, + LoadExtUVec16x4ToVecI32x4, + LoadExtSVec32x2ToVecI64x2, + LoadExtUVec32x2ToVecI64x2, + Load32Zero, + Load64Zero, }; enum SIMDLoadStoreLaneOp { - Load8LaneVec128, - Load16LaneVec128, - Load32LaneVec128, - Load64LaneVec128, - Store8LaneVec128, - Store16LaneVec128, - Store32LaneVec128, - Store64LaneVec128, + LoadLaneVec8x16, + LoadLaneVec16x8, + LoadLaneVec32x4, + LoadLaneVec64x2, + StoreLaneVec8x16, + StoreLaneVec16x8, + StoreLaneVec32x4, + StoreLaneVec64x2, }; enum SIMDTernaryOp { Bitselect, + QFMAF32x4, + QFMSF32x4, + QFMAF64x2, + QFMSF64x2, + SignSelectVec8x16, + SignSelectVec16x8, + SignSelectVec32x4, + SignSelectVec64x2 +}; - // Relaxed SIMD - RelaxedFmaVecF32x4, - RelaxedFmsVecF32x4, - RelaxedFmaVecF64x2, - RelaxedFmsVecF64x2, - LaneselectI8x16, - LaneselectI16x8, - LaneselectI32x4, - LaneselectI64x2, - DotI8x16I7x16AddSToVecI32x4, - DotI8x16I7x16AddUToVecI32x4, -}; - -enum RefIsOp { - RefIsNull, - RefIsFunc, - RefIsData, - RefIsI31, -}; - -enum RefAsOp { - RefAsNonNull, - RefAsFunc, - RefAsData, - RefAsI31, -}; - -enum BrOnOp { - BrOnNull, - BrOnNonNull, - BrOnCast, - BrOnCastFail, - BrOnFunc, - BrOnNonFunc, - BrOnData, - BrOnNonData, - BrOnI31, - BrOnNonI31, +enum PrefetchOp { + PrefetchTemporal, + PrefetchNontemporal, }; // // Expressions // // Note that little is provided in terms of constructors for these. The -// rationale is that writing `new Something(a, b, c, d, e)` is not the clearest, -// and it would be better to write new `Something(name=a, leftOperand=b...` -// etc., but C++ lacks named operands so you will see things like +// rationale is that writing new Something(a, b, c, d, e) is not the clearest, +// and it would be better to write new Something(name=a, leftOperand=b... +// etc., but C++ lacks named operands, so in asm2wasm etc. you will see things +// like // auto x = new Something(); // x->name = a; // x->leftOperand = b; @@ -631,6 +582,7 @@ MemorySizeId, MemoryGrowId, NopId, + PrefetchId, UnreachableId, AtomicRMWId, AtomicCmpxchgId, @@ -650,16 +602,13 @@ MemoryFillId, PopId, RefNullId, - RefIsId, + RefIsNullId, RefFuncId, RefEqId, - TableGetId, - TableSetId, - TableSizeId, - TableGrowId, TryId, ThrowId, RethrowId, + BrOnExnId, TupleMakeId, TupleExtractId, I31NewId, @@ -667,19 +616,16 @@ CallRefId, RefTestId, RefCastId, - BrOnId, + BrOnCastId, RttCanonId, RttSubId, StructNewId, StructGetId, StructSetId, ArrayNewId, - ArrayInitId, ArrayGetId, ArraySetId, ArrayLenId, - ArrayCopyId, - RefAsId, NumExpressionIds }; Id _id; @@ -832,8 +778,8 @@ ArenaVector targets; Name default_; - Expression* value = nullptr; Expression* condition = nullptr; + Expression* value = nullptr; void finalize(); }; @@ -852,10 +798,9 @@ class CallIndirect : public SpecificExpression { public: CallIndirect(MixedArena& allocator) : operands(allocator) {} - HeapType heapType; + Signature sig; ExpressionList operands; Expression* target; - Name table; bool isReturn = false; void finalize(); @@ -909,7 +854,7 @@ Load(MixedArena& allocator) {} uint8_t bytes; - bool signed_ = false; + bool signed_; Address offset; Address align; bool isAtomic; @@ -1098,6 +1043,18 @@ void finalize(); }; +class Prefetch : public SpecificExpression { +public: + Prefetch() = default; + Prefetch(MixedArena& allocator) : Prefetch() {} + + PrefetchOp op; + Address offset; + Address align; + Expression* ptr; + void finalize(); +}; + class MemoryInit : public SpecificExpression { public: MemoryInit() = default; @@ -1265,12 +1222,9 @@ void finalize(Type type); }; -class RefIs : public SpecificExpression { +class RefIsNull : public SpecificExpression { public: - RefIs(MixedArena& allocator) {} - - // RefIs can represent ref.is_null, ref.is_func, ref.is_data, and ref.is_i31. - RefIsOp op; + RefIsNull(MixedArena& allocator) {} Expression* value; @@ -1297,66 +1251,13 @@ void finalize(); }; -class TableGet : public SpecificExpression { -public: - TableGet(MixedArena& allocator) {} - - Name table; - - Expression* index; - - void finalize(); -}; - -class TableSet : public SpecificExpression { -public: - TableSet(MixedArena& allocator) {} - - Name table; - - Expression* index; - Expression* value; - - void finalize(); -}; - -class TableSize : public SpecificExpression { -public: - TableSize() { type = Type::i32; } - TableSize(MixedArena& allocator) : TableSize() {} - - Name table; - - void finalize(); -}; - -class TableGrow : public SpecificExpression { -public: - TableGrow() { type = Type::i32; } - TableGrow(MixedArena& allocator) : TableGrow() {} - - Name table; - Expression* value; - Expression* delta; - - void finalize(); -}; - class Try : public SpecificExpression { public: - Try(MixedArena& allocator) : catchTags(allocator), catchBodies(allocator) {} + Try(MixedArena& allocator) {} - Name name; // label that can only be targeted by 'delegate's Expression* body; - ArenaVector catchTags; - ExpressionList catchBodies; - Name delegateTarget; // target try's label + Expression* catchBody; - bool hasCatchAll() const { - return catchBodies.size() - catchTags.size() == 1; - } - bool isCatch() const { return !catchBodies.empty(); } - bool isDelegate() const { return delegateTarget.is(); } void finalize(); void finalize(Type type_); }; @@ -1365,7 +1266,7 @@ public: Throw(MixedArena& allocator) : operands(allocator) {} - Name tag; + Name event; ExpressionList operands; void finalize(); @@ -1375,7 +1276,22 @@ public: Rethrow(MixedArena& allocator) {} - Name target; + Expression* exnref; + + void finalize(); +}; + +class BrOnExn : public SpecificExpression { +public: + BrOnExn() { type = Type::unreachable; } + BrOnExn(MixedArena& allocator) : BrOnExn() {} + + Name name; + Name event; + Expression* exnref; + // This is duplicate info of param types stored in Event, but this is required + // for us to know the type of the value sent to the target block. + Type sent; void finalize(); }; @@ -1413,7 +1329,7 @@ I31Get(MixedArena& allocator) {} Expression* i31; - bool signed_ = false; + bool signed_; void finalize(); }; @@ -1434,17 +1350,11 @@ RefTest(MixedArena& allocator) {} Expression* ref; - - // If rtt is provided then this is a dynamic test with an rtt. If nullptr then - // this is a static cast and intendedType is set, and it contains the type we - // intend to cast to. - Expression* rtt = nullptr; - HeapType intendedType; + Expression* rtt; void finalize(); - // Returns the type we intend to cast to. - HeapType getIntendedType(); + Type getCastType(); }; class RefCast : public SpecificExpression { @@ -1452,48 +1362,27 @@ RefCast(MixedArena& allocator) {} Expression* ref; - - // See above with RefTest. - Expression* rtt = nullptr; - HeapType intendedType; - - // Support the unsafe `ref.cast_nop_static` to enable precise cast overhead - // measurements. - enum Safety { Safe, Unsafe }; - Safety safety; + Expression* rtt; void finalize(); - // Returns the type we intend to cast to. - HeapType getIntendedType(); + Type getCastType(); }; -class BrOn : public SpecificExpression { +class BrOnCast : public SpecificExpression { public: - BrOn(MixedArena& allocator) {} + BrOnCast(MixedArena& allocator) {} - BrOnOp op; Name name; + // The cast type cannot be inferred from rtt if rtt is unreachable, so we must + // store it explicitly. + Type castType; Expression* ref; - - // BrOnCast* has, like RefCast and RefTest, either an rtt or a static intended - // type. - Expression* rtt = nullptr; - HeapType intendedType; - - // TODO: BrOnNull also has an optional extra value in the spec, which we do - // not support. See also the discussion on - // https://github.com/WebAssembly/function-references/issues/45 - // - depending on the decision there, we may want to move BrOnNull into - // Break or a new class of its own. + Expression* rtt; void finalize(); - // Returns the type we intend to cast to. Relevant only for the cast variants. - HeapType getIntendedType(); - - // Returns the type sent on the branch, if it is taken. - Type getSentType(); + Type getCastType(); }; class RttCanon : public SpecificExpression { @@ -1509,11 +1398,6 @@ Expression* parent; - // rtt.fresh_sub is like rtt.sub, but never caching or canonicalizing (i.e., - // it always returns a fresh RTT, non-identical to any other RTT in the - // system). - bool fresh = false; - void finalize(); }; @@ -1521,10 +1405,7 @@ public: StructNew(MixedArena& allocator) : operands(allocator) {} - // A dynamic StructNew has an rtt, while a static one declares the type using - // the type field. - Expression* rtt = nullptr; - + Expression* rtt; // A struct.new_with_default has empty operands. This does leave the case of a // struct with no fields ambiguous, but it doesn't make a difference in that // case, and binaryen doesn't guarantee roundtripping binaries anyhow. @@ -1562,34 +1443,18 @@ public: ArrayNew(MixedArena& allocator) {} + Expression* rtt; + Expression* size; // If set, then the initial value is assigned to all entries in the array. If // not set, this is array.new_with_default and the default of the type is // used. Expression* init = nullptr; - Expression* size; - - // A dynamic ArrayNew has an rtt, while a static one declares the type using - // the type field. - Expression* rtt = nullptr; bool isWithDefault() { return !init; } void finalize(); }; -class ArrayInit : public SpecificExpression { -public: - ArrayInit(MixedArena& allocator) : values(allocator) {} - - ExpressionList values; - - // A dynamic ArrayInit has an rtt, while a static one declares the type using - // the type field. - Expression* rtt = nullptr; - - void finalize(); -}; - class ArrayGet : public SpecificExpression { public: ArrayGet(MixedArena& allocator) {} @@ -1622,33 +1487,9 @@ void finalize(); }; -class ArrayCopy : public SpecificExpression { -public: - ArrayCopy(MixedArena& allocator) {} - - Expression* destRef; - Expression* destIndex; - Expression* srcRef; - Expression* srcIndex; - Expression* length; - - void finalize(); -}; - -class RefAs : public SpecificExpression { -public: - RefAs(MixedArena& allocator) {} - - RefAsOp op; - - Expression* value; - - void finalize(); -}; - // Globals -struct Named { +struct Importable { Name name; // Explicit names are ones that we read from the input file and @@ -1657,6 +1498,11 @@ // use only and will not be written the name section. bool hasExplicitName = false; + // If these are set, then this is an import, as module.base + Name module, base; + + bool imported() const { return module.is(); } + void setName(Name name_, bool hasExplicitName_) { name = name_; hasExplicitName = hasExplicitName_; @@ -1665,13 +1511,6 @@ void setExplicitName(Name name_) { setName(name_, true); } }; -struct Importable : Named { - // If these are set, then this is an import, as module.base - Name module, base; - - bool imported() const { return module.is(); } -}; - class Function; // Represents an offset into a wasm binary file. This is used for debug info. @@ -1696,15 +1535,20 @@ // Track the extra delimiter positions that some instructions, in particular // control flow, have, like 'end' for loop and block. We keep these in a // separate map because they are rare and we optimize for the storage space - // for the common type of instruction which just needs a Span. - // For "else" (from an if) we use index 0, and for catch (from a try) we use - // indexes 0 and above. - // We use automatic zero-initialization here because that indicates a "null" - // debug value, indicating the information is not present. - using DelimiterLocations = ZeroInitSmallVector; - - enum DelimiterId : size_t { Else = 0, Invalid = size_t(-1) }; + // for the common type of instruction which just needs a Span. We implement + // this as a simple array with one element at the moment (more elements may + // be necessary in the future). + // TODO: If we are sure we won't need more, make this a single value? + struct DelimiterLocations : public std::array { + DelimiterLocations() { + // Ensure zero-initialization. + for (auto& item : *this) { + item = 0; + } + } + }; + enum DelimiterId { Else = 0, Catch = 0, Invalid = -1 }; std::unordered_map delimiters; // DWARF debug info can refer to multiple interesting positions in a function. @@ -1730,7 +1574,7 @@ class Function : public Importable { public: - HeapType type = HeapType(Signature()); // parameters and return value + Signature sig; // parameters and return value IRProfile profile = IRProfile::Normal; std::vector vars; // non-param locals @@ -1748,8 +1592,8 @@ std::unique_ptr stackIR; // local names. these are optional. - std::unordered_map localNames; - std::unordered_map localIndices; + std::map localNames; + std::map localIndices; // Source maps debugging info: map expression nodes to their file, line, col. struct DebugLocation { @@ -1779,12 +1623,6 @@ delimiterLocations; BinaryLocations::FunctionLocations funcLocation; - Signature getSig() { return type.getSignature(); } - Type getParams() { return getSig().params; } - Type getResults() { return getSig().results; } - void setParams(Type params) { type = Signature(params, getResults()); } - void setResults(Type results) { type = Signature(getParams(), results); } - size_t getNumParams(); size_t getNumVars(); size_t getNumLocals(); @@ -1813,7 +1651,7 @@ Table = 1, Memory = 2, Global = 3, - Tag = 4, + Event = 4, Invalid = -1 }; @@ -1826,25 +1664,6 @@ ExternalKind kind; }; -class ElementSegment : public Named { -public: - Name table; - Expression* offset; - Type type = Type::funcref; - std::vector data; - - ElementSegment() = default; - ElementSegment(Name table, Expression* offset, Type type = Type::funcref) - : table(table), offset(offset), type(type) {} - ElementSegment(Name table, - Expression* offset, - Type type, - std::vector& init) - : table(table), offset(offset), type(type) { - data.swap(init); - } -}; - class Table : public Importable { public: static const Address::address32_t kPageSize = 1; @@ -1852,15 +1671,32 @@ // In wasm32/64, the maximum table size is limited by a 32-bit pointer: 4GB static const Index kMaxSize = Index(-1); + struct Segment { + Expression* offset; + std::vector data; + Segment() = default; + Segment(Expression* offset) : offset(offset) {} + Segment(Expression* offset, std::vector& init) : offset(offset) { + data.swap(init); + } + }; + + // Currently the wasm object always 'has' one Table. It 'exists' if it has + // been defined or imported. The table can exist but be empty and have no + // defined initial or max size. + bool exists = false; Address initial = 0; Address max = kMaxSize; - Type type = Type::funcref; + std::vector segments; + Table() { name = Name::fromInt(0); } bool hasMax() { return max != kUnlimitedSize; } void clear() { + exists = false; name = ""; initial = 0; max = kMaxSize; + segments.clear(); } }; @@ -1904,6 +1740,7 @@ Address max = kMaxSize32; std::vector segments; + // See comment in Table. bool shared = false; Type indexType = Type::i32; @@ -1928,8 +1765,13 @@ bool mutable_ = false; }; -class Tag : public Importable { +// Kinds of event attributes. +enum WasmEventAttribute : unsigned { WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0 }; + +class Event : public Importable { public: + // Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible. + uint32_t attribute = WASM_EVENT_ATTRIBUTE_EXCEPTION; Signature sig; }; @@ -1944,10 +1786,8 @@ // The optional "dylink" section is used in dynamic linking. class DylinkSection { public: - bool isLegacy = false; Index memorySize, memoryAlignment, tableSize, tableAlignment; std::vector neededDynlibs; - std::vector tail; }; class Module { @@ -1957,10 +1797,9 @@ std::vector> exports; std::vector> functions; std::vector> globals; - std::vector> tags; - std::vector> elementSegments; - std::vector> tables; + std::vector> events; + Table table; Memory memory; Name start; @@ -1982,73 +1821,57 @@ // Module name, if specified. Serves a documentary role only. Name name; - std::unordered_map typeNames; - MixedArena allocator; private: // TODO: add a build option where Names are just indices, and then these // methods are not needed // exports map is by the *exported* name, which is unique - std::unordered_map exportsMap; - std::unordered_map functionsMap; - std::unordered_map tablesMap; - std::unordered_map elementSegmentsMap; - std::unordered_map globalsMap; - std::unordered_map tagsMap; + std::map exportsMap; + std::map functionsMap; + std::map globalsMap; + std::map eventsMap; public: Module() = default; Export* getExport(Name name); Function* getFunction(Name name); - Table* getTable(Name name); - ElementSegment* getElementSegment(Name name); Global* getGlobal(Name name); - Tag* getTag(Name name); + Event* getEvent(Name name); Export* getExportOrNull(Name name); - Table* getTableOrNull(Name name); - ElementSegment* getElementSegmentOrNull(Name name); Function* getFunctionOrNull(Name name); Global* getGlobalOrNull(Name name); - Tag* getTagOrNull(Name name); + Event* getEventOrNull(Name name); Export* addExport(Export* curr); Function* addFunction(Function* curr); Global* addGlobal(Global* curr); - Tag* addTag(Tag* curr); + Event* addEvent(Event* curr); Export* addExport(std::unique_ptr&& curr); Function* addFunction(std::unique_ptr&& curr); - Table* addTable(std::unique_ptr
&& curr); - ElementSegment* addElementSegment(std::unique_ptr&& curr); Global* addGlobal(std::unique_ptr&& curr); - Tag* addTag(std::unique_ptr&& curr); + Event* addEvent(std::unique_ptr&& curr); void addStart(const Name& s); void removeExport(Name name); void removeFunction(Name name); - void removeTable(Name name); - void removeElementSegment(Name name); void removeGlobal(Name name); - void removeTag(Name name); + void removeEvent(Name name); void removeExports(std::function pred); void removeFunctions(std::function pred); - void removeTables(std::function pred); - void removeElementSegments(std::function pred); void removeGlobals(std::function pred); - void removeTags(std::function pred); + void removeEvents(std::function pred); void updateMaps(); void clearDebugInfo(); }; -using ModuleExpression = std::pair; - } // namespace wasm namespace std { @@ -2060,7 +1883,6 @@ std::ostream& operator<<(std::ostream& o, wasm::Module& module); std::ostream& operator<<(std::ostream& o, wasm::Expression& expression); -std::ostream& operator<<(std::ostream& o, wasm::ModuleExpression pair); std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst); std::ostream& operator<<(std::ostream& o, wasm::StackIR& ir); diff -Nru binaryen-108/src/wasm-interpreter.h binaryen-99/src/wasm-interpreter.h --- binaryen-108/src/wasm-interpreter.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-interpreter.h 2021-01-07 20:01:06.000000000 +0000 @@ -26,7 +26,6 @@ #include #include #include -#include #include "ir/module-utils.h" #include "support/bits.h" @@ -35,13 +34,16 @@ #include "wasm-traversal.h" #include "wasm.h" +#ifdef WASM_INTERPRETER_DEBUG +#include "wasm-printing.h" +#endif + namespace wasm { struct WasmException { - Name tag; - Literals values; + WasmException(Literal exn) : exn(exn) {} + Literal exn; }; -std::ostream& operator<<(std::ostream& o, const WasmException& exn); using namespace cashew; @@ -98,6 +100,9 @@ } }; +// A list of literals, for function calls +typedef std::vector LiteralList; + // Debugging helpers #ifdef WASM_INTERPRETER_DEBUG class Indenter { @@ -150,13 +155,7 @@ // Execute an expression template class ExpressionRunner : public OverriddenVisitor { - SubType* self() { return static_cast(this); } - protected: - // Optional module context to search for globals and called functions. NULL if - // we are not interested in any context. - Module* module = nullptr; - // Maximum depth before giving up. Index maxDepth; Index depth = 0; @@ -164,11 +163,12 @@ // Maximum iterations before giving up on a loop. Index maxLoopIterations; - Flow generateArguments(const ExpressionList& operands, Literals& arguments) { + Flow generateArguments(const ExpressionList& operands, + LiteralList& arguments) { NOTE_ENTER_("generateArguments"); arguments.reserve(operands.size()); for (auto expression : operands) { - Flow flow = self()->visit(expression); + Flow flow = this->visit(expression); if (flow.breaking()) { return flow; } @@ -182,17 +182,14 @@ // Indicates no limit of maxDepth or maxLoopIterations. static const Index NO_LIMIT = 0; - ExpressionRunner(Module* module = nullptr, - Index maxDepth = NO_LIMIT, + ExpressionRunner(Index maxDepth = NO_LIMIT, Index maxLoopIterations = NO_LIMIT) - : module(module), maxDepth(maxDepth), maxLoopIterations(maxLoopIterations) { - } - virtual ~ExpressionRunner() = default; + : maxDepth(maxDepth), maxLoopIterations(maxLoopIterations) {} Flow visit(Expression* curr) { depth++; if (maxDepth != NO_LIMIT && depth > maxDepth) { - hostLimit("interpreter recursion limit"); + trap("interpreter recursion limit"); } auto ret = OverriddenVisitor::visit(curr); if (!ret.breaking()) { @@ -202,7 +199,7 @@ if (!Type::isSubType(type, curr->type)) { std::cerr << "expected " << curr->type << ", seeing " << type << " from\n" - << *curr << '\n'; + << curr << '\n'; } #endif assert(Type::isSubType(type, curr->type)); @@ -212,9 +209,6 @@ return ret; } - // Gets the module this runner is operating on. - Module* getModule() { return module; } - Flow visitBlock(Block* curr) { NOTE_ENTER("Block"); // special-case Block, because Block nesting (in their first element) can be @@ -394,6 +388,7 @@ return value.extendS16(); case ExtendS32Int64: return value.extendS32(); + case NegFloat32: case NegFloat64: return value.neg(); @@ -459,12 +454,12 @@ return value.splatF64x2(); case NotVec128: return value.notV128(); - case AnyTrueVec128: - return value.anyTrueV128(); case AbsVecI8x16: return value.absI8x16(); case NegVecI8x16: return value.negI8x16(); + case AnyTrueVecI8x16: + return value.anyTrueI8x16(); case AllTrueVecI8x16: return value.allTrueI8x16(); case BitmaskVecI8x16: @@ -475,6 +470,8 @@ return value.absI16x8(); case NegVecI16x8: return value.negI16x8(); + case AnyTrueVecI16x8: + return value.anyTrueI16x8(); case AllTrueVecI16x8: return value.allTrueI16x8(); case BitmaskVecI16x8: @@ -483,18 +480,16 @@ return value.absI32x4(); case NegVecI32x4: return value.negI32x4(); + case AnyTrueVecI32x4: + return value.anyTrueI32x4(); case AllTrueVecI32x4: return value.allTrueI32x4(); case BitmaskVecI32x4: return value.bitmaskI32x4(); - case AbsVecI64x2: - return value.absI64x2(); case NegVecI64x2: return value.negI64x2(); - case AllTrueVecI64x2: - return value.allTrueI64x2(); case BitmaskVecI64x2: - return value.bitmaskI64x2(); + WASM_UNREACHABLE("unimp"); case AbsVecF32x4: return value.absF32x4(); case NegVecF32x4: @@ -524,61 +519,50 @@ case NearestVecF64x2: return value.nearestF64x2(); case ExtAddPairwiseSVecI8x16ToI16x8: - return value.extAddPairwiseToSI16x8(); + WASM_UNREACHABLE("unimp"); case ExtAddPairwiseUVecI8x16ToI16x8: - return value.extAddPairwiseToUI16x8(); + WASM_UNREACHABLE("unimp"); case ExtAddPairwiseSVecI16x8ToI32x4: - return value.extAddPairwiseToSI32x4(); + WASM_UNREACHABLE("unimp"); case ExtAddPairwiseUVecI16x8ToI32x4: - return value.extAddPairwiseToUI32x4(); + WASM_UNREACHABLE("unimp"); case TruncSatSVecF32x4ToVecI32x4: - case RelaxedTruncSVecF32x4ToVecI32x4: return value.truncSatToSI32x4(); case TruncSatUVecF32x4ToVecI32x4: - case RelaxedTruncUVecF32x4ToVecI32x4: return value.truncSatToUI32x4(); + case TruncSatSVecF64x2ToVecI64x2: + return value.truncSatToSI64x2(); + case TruncSatUVecF64x2ToVecI64x2: + return value.truncSatToUI64x2(); case ConvertSVecI32x4ToVecF32x4: return value.convertSToF32x4(); case ConvertUVecI32x4ToVecF32x4: return value.convertUToF32x4(); - case ExtendLowSVecI8x16ToVecI16x8: - return value.extendLowSToI16x8(); - case ExtendHighSVecI8x16ToVecI16x8: - return value.extendHighSToI16x8(); - case ExtendLowUVecI8x16ToVecI16x8: - return value.extendLowUToI16x8(); - case ExtendHighUVecI8x16ToVecI16x8: - return value.extendHighUToI16x8(); - case ExtendLowSVecI16x8ToVecI32x4: - return value.extendLowSToI32x4(); - case ExtendHighSVecI16x8ToVecI32x4: - return value.extendHighSToI32x4(); - case ExtendLowUVecI16x8ToVecI32x4: - return value.extendLowUToI32x4(); - case ExtendHighUVecI16x8ToVecI32x4: - return value.extendHighUToI32x4(); - case ExtendLowSVecI32x4ToVecI64x2: - return value.extendLowSToI64x2(); - case ExtendHighSVecI32x4ToVecI64x2: - return value.extendHighSToI64x2(); - case ExtendLowUVecI32x4ToVecI64x2: - return value.extendLowUToI64x2(); - case ExtendHighUVecI32x4ToVecI64x2: - return value.extendHighUToI64x2(); - case ConvertLowSVecI32x4ToVecF64x2: - return value.convertLowSToF64x2(); - case ConvertLowUVecI32x4ToVecF64x2: - return value.convertLowUToF64x2(); - case TruncSatZeroSVecF64x2ToVecI32x4: - case RelaxedTruncZeroSVecF64x2ToVecI32x4: - return value.truncSatZeroSToI32x4(); - case TruncSatZeroUVecF64x2ToVecI32x4: - case RelaxedTruncZeroUVecF64x2ToVecI32x4: - return value.truncSatZeroUToI32x4(); - case DemoteZeroVecF64x2ToVecF32x4: - return value.demoteZeroToF32x4(); - case PromoteLowVecF32x4ToVecF64x2: - return value.promoteLowToF64x2(); + case ConvertSVecI64x2ToVecF64x2: + return value.convertSToF64x2(); + case ConvertUVecI64x2ToVecF64x2: + return value.convertUToF64x2(); + case WidenLowSVecI8x16ToVecI16x8: + return value.widenLowSToVecI16x8(); + case WidenHighSVecI8x16ToVecI16x8: + return value.widenHighSToVecI16x8(); + case WidenLowUVecI8x16ToVecI16x8: + return value.widenLowUToVecI16x8(); + case WidenHighUVecI8x16ToVecI16x8: + return value.widenHighUToVecI16x8(); + case WidenLowSVecI16x8ToVecI32x4: + return value.widenLowSToVecI32x4(); + case WidenHighSVecI16x8ToVecI32x4: + return value.widenHighSToVecI32x4(); + case WidenLowUVecI16x8ToVecI32x4: + return value.widenLowUToVecI32x4(); + case WidenHighUVecI16x8ToVecI32x4: + return value.widenHighUToVecI32x4(); + case WidenLowSVecI32x4ToVecI64x2: + case WidenHighSVecI32x4ToVecI64x2: + case WidenLowUVecI32x4ToVecI64x2: + case WidenHighUVecI32x4ToVecI64x2: + WASM_UNREACHABLE("unimp"); case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); } @@ -826,16 +810,6 @@ return left.geUI32x4(right); case EqVecI64x2: return left.eqI64x2(right); - case NeVecI64x2: - return left.neI64x2(right); - case LtSVecI64x2: - return left.ltSI64x2(right); - case GtSVecI64x2: - return left.gtSI64x2(right); - case LeSVecI64x2: - return left.leSI64x2(right); - case GeSVecI64x2: - return left.geSI64x2(right); case EqVecF32x4: return left.eqF32x4(right); case NeVecF32x4: @@ -882,6 +856,8 @@ return left.subSaturateSI8x16(right); case SubSatUVecI8x16: return left.subSaturateUI8x16(right); + case MulVecI8x16: + return left.mulI8x16(right); case MinSVecI8x16: return left.minSI8x16(right); case MinUVecI8x16: @@ -917,7 +893,6 @@ case AvgrUVecI16x8: return left.avgrUI16x8(right); case Q15MulrSatSVecI16x8: - case RelaxedQ15MulrSVecI16x8: return left.q15MulrSatSI16x8(right); case ExtMulLowSVecI16x8: return left.extMulLowSI16x8(right); @@ -975,10 +950,8 @@ case DivVecF32x4: return left.divF32x4(right); case MinVecF32x4: - case RelaxedMinVecF32x4: return left.minF32x4(right); case MaxVecF32x4: - case RelaxedMaxVecF32x4: return left.maxF32x4(right); case PMinVecF32x4: return left.pminF32x4(right); @@ -993,10 +966,8 @@ case DivVecF64x2: return left.divF64x2(right); case MinVecF64x2: - case RelaxedMinVecF64x2: return left.minF64x2(right); case MaxVecF64x2: - case RelaxedMaxVecF64x2: return left.maxF64x2(right); case PMinVecF64x2: return left.pminF64x2(right); @@ -1004,22 +975,16 @@ return left.pmaxF64x2(right); case NarrowSVecI16x8ToVecI8x16: - return left.narrowSToI8x16(right); + return left.narrowSToVecI8x16(right); case NarrowUVecI16x8ToVecI8x16: - return left.narrowUToI8x16(right); + return left.narrowUToVecI8x16(right); case NarrowSVecI32x4ToVecI16x8: - return left.narrowSToI16x8(right); + return left.narrowSToVecI16x8(right); case NarrowUVecI32x4ToVecI16x8: - return left.narrowUToI16x8(right); + return left.narrowUToVecI16x8(right); - case SwizzleVecI8x16: - case RelaxedSwizzleVecI8x16: - return left.swizzleI8x16(right); - - case DotI8x16I7x16SToVecI16x8: - return left.dotSI8x16toI16x8(right); - case DotI8x16I7x16UToVecI16x8: - return left.dotUI8x16toI16x8(right); + case SwizzleVec8x16: + return left.swizzleVec8x16(right); case InvalidBinary: WASM_UNREACHABLE("invalid binary op"); @@ -1028,7 +993,7 @@ } Flow visitSIMDExtract(SIMDExtract* curr) { NOTE_ENTER("SIMDExtract"); - Flow flow = self()->visit(curr->vec); + Flow flow = this->visit(curr->vec); if (flow.breaking()) { return flow; } @@ -1055,12 +1020,12 @@ } Flow visitSIMDReplace(SIMDReplace* curr) { NOTE_ENTER("SIMDReplace"); - Flow flow = self()->visit(curr->vec); + Flow flow = this->visit(curr->vec); if (flow.breaking()) { return flow; } Literal vec = flow.getSingleValue(); - flow = self()->visit(curr->value); + flow = this->visit(curr->value); if (flow.breaking()) { return flow; } @@ -1083,12 +1048,12 @@ } Flow visitSIMDShuffle(SIMDShuffle* curr) { NOTE_ENTER("SIMDShuffle"); - Flow flow = self()->visit(curr->left); + Flow flow = this->visit(curr->left); if (flow.breaking()) { return flow; } Literal left = flow.getSingleValue(); - flow = self()->visit(curr->right); + flow = this->visit(curr->right); if (flow.breaking()) { return flow; } @@ -1097,50 +1062,37 @@ } Flow visitSIMDTernary(SIMDTernary* curr) { NOTE_ENTER("SIMDBitselect"); - Flow flow = self()->visit(curr->a); + Flow flow = this->visit(curr->a); if (flow.breaking()) { return flow; } Literal a = flow.getSingleValue(); - flow = self()->visit(curr->b); + flow = this->visit(curr->b); if (flow.breaking()) { return flow; } Literal b = flow.getSingleValue(); - flow = self()->visit(curr->c); + flow = this->visit(curr->c); if (flow.breaking()) { return flow; } Literal c = flow.getSingleValue(); switch (curr->op) { case Bitselect: - case LaneselectI8x16: - case LaneselectI16x8: - case LaneselectI32x4: - case LaneselectI64x2: return c.bitselectV128(a, b); - - case RelaxedFmaVecF32x4: - return a.relaxedFmaF32x4(b, c); - case RelaxedFmsVecF32x4: - return a.relaxedFmsF32x4(b, c); - case RelaxedFmaVecF64x2: - return a.relaxedFmaF64x2(b, c); - case RelaxedFmsVecF64x2: - return a.relaxedFmsF64x2(b, c); default: - // TODO: implement signselect and dot_add + // TODO: implement qfma/qfms and signselect WASM_UNREACHABLE("not implemented"); } } Flow visitSIMDShift(SIMDShift* curr) { NOTE_ENTER("SIMDShift"); - Flow flow = self()->visit(curr->vec); + Flow flow = this->visit(curr->vec); if (flow.breaking()) { return flow; } Literal vec = flow.getSingleValue(); - flow = self()->visit(curr->shift); + flow = this->visit(curr->shift); if (flow.breaking()) { return flow; } @@ -1215,6 +1167,14 @@ NOTE_ENTER("Nop"); return Flow(); } + Flow visitPrefetch(Prefetch* curr) { + NOTE_ENTER("Prefetch"); + Flow flow = visit(curr->ptr); + if (flow.breaking()) { + return flow; + } + return Flow(); + } Flow visitUnreachable(Unreachable* curr) { NOTE_ENTER("Unreachable"); trap("unreachable"); @@ -1288,7 +1248,7 @@ } Flow visitTupleMake(TupleMake* curr) { NOTE_ENTER("tuple.make"); - Literals arguments; + LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) { return flow; @@ -1339,27 +1299,15 @@ NOTE_ENTER("RefNull"); return Literal::makeNull(curr->type); } - Flow visitRefIs(RefIs* curr) { - NOTE_ENTER("RefIs"); + Flow visitRefIsNull(RefIsNull* curr) { + NOTE_ENTER("RefIsNull"); Flow flow = visit(curr->value); if (flow.breaking()) { return flow; } const auto& value = flow.getSingleValue(); NOTE_EVAL1(value); - switch (curr->op) { - case RefIsNull: - return Literal(value.isNull()); - case RefIsFunc: - return Literal(!value.isNull() && value.type.isFunction()); - case RefIsData: - return Literal(!value.isNull() && value.isData()); - case RefIsI31: - return Literal(!value.isNull() && - value.type.getHeapType() == HeapType::i31); - default: - WASM_UNREACHABLE("unimplemented ref.is_*"); - } + return Literal(value.isNull()); } Flow visitRefFunc(RefFunc* curr) { NOTE_ENTER("RefFunc"); @@ -1381,28 +1329,55 @@ NOTE_EVAL2(left, right); return Literal(int32_t(left == right)); } - Flow visitTableGet(TableGet* curr) { WASM_UNREACHABLE("unimp"); } - Flow visitTableSet(TableSet* curr) { WASM_UNREACHABLE("unimp"); } - Flow visitTableSize(TableSize* curr) { WASM_UNREACHABLE("unimp"); } - Flow visitTableGrow(TableGrow* curr) { WASM_UNREACHABLE("unimp"); } Flow visitTry(Try* curr) { WASM_UNREACHABLE("unimp"); } Flow visitThrow(Throw* curr) { NOTE_ENTER("Throw"); - Literals arguments; + LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) { return flow; } - NOTE_EVAL1(curr->tag); - WasmException exn; - exn.tag = curr->tag; + NOTE_EVAL1(curr->event); + auto exn = std::make_unique(); + exn->event = curr->event; for (auto item : arguments) { - exn.values.push_back(item); + exn->values.push_back(item); } - throwException(exn); + throwException(Literal::makeExn(std::move(exn))); WASM_UNREACHABLE("throw"); } - Flow visitRethrow(Rethrow* curr) { WASM_UNREACHABLE("unimp"); } + Flow visitRethrow(Rethrow* curr) { + NOTE_ENTER("Rethrow"); + Flow flow = visit(curr->exnref); + if (flow.breaking()) { + return flow; + } + const auto& value = flow.getSingleValue(); + if (value.isNull()) { + trap("rethrow: argument is null"); + } + throwException(value); + WASM_UNREACHABLE("rethrow"); + } + Flow visitBrOnExn(BrOnExn* curr) { + NOTE_ENTER("BrOnExn"); + Flow flow = this->visit(curr->exnref); + if (flow.breaking()) { + return flow; + } + const auto& value = flow.getSingleValue(); + if (value.isNull()) { + trap("br_on_exn: argument is null"); + } + auto ex = value.getExceptionPackage(); + if (curr->event != ex.event) { // Not taken + return flow; + } + // Taken + flow.values = ex.values; + flow.breakTo = curr->name; + return flow; + } Flow visitI31New(I31New* curr) { NOTE_ENTER("I31New"); Flow flow = visit(curr->value); @@ -1427,266 +1402,125 @@ // Helper for ref.test, ref.cast, and br_on_cast, which share almost all their // logic except for what they return. struct Cast { - // The control flow that preempts the cast. - struct Breaking : Flow { - Breaking(Flow breaking) : Flow(breaking) {} - }; - // The null input to the cast. - struct Null : Literal { - Null(Literal original) : Literal(original) {} - }; - // The result of the successful cast. - struct Success : Literal { - Success(Literal result) : Literal(result) {} - }; - // The input to a failed cast. - struct Failure : Literal { - Failure(Literal original) : Literal(original) {} - }; - - std::variant state; - - template Cast(T state) : state(state) {} - Flow* getBreaking() { return std::get_if(&state); } - Literal* getNull() { return std::get_if(&state); } - Literal* getSuccess() { return std::get_if(&state); } - Literal* getFailure() { return std::get_if(&state); } - Literal* getNullOrFailure() { - if (auto* original = getNull()) { - return original; - } else { - return getFailure(); - } - } + enum Outcome { + // We took a break before doing anything. + Break, + // The input was null. + Null, + // The cast succeeded. + Success, + // The cast failed. + Failure + } outcome; + + Flow breaking; + Literal originalRef; + Literal castRef; }; template Cast doCast(T* curr) { - Flow ref = self()->visit(curr->ref); + Cast cast; + Flow ref = this->visit(curr->ref); if (ref.breaking()) { - return typename Cast::Breaking{ref}; - } - // The RTT value for the type we are trying to cast to. - Literal intendedRtt; - if (curr->rtt) { - // This is a dynamic check with an RTT. - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return typename Cast::Breaking{rtt}; - } - intendedRtt = rtt.getSingleValue(); - } else { - // If there is no explicit RTT, use the canonical RTT for the static type. - intendedRtt = Literal::makeCanonicalRtt(curr->intendedType); - } - Literal original = ref.getSingleValue(); - if (original.isNull()) { - return typename Cast::Null{original}; - } - // The input may not be GC data or a function; for example it could be an - // anyref or an i31. The cast definitely fails in these cases. - if (!original.isData() && !original.isFunction()) { - return typename Cast::Failure{original}; - } - Literal actualRtt; - if (original.isFunction()) { - // Function references always have the canonical RTTs of the functions - // they reference. We must have a module to look up the function's type to - // get that canonical RTT. - auto* func = - module ? module->getFunctionOrNull(original.getFunc()) : nullptr; - if (!func) { - return typename Cast::Breaking{NONCONSTANT_FLOW}; - } - actualRtt = Literal::makeCanonicalRtt(func->type); - } else { - assert(original.isData()); - actualRtt = original.getGCData()->rtt; - }; - // We have the actual and intended RTTs, so perform the cast. - if (actualRtt.isSubRtt(intendedRtt)) { - Type resultType(intendedRtt.type.getHeapType(), NonNullable); - if (original.isFunction()) { - return typename Cast::Success{Literal{original.getFunc(), resultType}}; - } else { - return - typename Cast::Success{Literal(original.getGCData(), resultType)}; - } + cast.outcome = cast.Break; + cast.breaking = ref; + return cast; + } + Flow rtt = this->visit(curr->rtt); + if (rtt.breaking()) { + cast.outcome = cast.Break; + cast.breaking = rtt; + return cast; + } + cast.originalRef = ref.getSingleValue(); + auto gcData = cast.originalRef.getGCData(); + if (!gcData) { + cast.outcome = cast.Null; + return cast; + } + auto refRtt = gcData->rtt; + auto intendedRtt = rtt.getSingleValue(); + if (!refRtt.isSubRtt(intendedRtt)) { + cast.outcome = cast.Failure; } else { - return typename Cast::Failure{original}; + cast.outcome = cast.Success; + cast.castRef = + Literal(gcData, Type(intendedRtt.type.getHeapType(), Nullable)); } + return cast; } Flow visitRefTest(RefTest* curr) { NOTE_ENTER("RefTest"); auto cast = doCast(curr); - if (auto* breaking = cast.getBreaking()) { - return *breaking; - } else { - return Literal(int32_t(bool(cast.getSuccess()))); + if (cast.outcome == cast.Break) { + return cast.breaking; } + return Literal(int32_t(cast.outcome == cast.Success)); } Flow visitRefCast(RefCast* curr) { NOTE_ENTER("RefCast"); auto cast = doCast(curr); - if (auto* breaking = cast.getBreaking()) { - return *breaking; - } else if (cast.getNull()) { - return Literal::makeNull(Type(curr->type.getHeapType(), Nullable)); - } else if (auto* result = cast.getSuccess()) { - return *result; - } - assert(cast.getFailure()); - trap("cast error"); - WASM_UNREACHABLE("unreachable"); - } - Flow visitBrOn(BrOn* curr) { - NOTE_ENTER("BrOn"); - // BrOnCast* uses the casting infrastructure, so handle them first. - if (curr->op == BrOnCast || curr->op == BrOnCastFail) { - auto cast = doCast(curr); - if (auto* breaking = cast.getBreaking()) { - return *breaking; - } else if (auto* original = cast.getNullOrFailure()) { - if (curr->op == BrOnCast) { - return *original; - } else { - return Flow(curr->name, *original); - } - } else { - auto* result = cast.getSuccess(); - assert(result); - if (curr->op == BrOnCast) { - return Flow(curr->name, *result); - } else { - return *result; - } - } + if (cast.outcome == cast.Break) { + return cast.breaking; } - // The others do a simpler check for the type. - Flow flow = visit(curr->ref); - if (flow.breaking()) { - return flow; + if (cast.outcome == cast.Null) { + return Literal::makeNull(curr->type); } - const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); - if (curr->op == BrOnNull) { - // Unlike the others, BrOnNull does not propagate the value if it takes - // the branch. - if (value.isNull()) { - return Flow(curr->name); - } - // If the branch is not taken, we return the non-null value. - return {value}; - } - if (curr->op == BrOnNonNull) { - // Unlike the others, BrOnNonNull does not return a value if it does not - // take the branch. - if (value.isNull()) { - return Flow(); - } - // If the branch is taken, we send the non-null value. - return Flow(curr->name, value); + if (cast.outcome == cast.Failure) { + trap("cast error"); } - // See if the input is the right kind (ignoring the flipping behavior of - // BrOn*). - bool isRightKind; - if (value.isNull()) { - // A null is never the right kind. - isRightKind = false; - } else { - switch (curr->op) { - case BrOnNonFunc: - case BrOnFunc: - isRightKind = value.type.isFunction(); - break; - case BrOnNonData: - case BrOnData: - isRightKind = value.isData(); - break; - case BrOnNonI31: - case BrOnI31: - isRightKind = value.type.getHeapType() == HeapType::i31; - break; - default: - WASM_UNREACHABLE("invalid br_on_*"); - } + assert(cast.outcome == cast.Success); + return cast.castRef; + } + Flow visitBrOnCast(BrOnCast* curr) { + NOTE_ENTER("BrOnCast"); + auto cast = doCast(curr); + if (cast.outcome == cast.Break) { + return cast.breaking; } - // The Non* operations require us to flip the normal behavior. - switch (curr->op) { - case BrOnNonFunc: - case BrOnNonData: - case BrOnNonI31: - isRightKind = !isRightKind; - break; - default: { - } - } - if (isRightKind) { - // Take the branch. - return Flow(curr->name, value); + if (cast.outcome == cast.Null || cast.outcome == cast.Failure) { + return cast.originalRef; } - return {value}; - } - Flow visitRttCanon(RttCanon* curr) { - return Literal::makeCanonicalRtt(curr->type.getHeapType()); + assert(cast.outcome == cast.Success); + return Flow(curr->name, cast.castRef); } + Flow visitRttCanon(RttCanon* curr) { return Literal(curr->type); } Flow visitRttSub(RttSub* curr) { - Flow parent = self()->visit(curr->parent); + Flow parent = this->visit(curr->parent); if (parent.breaking()) { return parent; } auto parentValue = parent.getSingleValue(); auto newSupers = std::make_unique(parentValue.getRttSupers()); - newSupers->push_back(parentValue.type.getHeapType()); - if (curr->fresh) { - newSupers->back().makeFresh(); - } + newSupers->push_back(parentValue.type); return Literal(std::move(newSupers), curr->type); } - Flow visitStructNew(StructNew* curr) { NOTE_ENTER("StructNew"); - Literal rttVal; - if (curr->rtt) { - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return rtt; - } - rttVal = rtt.getSingleValue(); - } - if (curr->type == Type::unreachable) { - // We cannot proceed to compute the heap type, as there isn't one. Just - // find why we are unreachable, and stop there. - for (auto* operand : curr->operands) { - auto value = self()->visit(operand); - if (value.breaking()) { - return value; - } - } - WASM_UNREACHABLE("unreachable but no unreachable child"); + auto rtt = this->visit(curr->rtt); + if (rtt.breaking()) { + return rtt; } - auto heapType = curr->type.getHeapType(); - const auto& fields = heapType.getStruct().fields; + const auto& fields = curr->rtt->type.getHeapType().getStruct().fields; Literals data(fields.size()); for (Index i = 0; i < fields.size(); i++) { if (curr->isWithDefault()) { data[i] = Literal::makeZero(fields[i].type); } else { - auto value = self()->visit(curr->operands[i]); + auto value = this->visit(curr->operands[i]); if (value.breaking()) { return value; } data[i] = value.getSingleValue(); } } - if (!curr->rtt) { - rttVal = Literal::makeCanonicalRtt(heapType); - } - return Literal(std::make_shared(rttVal, data), curr->type); + return Flow(Literal(std::make_shared(rtt.getSingleValue(), data), + curr->type)); } Flow visitStructGet(StructGet* curr) { NOTE_ENTER("StructGet"); - Flow ref = self()->visit(curr->ref); + Flow ref = this->visit(curr->ref); if (ref.breaking()) { return ref; } @@ -1699,11 +1533,11 @@ } Flow visitStructSet(StructSet* curr) { NOTE_ENTER("StructSet"); - Flow ref = self()->visit(curr->ref); + Flow ref = this->visit(curr->ref); if (ref.breaking()) { return ref; } - Flow value = self()->visit(curr->value); + Flow value = this->visit(curr->value); if (value.breaking()) { return value; } @@ -1716,108 +1550,43 @@ truncateForPacking(value.getSingleValue(), field); return Flow(); } - - // Arbitrary deterministic limit on size. If we need to allocate a Literals - // vector that takes around 1-2GB of memory then we are likely to hit memory - // limits on 32-bit machines, and in particular on wasm32 VMs that do not - // have 4GB support, so give up there. - static const Index ArrayLimit = (1 << 30) / sizeof(Literal); - Flow visitArrayNew(ArrayNew* curr) { NOTE_ENTER("ArrayNew"); - Literal rttVal; - if (curr->rtt) { - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return rtt; - } - rttVal = rtt.getSingleValue(); + auto rtt = this->visit(curr->rtt); + if (rtt.breaking()) { + return rtt; } - auto size = self()->visit(curr->size); + auto size = this->visit(curr->size); if (size.breaking()) { return size; } - if (curr->type == Type::unreachable) { - // We cannot proceed to compute the heap type, as there isn't one. Just - // visit the unreachable child, and stop there. - auto init = self()->visit(curr->init); - assert(init.breaking()); - return init; - } - auto heapType = curr->type.getHeapType(); - const auto& element = heapType.getArray().element; + const auto& element = curr->rtt->type.getHeapType().getArray().element; Index num = size.getSingleValue().geti32(); - if (num >= ArrayLimit) { - hostLimit("allocation failure"); - } Literals data(num); if (curr->isWithDefault()) { for (Index i = 0; i < num; i++) { data[i] = Literal::makeZero(element.type); } } else { - auto init = self()->visit(curr->init); + auto init = this->visit(curr->init); if (init.breaking()) { return init; } - auto field = curr->type.getHeapType().getArray().element; - auto value = truncateForPacking(init.getSingleValue(), field); + auto value = init.getSingleValue(); for (Index i = 0; i < num; i++) { data[i] = value; } } - if (!curr->rtt) { - rttVal = Literal::makeCanonicalRtt(heapType); - } - return Literal(std::make_shared(rttVal, data), curr->type); - } - Flow visitArrayInit(ArrayInit* curr) { - NOTE_ENTER("ArrayInit"); - Literal rttVal; - if (curr->rtt) { - Flow rtt = self()->visit(curr->rtt); - if (rtt.breaking()) { - return rtt; - } - rttVal = rtt.getSingleValue(); - } - Index num = curr->values.size(); - if (num >= ArrayLimit) { - hostLimit("allocation failure"); - } - if (curr->type == Type::unreachable) { - // We cannot proceed to compute the heap type, as there isn't one. Just - // find why we are unreachable, and stop there. - for (auto* value : curr->values) { - auto result = self()->visit(value); - if (result.breaking()) { - return result; - } - } - WASM_UNREACHABLE("unreachable but no unreachable child"); - } - auto heapType = curr->type.getHeapType(); - auto field = heapType.getArray().element; - Literals data(num); - for (Index i = 0; i < num; i++) { - auto value = self()->visit(curr->values[i]); - if (value.breaking()) { - return value; - } - data[i] = truncateForPacking(value.getSingleValue(), field); - } - if (!curr->rtt) { - rttVal = Literal::makeCanonicalRtt(heapType); - } - return Literal(std::make_shared(rttVal, data), curr->type); + return Flow(Literal(std::make_shared(rtt.getSingleValue(), data), + curr->type)); } Flow visitArrayGet(ArrayGet* curr) { NOTE_ENTER("ArrayGet"); - Flow ref = self()->visit(curr->ref); + Flow ref = this->visit(curr->ref); if (ref.breaking()) { return ref; } - Flow index = self()->visit(curr->index); + Flow index = this->visit(curr->index); if (index.breaking()) { return index; } @@ -1834,15 +1603,15 @@ } Flow visitArraySet(ArraySet* curr) { NOTE_ENTER("ArraySet"); - Flow ref = self()->visit(curr->ref); + Flow ref = this->visit(curr->ref); if (ref.breaking()) { return ref; } - Flow index = self()->visit(curr->index); + Flow index = this->visit(curr->index); if (index.breaking()) { return index; } - Flow value = self()->visit(curr->value); + Flow value = this->visit(curr->value); if (value.breaking()) { return value; } @@ -1860,7 +1629,7 @@ } Flow visitArrayLen(ArrayLen* curr) { NOTE_ENTER("ArrayLen"); - Flow ref = self()->visit(curr->ref); + Flow ref = this->visit(curr->ref); if (ref.breaking()) { return ref; } @@ -1870,101 +1639,10 @@ } return Literal(int32_t(data->values.size())); } - Flow visitArrayCopy(ArrayCopy* curr) { - NOTE_ENTER("ArrayCopy"); - Flow destRef = self()->visit(curr->destRef); - if (destRef.breaking()) { - return destRef; - } - Flow destIndex = self()->visit(curr->destIndex); - if (destIndex.breaking()) { - return destIndex; - } - Flow srcRef = self()->visit(curr->srcRef); - if (srcRef.breaking()) { - return srcRef; - } - Flow srcIndex = self()->visit(curr->srcIndex); - if (srcIndex.breaking()) { - return srcIndex; - } - Flow length = self()->visit(curr->length); - if (length.breaking()) { - return length; - } - auto destData = destRef.getSingleValue().getGCData(); - if (!destData) { - trap("null ref"); - } - auto srcData = srcRef.getSingleValue().getGCData(); - if (!srcData) { - trap("null ref"); - } - size_t destVal = destIndex.getSingleValue().getUnsigned(); - size_t srcVal = srcIndex.getSingleValue().getUnsigned(); - size_t lengthVal = length.getSingleValue().getUnsigned(); - if (lengthVal >= ArrayLimit) { - hostLimit("allocation failure"); - } - std::vector copied; - copied.resize(lengthVal); - for (size_t i = 0; i < lengthVal; i++) { - if (srcVal + i >= srcData->values.size()) { - trap("oob"); - } - copied[i] = srcData->values[srcVal + i]; - } - for (size_t i = 0; i < lengthVal; i++) { - if (destVal + i >= destData->values.size()) { - trap("oob"); - } - destData->values[destVal + i] = copied[i]; - } - return Flow(); - } - Flow visitRefAs(RefAs* curr) { - NOTE_ENTER("RefAs"); - Flow flow = visit(curr->value); - if (flow.breaking()) { - return flow; - } - const auto& value = flow.getSingleValue(); - NOTE_EVAL1(value); - if (value.isNull()) { - trap("null ref"); - } - switch (curr->op) { - case RefAsNonNull: - // We've already checked for a null. - break; - case RefAsFunc: - if (!value.type.isFunction()) { - trap("not a func"); - } - break; - case RefAsData: - if (!value.isData()) { - trap("not a data"); - } - break; - case RefAsI31: - if (value.type.getHeapType() != HeapType::i31) { - trap("not an i31"); - } - break; - default: - WASM_UNREACHABLE("unimplemented ref.as_*"); - } - return value; - } virtual void trap(const char* why) { WASM_UNREACHABLE("unimp"); } - virtual void hostLimit(const char* why) { WASM_UNREACHABLE("unimp"); } - - virtual void throwException(const WasmException& exn) { - WASM_UNREACHABLE("unimp"); - } + virtual void throwException(Literal exn) { WASM_UNREACHABLE("unimp"); } private: // Truncate the value if we need to. The storage is just a list of Literals, @@ -2033,6 +1711,10 @@ static const Index NO_LIMIT = 0; protected: + // Optional module context to search for globals and called functions. NULL if + // we are not interested in any context. + Module* module = nullptr; + // Flags indicating special requirements. See FlagValues. Flags flags = FlagValues::DEFAULT; @@ -2049,9 +1731,12 @@ Flags flags, Index maxDepth, Index maxLoopIterations) - : ExpressionRunner(module, maxDepth, maxLoopIterations), + : ExpressionRunner(maxDepth, maxLoopIterations), module(module), flags(flags) {} + // Gets the module this runner is operating on. + Module* getModule() { return module; } + // Sets a known local value to use. void setLocalValue(Index index, Literals& values) { assert(values.isConcrete()); @@ -2096,8 +1781,8 @@ Flow visitGlobalGet(GlobalGet* curr) { NOTE_ENTER("GlobalGet"); NOTE_NAME(curr->name); - if (this->module != nullptr) { - auto* global = this->module->getGlobal(curr->name); + if (module != nullptr) { + auto* global = module->getGlobal(curr->name); // Check if the global has an immutable value anyway if (!global->imported() && !global->mutable_) { return ExpressionRunner::visit(global->init); @@ -2113,11 +1798,11 @@ Flow visitGlobalSet(GlobalSet* curr) { NOTE_ENTER("GlobalSet"); NOTE_NAME(curr->name); - if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS) && - this->module != nullptr) { + if (!(flags & FlagValues::PRESERVE_SIDEEFFECTS) && module != nullptr) { // If we are evaluating and not replacing the expression, remember the // constant value set, if any, for subsequent gets. - assert(this->module->getGlobal(curr->name)->mutable_); + auto* global = module->getGlobal(curr->name); + assert(global->mutable_); auto setFlow = ExpressionRunner::visit(curr->value); if (!setFlow.breaking()) { setGlobalValue(curr->name, setFlow.values); @@ -2133,10 +1818,10 @@ // when replacing as long as the function does not have any side effects. // Might yield something useful for simple functions like `clamp`, sometimes // even if arguments are only partially constant or not constant at all. - if ((flags & FlagValues::TRAVERSE_CALLS) != 0 && this->module != nullptr) { - auto* func = this->module->getFunction(curr->target); + if ((flags & FlagValues::TRAVERSE_CALLS) != 0 && module != nullptr) { + auto* func = module->getFunction(curr->target); if (!func->imported()) { - if (func->getResults().isConcrete()) { + if (func->sig.results.isConcrete()) { auto numOperands = curr->operands.size(); assert(numOperands == func->getNumParams()); auto prevLocalValues = localValues; @@ -2168,22 +1853,6 @@ NOTE_ENTER("CallRef"); return Flow(NONCONSTANT_FLOW); } - Flow visitTableGet(TableGet* curr) { - NOTE_ENTER("TableGet"); - return Flow(NONCONSTANT_FLOW); - } - Flow visitTableSet(TableSet* curr) { - NOTE_ENTER("TableSet"); - return Flow(NONCONSTANT_FLOW); - } - Flow visitTableSize(TableSize* curr) { - NOTE_ENTER("TableSize"); - return Flow(NONCONSTANT_FLOW); - } - Flow visitTableGrow(TableGrow* curr) { - NOTE_ENTER("TableGrow"); - return Flow(NONCONSTANT_FLOW); - } Flow visitLoad(Load* curr) { NOTE_ENTER("Load"); return Flow(NONCONSTANT_FLOW); @@ -2256,28 +1925,32 @@ NOTE_ENTER("Try"); return Flow(NONCONSTANT_FLOW); } - Flow visitRethrow(Rethrow* curr) { - NOTE_ENTER("Rethrow"); - return Flow(NONCONSTANT_FLOW); - } void trap(const char* why) override { throw NonconstantException(); } - void hostLimit(const char* why) override { throw NonconstantException(); } - - virtual void throwException(const WasmException& exn) override { + virtual void throwException(Literal exn) override { throw NonconstantException(); } }; -using GlobalValueSet = std::map; +// Execute an initializer expression of a global, data or element segment. +// see: https://webassembly.org/docs/modules/#initializer-expression +template +class InitializerExpressionRunner + : public ExpressionRunner> { + GlobalManager& globals; + +public: + InitializerExpressionRunner(GlobalManager& globals, Index maxDepth) + : ExpressionRunner>(maxDepth), + globals(globals) {} + + Flow visitGlobalGet(GlobalGet* curr) { return Flow(globals[curr->name]); } +}; // -// A runner for a module. Each runner contains the information to execute the -// module, such as the state of globals, and so forth, so it basically -// encapsulates an instantiation of the wasm, and implements all the interpreter -// instructions that use that info (like global.set etc.) that are not declared -// in ExpressionRunner, which just looks at a single instruction. +// An instance of a WebAssembly module, which can execute it via AST +// interpretation. // // To embed this interpreter, you need to provide an ExternalInterface instance // (see below) which provides the embedding-specific details, that is, how to @@ -2286,8 +1959,7 @@ // To call into the interpreter, use callExport. // -template -class ModuleRunnerBase : public ExpressionRunner { +template class ModuleInstanceBase { public: // // You need to implement one of these to create a concrete interpreter. The @@ -2295,26 +1967,17 @@ // an imported function or accessing memory. // struct ExternalInterface { - ExternalInterface( - std::map> linkedInstances = {}) {} - virtual ~ExternalInterface() = default; virtual void init(Module& wasm, SubType& instance) {} - virtual void importGlobals(GlobalValueSet& globals, Module& wasm) = 0; - virtual Literals callImport(Function* import, Literals& arguments) = 0; - virtual Literals callTable(Name tableName, - Index index, - HeapType sig, - Literals& arguments, + virtual void importGlobals(GlobalManager& globals, Module& wasm) = 0; + virtual Literals callImport(Function* import, LiteralList& arguments) = 0; + virtual Literals callTable(Index index, + Signature sig, + LiteralList& arguments, Type result, SubType& instance) = 0; virtual bool growMemory(Address oldSize, Address newSize) = 0; - virtual bool growTable(Name name, - const Literal& value, - Index oldSize, - Index newSize) = 0; virtual void trap(const char* why) = 0; - virtual void hostLimit(const char* why) = 0; - virtual void throwException(const WasmException& exn) = 0; + virtual void throwException(Literal exnref) = 0; // the default impls for load and store switch on the sizes. you can either // customize load/store, or the sub-functions which they call @@ -2360,10 +2023,11 @@ case Type::v128: return Literal(load128(addr).data()); case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2418,10 +2082,11 @@ store128(addr, value.getv128()); break; case Type::funcref: + case Type::externref: + case Type::exnref: case Type::anyref: case Type::eqref: case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -2456,40 +2121,33 @@ WASM_UNREACHABLE("unimp"); } - virtual Index tableSize(Name tableName) = 0; - - virtual void tableStore(Name tableName, Index index, const Literal& entry) { - WASM_UNREACHABLE("unimp"); - } - virtual Literal tableLoad(Name tableName, Index index) { + virtual void tableStore(Address addr, Name entry) { WASM_UNREACHABLE("unimp"); } }; SubType* self() { return static_cast(this); } - // TODO: this duplicates module in ExpressionRunner, and can be removed Module& wasm; // Values of globals - GlobalValueSet globals; + GlobalManager globals; // Multivalue ABI support (see push/pop). - std::vector multiValues; + std::vector multiValues; - ModuleRunnerBase( - Module& wasm, - ExternalInterface* externalInterface, - std::map> linkedInstances_ = {}) - : ExpressionRunner(&wasm), wasm(wasm), - externalInterface(externalInterface), linkedInstances(linkedInstances_) { + ModuleInstanceBase(Module& wasm, ExternalInterface* externalInterface) + : wasm(wasm), externalInterface(externalInterface) { // import globals from the outside externalInterface->importGlobals(globals, wasm); // prepare memory memorySize = wasm.memory.initial; // generate internal (non-imported) globals ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) { - globals[global->name] = self()->visit(global->init).values; + globals[global->name] = + InitializerExpressionRunner(globals, maxDepth) + .visit(global->init) + .values; }); // initialize the rest of the external interface @@ -2500,13 +2158,13 @@ // run start, if present if (wasm.start.is()) { - Literals arguments; + LiteralList arguments; callFunction(wasm.start, arguments); } } // call an exported function - Literals callExport(Name name, const Literals& arguments) { + Literals callExport(Name name, const LiteralList& arguments) { Export* export_ = wasm.getExportOrNull(name); if (!export_) { externalInterface->trap("callExport not found"); @@ -2514,7 +2172,7 @@ return callFunction(export_->value, arguments); } - Literals callExport(Name name) { return callExport(name, Literals()); } + Literals callExport(Name name) { return callExport(name, LiteralList()); } // get an exported global Literals getExport(Name name) { @@ -2541,7 +2199,7 @@ private: // Keep a record of call depth, to guard against excessive recursion. - size_t callDepth = 0; + size_t callDepth; // Function name stack. We maintain this explicitly to allow printing of // stack traces. @@ -2549,55 +2207,20 @@ std::unordered_set droppedSegments; - struct TableInterfaceInfo { - // The external interface in which the table is defined. - ExternalInterface* interface; - // The name the table has in that interface. - Name name; - }; - - TableInterfaceInfo getTableInterfaceInfo(Name name) { - auto* table = wasm.getTable(name); - if (table->imported()) { - auto& importedInstance = linkedInstances.at(table->module); - auto* tableExport = importedInstance->wasm.getExport(table->base); - return TableInterfaceInfo{importedInstance->externalInterface, - tableExport->value}; - } else { - return TableInterfaceInfo{externalInterface, name}; - } - } - void initializeTableContents() { - for (auto& table : wasm.tables) { - if (table->type.isNullable()) { - // Initial with nulls in a nullable table. - auto info = getTableInterfaceInfo(table->name); - auto null = Literal::makeNull(table->type); - for (Address i = 0; i < table->initial; i++) { - info.interface->tableStore(info.name, i, null); - } - } - } - - ModuleUtils::iterActiveElementSegments(wasm, [&](ElementSegment* segment) { + for (auto& segment : wasm.table.segments) { Address offset = - (uint32_t)self()->visit(segment->offset).getSingleValue().geti32(); - - Table* table = wasm.getTable(segment->table); - ExternalInterface* extInterface = externalInterface; - Name tableName = segment->table; - if (table->imported()) { - auto inst = linkedInstances.at(table->module); - extInterface = inst->externalInterface; - tableName = inst->wasm.getExport(table->base)->value; + (uint32_t)InitializerExpressionRunner(globals, maxDepth) + .visit(segment.offset) + .getSingleValue() + .geti32(); + if (offset + segment.data.size() > wasm.table.initial) { + externalInterface->trap("invalid offset when initializing table"); } - - for (Index i = 0; i < segment->data.size(); ++i) { - Flow ret = self()->visit(segment->data[i]); - extInterface->tableStore(tableName, offset + i, ret.getSingleValue()); + for (size_t i = 0; i != segment.data.size(); ++i) { + externalInterface->tableStore(offset + i, segment.data[i]); } - }); + } } void initializeMemoryContents() { @@ -2627,41 +2250,36 @@ drop.segment = i; drop.finalize(); - self()->visit(&init); - self()->visit(&drop); + // we don't actually have a function, but we need one in order to visit + // the memory.init and data.drop instructions. + Function dummyFunc; + FunctionScope dummyScope(&dummyFunc, {}); + RuntimeExpressionRunner runner(*this, dummyScope, maxDepth); + runner.visit(&init); + runner.visit(&drop); } } -public: class FunctionScope { public: std::vector locals; Function* function; - SubType& parent; - - FunctionScope* oldScope; - - FunctionScope(Function* function, - const Literals& arguments, - SubType& parent) - : function(function), parent(parent) { - oldScope = parent.scope; - parent.scope = this; - if (function->getParams().size() != arguments.size()) { + FunctionScope(Function* function, const LiteralList& arguments) + : function(function) { + if (function->sig.params.size() != arguments.size()) { std::cerr << "Function `" << function->name << "` expects " - << function->getParams().size() << " parameters, got " + << function->sig.params.size() << " parameters, got " << arguments.size() << " arguments." << std::endl; WASM_UNREACHABLE("invalid param count"); } locals.resize(function->getNumLocals()); - Type params = function->getParams(); for (size_t i = 0; i < function->getNumLocals(); i++) { if (i < arguments.size()) { - if (!Type::isSubType(arguments[i].type, params[i])) { + if (!Type::isSubType(arguments[i].type, function->sig.params[i])) { std::cerr << "Function `" << function->name << "` expects type " - << params[i] << " for parameter " << i << ", got " - << arguments[i].type << "." << std::endl; + << function->sig.params[i] << " for parameter " << i + << ", got " << arguments[i].type << "." << std::endl; WASM_UNREACHABLE("invalid param count"); } locals[i] = {arguments[i]}; @@ -2671,866 +2289,718 @@ } } } - - ~FunctionScope() { parent.scope = oldScope; } - - // The current delegate target, if delegation of an exception is in - // progress. If no delegation is in progress, this will be an empty Name. - // This is on a function scope because it cannot "escape" to the outside, - // that is, a delegate target is like a branch target, it operates within - // a function. - Name currDelegateTarget; }; -private: - // This is managed in an RAII manner by the FunctionScope class. - FunctionScope* scope = nullptr; - - // Stack of - SmallVector, 4> exceptionStack; + // Executes expressions with concrete runtime info, the function and module at + // runtime + class RuntimeExpressionRunner + : public ExpressionRunner { + ModuleInstanceBase& instance; + FunctionScope& scope; -protected: - // Returns the instance that defines the memory used by this one. - SubType* getMemoryInstance() { - auto* inst = self(); - while (inst->wasm.memory.imported()) { - inst = inst->linkedInstances.at(inst->wasm.memory.module).get(); - } - return inst; - } - - // Returns a reference to the current value of a potentially imported global - Literals& getGlobal(Name name) { - auto* inst = self(); - auto* global = inst->wasm.getGlobal(name); - while (global->imported()) { - inst = inst->linkedInstances.at(global->module).get(); - Export* globalExport = inst->wasm.getExport(global->base); - global = inst->wasm.getGlobal(globalExport->value); - } - - return inst->globals[global->name]; - } - -public: - Flow visitCall(Call* curr) { - NOTE_ENTER("Call"); - NOTE_NAME(curr->target); - Literals arguments; - Flow flow = self()->generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } - auto* func = wasm.getFunction(curr->target); - Flow ret; - if (func->imported()) { - ret.values = externalInterface->callImport(func, arguments); - } else { - ret.values = callFunctionInternal(curr->target, arguments); - } + public: + RuntimeExpressionRunner(ModuleInstanceBase& instance, + FunctionScope& scope, + Index maxDepth) + : ExpressionRunner(maxDepth), instance(instance), + scope(scope) {} + + Flow visitCall(Call* curr) { + NOTE_ENTER("Call"); + NOTE_NAME(curr->target); + LiteralList arguments; + Flow flow = this->generateArguments(curr->operands, arguments); + if (flow.breaking()) { + return flow; + } + auto* func = instance.wasm.getFunction(curr->target); + Flow ret; + if (func->imported()) { + ret.values = instance.externalInterface->callImport(func, arguments); + } else { + ret.values = instance.callFunctionInternal(curr->target, arguments); + } +#ifdef WASM_INTERPRETER_DEBUG + std::cout << "(returned to " << scope.function->name << ")\n"; +#endif + // TODO: make this a proper tail call (return first) + if (curr->isReturn) { + ret.breakTo = RETURN_FLOW; + } + return ret; + } + Flow visitCallIndirect(CallIndirect* curr) { + NOTE_ENTER("CallIndirect"); + LiteralList arguments; + Flow flow = this->generateArguments(curr->operands, arguments); + if (flow.breaking()) { + return flow; + } + Flow target = this->visit(curr->target); + if (target.breaking()) { + return target; + } + Index index = target.getSingleValue().geti32(); + Type type = curr->isReturn ? scope.function->sig.results : curr->type; + Flow ret = instance.externalInterface->callTable( + index, curr->sig, arguments, type, *instance.self()); + // TODO: make this a proper tail call (return first) + if (curr->isReturn) { + ret.breakTo = RETURN_FLOW; + } + return ret; + } + Flow visitCallRef(CallRef* curr) { + NOTE_ENTER("CallRef"); + LiteralList arguments; + Flow flow = this->generateArguments(curr->operands, arguments); + if (flow.breaking()) { + return flow; + } + Flow target = this->visit(curr->target); + if (target.breaking()) { + return target; + } + if (target.getSingleValue().isNull()) { + trap("null target in call_ref"); + } + Name funcName = target.getSingleValue().getFunc(); + auto* func = instance.wasm.getFunction(funcName); + Flow ret; + if (func->imported()) { + ret.values = instance.externalInterface->callImport(func, arguments); + } else { + ret.values = instance.callFunctionInternal(funcName, arguments); + } #ifdef WASM_INTERPRETER_DEBUG - std::cout << "(returned to " << scope->function->name << ")\n"; + std::cout << "(returned to " << scope.function->name << ")\n"; #endif - // TODO: make this a proper tail call (return first) - if (curr->isReturn) { - ret.breakTo = RETURN_FLOW; + // TODO: make this a proper tail call (return first) + if (curr->isReturn) { + ret.breakTo = RETURN_FLOW; + } + return ret; + } + + Flow visitLocalGet(LocalGet* curr) { + NOTE_ENTER("LocalGet"); + auto index = curr->index; + NOTE_EVAL1(index); + NOTE_EVAL1(scope.locals[index]); + return scope.locals[index]; + } + Flow visitLocalSet(LocalSet* curr) { + NOTE_ENTER("LocalSet"); + auto index = curr->index; + Flow flow = this->visit(curr->value); + if (flow.breaking()) { + return flow; + } + NOTE_EVAL1(index); + NOTE_EVAL1(flow.getSingleValue()); + assert(curr->isTee() ? Type::isSubType(flow.getType(), curr->type) + : true); + scope.locals[index] = flow.values; + return curr->isTee() ? flow : Flow(); + } + + Flow visitGlobalGet(GlobalGet* curr) { + NOTE_ENTER("GlobalGet"); + auto name = curr->name; + NOTE_EVAL1(name); + assert(instance.globals.find(name) != instance.globals.end()); + NOTE_EVAL1(instance.globals[name]); + return instance.globals[name]; + } + Flow visitGlobalSet(GlobalSet* curr) { + NOTE_ENTER("GlobalSet"); + auto name = curr->name; + Flow flow = this->visit(curr->value); + if (flow.breaking()) { + return flow; + } + NOTE_EVAL1(name); + NOTE_EVAL1(flow.getSingleValue()); + instance.globals[name] = flow.values; + return Flow(); } - return ret; - } - Flow visitCallIndirect(CallIndirect* curr) { - NOTE_ENTER("CallIndirect"); - Literals arguments; - Flow flow = self()->generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; + Flow visitLoad(Load* curr) { + NOTE_ENTER("Load"); + Flow flow = this->visit(curr->ptr); + if (flow.breaking()) { + return flow; + } + NOTE_EVAL1(flow); + auto addr = instance.getFinalAddress(curr, flow.getSingleValue()); + if (curr->isAtomic) { + instance.checkAtomicAddress(addr, curr->bytes); + } + auto ret = instance.externalInterface->load(curr, addr); + NOTE_EVAL1(addr); + NOTE_EVAL1(ret); + return ret; + } + Flow visitStore(Store* curr) { + NOTE_ENTER("Store"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) { + return ptr; + } + Flow value = this->visit(curr->value); + if (value.breaking()) { + return value; + } + auto addr = instance.getFinalAddress(curr, ptr.getSingleValue()); + if (curr->isAtomic) { + instance.checkAtomicAddress(addr, curr->bytes); + } + NOTE_EVAL1(addr); + NOTE_EVAL1(value); + instance.externalInterface->store(curr, addr, value.getSingleValue()); + return Flow(); + } + + Flow visitAtomicRMW(AtomicRMW* curr) { + NOTE_ENTER("AtomicRMW"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) { + return ptr; + } + auto value = this->visit(curr->value); + if (value.breaking()) { + return value; + } + NOTE_EVAL1(ptr); + auto addr = instance.getFinalAddress(curr, ptr.getSingleValue()); + NOTE_EVAL1(addr); + NOTE_EVAL1(value); + auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type); + NOTE_EVAL1(loaded); + auto computed = value.getSingleValue(); + switch (curr->op) { + case RMWAdd: + computed = loaded.add(computed); + break; + case RMWSub: + computed = loaded.sub(computed); + break; + case RMWAnd: + computed = loaded.and_(computed); + break; + case RMWOr: + computed = loaded.or_(computed); + break; + case RMWXor: + computed = loaded.xor_(computed); + break; + case RMWXchg: + break; + } + instance.doAtomicStore(addr, curr->bytes, computed); + return loaded; } - Flow target = self()->visit(curr->target); - if (target.breaking()) { - return target; + Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { + NOTE_ENTER("AtomicCmpxchg"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) { + return ptr; + } + NOTE_EVAL1(ptr); + auto expected = this->visit(curr->expected); + if (expected.breaking()) { + return expected; + } + auto replacement = this->visit(curr->replacement); + if (replacement.breaking()) { + return replacement; + } + auto addr = instance.getFinalAddress(curr, ptr.getSingleValue()); + expected = + Flow(wrapToSmallerSize(expected.getSingleValue(), curr->bytes)); + NOTE_EVAL1(addr); + NOTE_EVAL1(expected); + NOTE_EVAL1(replacement); + auto loaded = instance.doAtomicLoad(addr, curr->bytes, curr->type); + NOTE_EVAL1(loaded); + if (loaded == expected.getSingleValue()) { + instance.doAtomicStore(addr, curr->bytes, replacement.getSingleValue()); + } + return loaded; + } + Flow visitAtomicWait(AtomicWait* curr) { + NOTE_ENTER("AtomicWait"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) { + return ptr; + } + NOTE_EVAL1(ptr); + auto expected = this->visit(curr->expected); + NOTE_EVAL1(expected); + if (expected.breaking()) { + return expected; + } + auto timeout = this->visit(curr->timeout); + NOTE_EVAL1(timeout); + if (timeout.breaking()) { + return timeout; + } + auto bytes = curr->expectedType.getByteSize(); + auto addr = instance.getFinalAddress(curr, ptr.getSingleValue(), bytes); + auto loaded = instance.doAtomicLoad(addr, bytes, curr->expectedType); + NOTE_EVAL1(loaded); + if (loaded != expected.getSingleValue()) { + return Literal(int32_t(1)); // not equal + } + // TODO: add threads support! + // for now, just assume we are woken up + return Literal(int32_t(0)); // woken up + } + Flow visitAtomicNotify(AtomicNotify* curr) { + NOTE_ENTER("AtomicNotify"); + Flow ptr = this->visit(curr->ptr); + if (ptr.breaking()) { + return ptr; + } + NOTE_EVAL1(ptr); + auto count = this->visit(curr->notifyCount); + NOTE_EVAL1(count); + if (count.breaking()) { + return count; + } + auto addr = instance.getFinalAddress(curr, ptr.getSingleValue(), 4); + // Just check TODO actual threads support + instance.checkAtomicAddress(addr, 4); + return Literal(int32_t(0)); // none woken up } - - Index index = target.getSingleValue().geti32(); - Type type = curr->isReturn ? scope->function->getResults() : curr->type; - - auto info = getTableInterfaceInfo(curr->table); - Flow ret = info.interface->callTable( - info.name, index, curr->heapType, arguments, type, *self()); - - // TODO: make this a proper tail call (return first) - if (curr->isReturn) { - ret.breakTo = RETURN_FLOW; + Flow visitSIMDLoad(SIMDLoad* curr) { + NOTE_ENTER("SIMDLoad"); + switch (curr->op) { + case LoadSplatVec8x16: + case LoadSplatVec16x8: + case LoadSplatVec32x4: + case LoadSplatVec64x2: + return visitSIMDLoadSplat(curr); + case LoadExtSVec8x8ToVecI16x8: + case LoadExtUVec8x8ToVecI16x8: + case LoadExtSVec16x4ToVecI32x4: + case LoadExtUVec16x4ToVecI32x4: + case LoadExtSVec32x2ToVecI64x2: + case LoadExtUVec32x2ToVecI64x2: + return visitSIMDLoadExtend(curr); + case Load32Zero: + case Load64Zero: + return visitSIMDLoadZero(curr); + } + WASM_UNREACHABLE("invalid op"); } - return ret; - } - Flow visitCallRef(CallRef* curr) { - NOTE_ENTER("CallRef"); - Literals arguments; - Flow flow = self()->generateArguments(curr->operands, arguments); - if (flow.breaking()) { - return flow; - } - Flow target = self()->visit(curr->target); - if (target.breaking()) { - return target; - } - if (target.getSingleValue().isNull()) { - trap("null target in call_ref"); - } - Name funcName = target.getSingleValue().getFunc(); - auto* func = wasm.getFunction(funcName); - Flow ret; - if (func->imported()) { - ret.values = externalInterface->callImport(func, arguments); - } else { - ret.values = callFunctionInternal(funcName, arguments); - } -#ifdef WASM_INTERPRETER_DEBUG - std::cout << "(returned to " << scope->function->name << ")\n"; -#endif - // TODO: make this a proper tail call (return first) - if (curr->isReturn) { - ret.breakTo = RETURN_FLOW; - } - return ret; - } - - Flow visitTableGet(TableGet* curr) { - NOTE_ENTER("TableGet"); - Flow index = self()->visit(curr->index); - if (index.breaking()) { - return index; - } - auto info = getTableInterfaceInfo(curr->table); - return info.interface->tableLoad(info.name, - index.getSingleValue().geti32()); - } - Flow visitTableSet(TableSet* curr) { - NOTE_ENTER("TableSet"); - Flow indexFlow = self()->visit(curr->index); - if (indexFlow.breaking()) { - return indexFlow; - } - Flow valueFlow = self()->visit(curr->value); - if (valueFlow.breaking()) { - return valueFlow; - } - auto info = getTableInterfaceInfo(curr->table); - info.interface->tableStore(info.name, - indexFlow.getSingleValue().geti32(), - valueFlow.getSingleValue()); - return Flow(); - } - - Flow visitTableSize(TableSize* curr) { - NOTE_ENTER("TableSize"); - auto info = getTableInterfaceInfo(curr->table); - Index tableSize = info.interface->tableSize(curr->table); - return Literal::makeFromInt32(tableSize, Type::i32); - } - - Flow visitTableGrow(TableGrow* curr) { - NOTE_ENTER("TableGrow"); - Flow valueFlow = self()->visit(curr->value); - if (valueFlow.breaking()) { - return valueFlow; - } - Flow deltaFlow = self()->visit(curr->delta); - if (deltaFlow.breaking()) { - return deltaFlow; - } - Name tableName = curr->table; - auto info = getTableInterfaceInfo(tableName); - - Index tableSize = info.interface->tableSize(tableName); - Flow ret = Literal::makeFromInt32(tableSize, Type::i32); - Flow fail = Literal::makeFromInt32(-1, Type::i32); - Index delta = deltaFlow.getSingleValue().geti32(); - - if (tableSize >= uint32_t(-1) - delta) { - return fail; - } - auto maxTableSize = self()->wasm.getTable(tableName)->max; - if (uint64_t(tableSize) + uint64_t(delta) > uint64_t(maxTableSize)) { - return fail; - } - Index newSize = tableSize + delta; - if (!info.interface->growTable( - tableName, valueFlow.getSingleValue(), tableSize, newSize)) { - // We failed to grow the table in practice, even though it was valid - // to try to do so. - return fail; - } - return ret; - } - - Flow visitLocalGet(LocalGet* curr) { - NOTE_ENTER("LocalGet"); - auto index = curr->index; - NOTE_EVAL1(index); - NOTE_EVAL1(scope->locals[index]); - return scope->locals[index]; - } - Flow visitLocalSet(LocalSet* curr) { - NOTE_ENTER("LocalSet"); - auto index = curr->index; - Flow flow = self()->visit(curr->value); - if (flow.breaking()) { - return flow; - } - NOTE_EVAL1(index); - NOTE_EVAL1(flow.getSingleValue()); - assert(curr->isTee() ? Type::isSubType(flow.getType(), curr->type) : true); - scope->locals[index] = flow.values; - return curr->isTee() ? flow : Flow(); - } - - Flow visitGlobalGet(GlobalGet* curr) { - NOTE_ENTER("GlobalGet"); - auto name = curr->name; - NOTE_EVAL1(name); - return getGlobal(name); - } - Flow visitGlobalSet(GlobalSet* curr) { - NOTE_ENTER("GlobalSet"); - auto name = curr->name; - Flow flow = self()->visit(curr->value); - if (flow.breaking()) { - return flow; - } - NOTE_EVAL1(name); - NOTE_EVAL1(flow.getSingleValue()); - - getGlobal(name) = flow.values; - return Flow(); - } - - Flow visitLoad(Load* curr) { - NOTE_ENTER("Load"); - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; - } - NOTE_EVAL1(flow); - auto* inst = getMemoryInstance(); - auto addr = inst->getFinalAddress(curr, flow.getSingleValue()); - if (curr->isAtomic) { - inst->checkAtomicAddress(addr, curr->bytes); - } - auto ret = inst->externalInterface->load(curr, addr); - NOTE_EVAL1(addr); - NOTE_EVAL1(ret); - return ret; - } - Flow visitStore(Store* curr) { - NOTE_ENTER("Store"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } - auto* inst = getMemoryInstance(); - auto addr = inst->getFinalAddress(curr, ptr.getSingleValue()); - if (curr->isAtomic) { - inst->checkAtomicAddress(addr, curr->bytes); - } - NOTE_EVAL1(addr); - NOTE_EVAL1(value); - inst->externalInterface->store(curr, addr, value.getSingleValue()); - return Flow(); - } - - Flow visitAtomicRMW(AtomicRMW* curr) { - NOTE_ENTER("AtomicRMW"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - auto value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } - NOTE_EVAL1(ptr); - auto* inst = getMemoryInstance(); - auto addr = inst->getFinalAddress(curr, ptr.getSingleValue()); - NOTE_EVAL1(addr); - NOTE_EVAL1(value); - auto loaded = inst->doAtomicLoad(addr, curr->bytes, curr->type); - NOTE_EVAL1(loaded); - auto computed = value.getSingleValue(); - switch (curr->op) { - case RMWAdd: - computed = loaded.add(computed); - break; - case RMWSub: - computed = loaded.sub(computed); - break; - case RMWAnd: - computed = loaded.and_(computed); - break; - case RMWOr: - computed = loaded.or_(computed); - break; - case RMWXor: - computed = loaded.xor_(computed); - break; - case RMWXchg: - break; - } - inst->doAtomicStore(addr, curr->bytes, computed); - return loaded; - } - Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { - NOTE_ENTER("AtomicCmpxchg"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - NOTE_EVAL1(ptr); - auto expected = self()->visit(curr->expected); - if (expected.breaking()) { - return expected; - } - auto replacement = self()->visit(curr->replacement); - if (replacement.breaking()) { - return replacement; - } - auto* inst = getMemoryInstance(); - auto addr = inst->getFinalAddress(curr, ptr.getSingleValue()); - expected = Flow(wrapToSmallerSize(expected.getSingleValue(), curr->bytes)); - NOTE_EVAL1(addr); - NOTE_EVAL1(expected); - NOTE_EVAL1(replacement); - auto loaded = inst->doAtomicLoad(addr, curr->bytes, curr->type); - NOTE_EVAL1(loaded); - if (loaded == expected.getSingleValue()) { - inst->doAtomicStore(addr, curr->bytes, replacement.getSingleValue()); - } - return loaded; - } - Flow visitAtomicWait(AtomicWait* curr) { - NOTE_ENTER("AtomicWait"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - NOTE_EVAL1(ptr); - auto expected = self()->visit(curr->expected); - NOTE_EVAL1(expected); - if (expected.breaking()) { - return expected; - } - auto timeout = self()->visit(curr->timeout); - NOTE_EVAL1(timeout); - if (timeout.breaking()) { - return timeout; - } - auto* inst = getMemoryInstance(); - auto bytes = curr->expectedType.getByteSize(); - auto addr = inst->getFinalAddress(curr, ptr.getSingleValue(), bytes); - auto loaded = inst->doAtomicLoad(addr, bytes, curr->expectedType); - NOTE_EVAL1(loaded); - if (loaded != expected.getSingleValue()) { - return Literal(int32_t(1)); // not equal - } - // TODO: add threads support! - // for now, just assume we are woken up - return Literal(int32_t(0)); // woken up - } - Flow visitAtomicNotify(AtomicNotify* curr) { - NOTE_ENTER("AtomicNotify"); - Flow ptr = self()->visit(curr->ptr); - if (ptr.breaking()) { - return ptr; - } - NOTE_EVAL1(ptr); - auto count = self()->visit(curr->notifyCount); - NOTE_EVAL1(count); - if (count.breaking()) { - return count; - } - auto* inst = getMemoryInstance(); - auto addr = inst->getFinalAddress(curr, ptr.getSingleValue(), 4); - // Just check TODO actual threads support - inst->checkAtomicAddress(addr, 4); - return Literal(int32_t(0)); // none woken up - } - Flow visitSIMDLoad(SIMDLoad* curr) { - NOTE_ENTER("SIMDLoad"); - switch (curr->op) { - case Load8SplatVec128: - case Load16SplatVec128: - case Load32SplatVec128: - case Load64SplatVec128: - return visitSIMDLoadSplat(curr); - case Load8x8SVec128: - case Load8x8UVec128: - case Load16x4SVec128: - case Load16x4UVec128: - case Load32x2SVec128: - case Load32x2UVec128: - return visitSIMDLoadExtend(curr); - case Load32ZeroVec128: - case Load64ZeroVec128: - return visitSIMDLoadZero(curr); + Flow visitSIMDLoadSplat(SIMDLoad* curr) { + Load load; + load.type = Type::i32; + load.bytes = curr->getMemBytes(); + load.signed_ = false; + load.offset = curr->offset; + load.align = curr->align; + load.isAtomic = false; + load.ptr = curr->ptr; + Literal (Literal::*splat)() const = nullptr; + switch (curr->op) { + case LoadSplatVec8x16: + splat = &Literal::splatI8x16; + break; + case LoadSplatVec16x8: + splat = &Literal::splatI16x8; + break; + case LoadSplatVec32x4: + splat = &Literal::splatI32x4; + break; + case LoadSplatVec64x2: + load.type = Type::i64; + splat = &Literal::splatI64x2; + break; + default: + WASM_UNREACHABLE("invalid op"); + } + load.finalize(); + Flow flow = this->visit(&load); + if (flow.breaking()) { + return flow; + } + return (flow.getSingleValue().*splat)(); } - WASM_UNREACHABLE("invalid op"); - } - Flow visitSIMDLoadSplat(SIMDLoad* curr) { - Load load; - load.type = Type::i32; - load.bytes = curr->getMemBytes(); - load.signed_ = false; - load.offset = curr->offset; - load.align = curr->align; - load.isAtomic = false; - load.ptr = curr->ptr; - Literal (Literal::*splat)() const = nullptr; - switch (curr->op) { - case Load8SplatVec128: - splat = &Literal::splatI8x16; - break; - case Load16SplatVec128: - splat = &Literal::splatI16x8; - break; - case Load32SplatVec128: - splat = &Literal::splatI32x4; - break; - case Load64SplatVec128: - load.type = Type::i64; - splat = &Literal::splatI64x2; - break; - default: + Flow visitSIMDLoadExtend(SIMDLoad* curr) { + Flow flow = this->visit(curr->ptr); + if (flow.breaking()) { + return flow; + } + NOTE_EVAL1(flow); + Address src(uint32_t(flow.getSingleValue().geti32())); + auto loadLane = [&](Address addr) { + switch (curr->op) { + case LoadExtSVec8x8ToVecI16x8: + return Literal(int32_t(instance.externalInterface->load8s(addr))); + case LoadExtUVec8x8ToVecI16x8: + return Literal(int32_t(instance.externalInterface->load8u(addr))); + case LoadExtSVec16x4ToVecI32x4: + return Literal(int32_t(instance.externalInterface->load16s(addr))); + case LoadExtUVec16x4ToVecI32x4: + return Literal(int32_t(instance.externalInterface->load16u(addr))); + case LoadExtSVec32x2ToVecI64x2: + return Literal(int64_t(instance.externalInterface->load32s(addr))); + case LoadExtUVec32x2ToVecI64x2: + return Literal(int64_t(instance.externalInterface->load32u(addr))); + default: + WASM_UNREACHABLE("unexpected op"); + } WASM_UNREACHABLE("invalid op"); - } - load.finalize(); - Flow flow = self()->visit(&load); - if (flow.breaking()) { - return flow; - } - return (flow.getSingleValue().*splat)(); - } - Flow visitSIMDLoadExtend(SIMDLoad* curr) { - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; - } - NOTE_EVAL1(flow); - Address src(uint32_t(flow.getSingleValue().geti32())); - auto* inst = getMemoryInstance(); - auto loadLane = [&](Address addr) { + }; + auto fillLanes = [&](auto lanes, size_t laneBytes) { + for (auto& lane : lanes) { + lane = loadLane( + instance.getFinalAddress(curr, Literal(uint32_t(src)), laneBytes)); + src = Address(uint32_t(src) + laneBytes); + } + return Literal(lanes); + }; switch (curr->op) { - case Load8x8SVec128: - return Literal(int32_t(inst->externalInterface->load8s(addr))); - case Load8x8UVec128: - return Literal(int32_t(inst->externalInterface->load8u(addr))); - case Load16x4SVec128: - return Literal(int32_t(inst->externalInterface->load16s(addr))); - case Load16x4UVec128: - return Literal(int32_t(inst->externalInterface->load16u(addr))); - case Load32x2SVec128: - return Literal(int64_t(inst->externalInterface->load32s(addr))); - case Load32x2UVec128: - return Literal(int64_t(inst->externalInterface->load32u(addr))); + case LoadExtSVec8x8ToVecI16x8: + case LoadExtUVec8x8ToVecI16x8: { + std::array lanes; + return fillLanes(lanes, 1); + } + case LoadExtSVec16x4ToVecI32x4: + case LoadExtUVec16x4ToVecI32x4: { + std::array lanes; + return fillLanes(lanes, 2); + } + case LoadExtSVec32x2ToVecI64x2: + case LoadExtUVec32x2ToVecI64x2: { + std::array lanes; + return fillLanes(lanes, 4); + } default: WASM_UNREACHABLE("unexpected op"); } WASM_UNREACHABLE("invalid op"); - }; - auto fillLanes = [&](auto lanes, size_t laneBytes) { - for (auto& lane : lanes) { - lane = loadLane( - inst->getFinalAddress(curr, Literal(uint32_t(src)), laneBytes)); - src = Address(uint32_t(src) + laneBytes); + } + Flow visitSIMDLoadZero(SIMDLoad* curr) { + Flow flow = this->visit(curr->ptr); + if (flow.breaking()) { + return flow; } - return Literal(lanes); - }; - switch (curr->op) { - case Load8x8SVec128: - case Load8x8UVec128: { - std::array lanes; - return fillLanes(lanes, 1); - } - case Load16x4SVec128: - case Load16x4UVec128: { - std::array lanes; - return fillLanes(lanes, 2); - } - case Load32x2SVec128: - case Load32x2UVec128: { - std::array lanes; - return fillLanes(lanes, 4); + NOTE_EVAL1(flow); + Address src = instance.getFinalAddress( + curr, flow.getSingleValue(), curr->getMemBytes()); + auto zero = + Literal::makeZero(curr->op == Load32Zero ? Type::i32 : Type::i64); + if (curr->op == Load32Zero) { + auto val = Literal(instance.externalInterface->load32u(src)); + return Literal(std::array{{val, zero, zero, zero}}); + } else { + auto val = Literal(instance.externalInterface->load64u(src)); + return Literal(std::array{{val, zero}}); } - default: - WASM_UNREACHABLE("unexpected op"); - } - WASM_UNREACHABLE("invalid op"); - } - Flow visitSIMDLoadZero(SIMDLoad* curr) { - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; } - NOTE_EVAL1(flow); - auto* inst = getMemoryInstance(); - Address src = - inst->getFinalAddress(curr, flow.getSingleValue(), curr->getMemBytes()); - auto zero = - Literal::makeZero(curr->op == Load32ZeroVec128 ? Type::i32 : Type::i64); - if (curr->op == Load32ZeroVec128) { - auto val = Literal(inst->externalInterface->load32u(src)); - return Literal(std::array{{val, zero, zero, zero}}); - } else { - auto val = Literal(inst->externalInterface->load64u(src)); - return Literal(std::array{{val, zero}}); - } - } - Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { - NOTE_ENTER("SIMDLoadStoreLane"); - Flow flow = self()->visit(curr->ptr); - if (flow.breaking()) { - return flow; - } - NOTE_EVAL1(flow); - auto* inst = getMemoryInstance(); - Address addr = - inst->getFinalAddress(curr, flow.getSingleValue(), curr->getMemBytes()); - flow = self()->visit(curr->vec); - if (flow.breaking()) { - return flow; - } - Literal vec = flow.getSingleValue(); - switch (curr->op) { - case Load8LaneVec128: - case Store8LaneVec128: { - std::array lanes = vec.getLanesUI8x16(); - if (curr->isLoad()) { - lanes[curr->index] = Literal(inst->externalInterface->load8u(addr)); - return Literal(lanes); - } else { - inst->externalInterface->store8(addr, lanes[curr->index].geti32()); - return {}; - } - } - case Load16LaneVec128: - case Store16LaneVec128: { - std::array lanes = vec.getLanesUI16x8(); - if (curr->isLoad()) { - lanes[curr->index] = Literal(inst->externalInterface->load16u(addr)); - return Literal(lanes); - } else { - inst->externalInterface->store16(addr, lanes[curr->index].geti32()); - return {}; - } + Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { + NOTE_ENTER("SIMDLoadStoreLane"); + Flow flow = this->visit(curr->ptr); + if (flow.breaking()) { + return flow; } - case Load32LaneVec128: - case Store32LaneVec128: { - std::array lanes = vec.getLanesI32x4(); - if (curr->isLoad()) { - lanes[curr->index] = Literal(inst->externalInterface->load32u(addr)); - return Literal(lanes); - } else { - inst->externalInterface->store32(addr, lanes[curr->index].geti32()); - return {}; - } + NOTE_EVAL1(flow); + Address addr = instance.getFinalAddress( + curr, flow.getSingleValue(), curr->getMemBytes()); + flow = this->visit(curr->vec); + if (flow.breaking()) { + return flow; } - case Store64LaneVec128: - case Load64LaneVec128: { - std::array lanes = vec.getLanesI64x2(); - if (curr->isLoad()) { - lanes[curr->index] = Literal(inst->externalInterface->load64u(addr)); - return Literal(lanes); - } else { - inst->externalInterface->store64(addr, lanes[curr->index].geti64()); - return {}; + Literal vec = flow.getSingleValue(); + switch (curr->op) { + case LoadLaneVec8x16: + case StoreLaneVec8x16: { + std::array lanes = vec.getLanesUI8x16(); + if (curr->isLoad()) { + lanes[curr->index] = + Literal(instance.externalInterface->load8u(addr)); + return Literal(lanes); + } else { + instance.externalInterface->store8(addr, + lanes[curr->index].geti32()); + return {}; + } } - } - } - WASM_UNREACHABLE("unexpected op"); - } - Flow visitMemorySize(MemorySize* curr) { - NOTE_ENTER("MemorySize"); - auto* inst = getMemoryInstance(); - return Literal::makeFromInt64(inst->memorySize, - inst->wasm.memory.indexType); - } - Flow visitMemoryGrow(MemoryGrow* curr) { - NOTE_ENTER("MemoryGrow"); - auto* inst = getMemoryInstance(); - auto indexType = inst->wasm.memory.indexType; - auto fail = Literal::makeFromInt64(-1, indexType); - Flow flow = self()->visit(curr->delta); - if (flow.breaking()) { - return flow; - } - Flow ret = Literal::makeFromInt64(inst->memorySize, indexType); - uint64_t delta = flow.getSingleValue().getUnsigned(); - if (delta > uint32_t(-1) / Memory::kPageSize && indexType == Type::i32) { - return fail; - } - if (inst->memorySize >= uint32_t(-1) - delta && indexType == Type::i32) { - return fail; - } - auto newSize = inst->memorySize + delta; - if (newSize > inst->wasm.memory.max) { - return fail; - } - if (!inst->externalInterface->growMemory( - inst->memorySize * Memory::kPageSize, newSize * Memory::kPageSize)) { - // We failed to grow the memory in practice, even though it was valid - // to try to do so. - return fail; - } - inst->memorySize = newSize; - return ret; - } - Flow visitMemoryInit(MemoryInit* curr) { - NOTE_ENTER("MemoryInit"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow offset = self()->visit(curr->offset); - if (offset.breaking()) { - return offset; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } - NOTE_EVAL1(dest); - NOTE_EVAL1(offset); - NOTE_EVAL1(size); - - assert(curr->segment < wasm.memory.segments.size()); - Memory::Segment& segment = wasm.memory.segments[curr->segment]; - - Address destVal(dest.getSingleValue().getUnsigned()); - Address offsetVal(uint32_t(offset.getSingleValue().geti32())); - Address sizeVal(uint32_t(size.getSingleValue().geti32())); - - if (offsetVal + sizeVal > 0 && droppedSegments.count(curr->segment)) { - trap("out of bounds segment access in memory.init"); - } - if ((uint64_t)offsetVal + sizeVal > segment.data.size()) { - trap("out of bounds segment access in memory.init"); - } - auto* inst = getMemoryInstance(); - if (destVal + sizeVal > inst->memorySize * Memory::kPageSize) { - trap("out of bounds memory access in memory.init"); - } - for (size_t i = 0; i < sizeVal; ++i) { - Literal addr(destVal + i); - inst->externalInterface->store8( - inst->getFinalAddressWithoutOffset(addr, 1), - segment.data[offsetVal + i]); - } - return {}; - } - Flow visitDataDrop(DataDrop* curr) { - NOTE_ENTER("DataDrop"); - droppedSegments.insert(curr->segment); - return {}; - } - Flow visitMemoryCopy(MemoryCopy* curr) { - NOTE_ENTER("MemoryCopy"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow source = self()->visit(curr->source); - if (source.breaking()) { - return source; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } - NOTE_EVAL1(dest); - NOTE_EVAL1(source); - NOTE_EVAL1(size); - Address destVal(dest.getSingleValue().getUnsigned()); - Address sourceVal(source.getSingleValue().getUnsigned()); - Address sizeVal(size.getSingleValue().getUnsigned()); - - auto* inst = getMemoryInstance(); - if (sourceVal + sizeVal > inst->memorySize * Memory::kPageSize || - destVal + sizeVal > inst->memorySize * Memory::kPageSize || - // FIXME: better/cheaper way to detect wrapping? - sourceVal + sizeVal < sourceVal || sourceVal + sizeVal < sizeVal || - destVal + sizeVal < destVal || destVal + sizeVal < sizeVal) { - trap("out of bounds segment access in memory.copy"); - } - - int64_t start = 0; - int64_t end = sizeVal; - int step = 1; - // Reverse direction if source is below dest - if (sourceVal < destVal) { - start = int64_t(sizeVal) - 1; - end = -1; - step = -1; - } - for (int64_t i = start; i != end; i += step) { - inst->externalInterface->store8( - inst->getFinalAddressWithoutOffset(Literal(destVal + i), 1), - inst->externalInterface->load8s( - inst->getFinalAddressWithoutOffset(Literal(sourceVal + i), 1))); - } - return {}; - } - Flow visitMemoryFill(MemoryFill* curr) { - NOTE_ENTER("MemoryFill"); - Flow dest = self()->visit(curr->dest); - if (dest.breaking()) { - return dest; - } - Flow value = self()->visit(curr->value); - if (value.breaking()) { - return value; - } - Flow size = self()->visit(curr->size); - if (size.breaking()) { - return size; - } - NOTE_EVAL1(dest); - NOTE_EVAL1(value); - NOTE_EVAL1(size); - Address destVal(dest.getSingleValue().getUnsigned()); - Address sizeVal(size.getSingleValue().getUnsigned()); - - auto* inst = getMemoryInstance(); - // FIXME: cheaper wrapping detection? - if (destVal > inst->memorySize * Memory::kPageSize || - sizeVal > inst->memorySize * Memory::kPageSize || - destVal + sizeVal > inst->memorySize * Memory::kPageSize) { - trap("out of bounds memory access in memory.fill"); - } - uint8_t val(value.getSingleValue().geti32()); - for (size_t i = 0; i < sizeVal; ++i) { - inst->externalInterface->store8( - inst->getFinalAddressWithoutOffset(Literal(destVal + i), 1), val); - } - return {}; - } - Flow visitTry(Try* curr) { - NOTE_ENTER("Try"); - try { - return self()->visit(curr->body); - } catch (const WasmException& e) { - // If delegation is in progress and the current try is not the target of - // the delegation, don't handle it and just rethrow. - if (scope->currDelegateTarget.is()) { - if (scope->currDelegateTarget == curr->name) { - scope->currDelegateTarget.clear(); - } else { - throw; + case LoadLaneVec16x8: + case StoreLaneVec16x8: { + std::array lanes = vec.getLanesUI16x8(); + if (curr->isLoad()) { + lanes[curr->index] = + Literal(instance.externalInterface->load16u(addr)); + return Literal(lanes); + } else { + instance.externalInterface->store16(addr, + lanes[curr->index].geti32()); + return {}; + } } - } - - auto processCatchBody = [&](Expression* catchBody) { - // Push the current exception onto the exceptionStack in case - // 'rethrow's use it - exceptionStack.push_back(std::make_pair(e, curr->name)); - // We need to pop exceptionStack in either case: when the catch body - // exits normally or when a new exception is thrown - Flow ret; - try { - ret = self()->visit(catchBody); - } catch (const WasmException&) { - exceptionStack.pop_back(); - throw; + case LoadLaneVec32x4: + case StoreLaneVec32x4: { + std::array lanes = vec.getLanesI32x4(); + if (curr->isLoad()) { + lanes[curr->index] = + Literal(instance.externalInterface->load32u(addr)); + return Literal(lanes); + } else { + instance.externalInterface->store32(addr, + lanes[curr->index].geti32()); + return {}; + } } - exceptionStack.pop_back(); - return ret; - }; - - for (size_t i = 0; i < curr->catchTags.size(); i++) { - if (curr->catchTags[i] == e.tag) { - multiValues.push_back(e.values); - return processCatchBody(curr->catchBodies[i]); + case StoreLaneVec64x2: + case LoadLaneVec64x2: { + std::array lanes = vec.getLanesI64x2(); + if (curr->isLoad()) { + lanes[curr->index] = + Literal(instance.externalInterface->load64u(addr)); + return Literal(lanes); + } else { + instance.externalInterface->store64(addr, + lanes[curr->index].geti64()); + return {}; + } } } - if (curr->hasCatchAll()) { - return processCatchBody(curr->catchBodies.back()); - } - if (curr->isDelegate()) { - scope->currDelegateTarget = curr->delegateTarget; - } - // This exception is not caught by this try-catch. Rethrow it. - throw; + WASM_UNREACHABLE("unexpected op"); } - } - Flow visitRethrow(Rethrow* curr) { - for (int i = exceptionStack.size() - 1; i >= 0; i--) { - if (exceptionStack[i].second == curr->target) { - throwException(exceptionStack[i].first); + Flow visitMemorySize(MemorySize* curr) { + NOTE_ENTER("MemorySize"); + return Literal::makeFromInt64(instance.memorySize, + instance.wasm.memory.indexType); + } + Flow visitMemoryGrow(MemoryGrow* curr) { + NOTE_ENTER("MemoryGrow"); + auto indexType = instance.wasm.memory.indexType; + auto fail = Literal::makeFromInt64(-1, indexType); + Flow flow = this->visit(curr->delta); + if (flow.breaking()) { + return flow; } - } - WASM_UNREACHABLE("rethrow"); - } - Flow visitPop(Pop* curr) { - NOTE_ENTER("Pop"); - assert(!multiValues.empty()); - auto ret = multiValues.back(); - assert(curr->type == ret.getType()); - multiValues.pop_back(); - return ret; - } - - void trap(const char* why) override { externalInterface->trap(why); } - - void hostLimit(const char* why) override { - externalInterface->hostLimit(why); - } - - void throwException(const WasmException& exn) override { - externalInterface->throwException(exn); - } - - // Given a value, wrap it to a smaller given number of bytes. - Literal wrapToSmallerSize(Literal value, Index bytes) { - if (value.type == Type::i32) { - switch (bytes) { - case 1: { - return value.and_(Literal(uint32_t(0xff))); - } - case 2: { - return value.and_(Literal(uint32_t(0xffff))); - } - case 4: { - break; - } - default: - WASM_UNREACHABLE("unexpected bytes"); + Flow ret = Literal::makeFromInt64(instance.memorySize, indexType); + uint64_t delta = flow.getSingleValue().getUnsigned(); + if (delta > uint32_t(-1) / Memory::kPageSize && indexType == Type::i32) { + return fail; + } + if (instance.memorySize >= uint32_t(-1) - delta && + indexType == Type::i32) { + return fail; + } + auto newSize = instance.memorySize + delta; + if (newSize > instance.wasm.memory.max) { + return fail; + } + if (!instance.externalInterface->growMemory( + instance.memorySize * Memory::kPageSize, + newSize * Memory::kPageSize)) { + // We failed to grow the memory in practice, even though it was valid + // to try to do so. + return fail; + } + instance.memorySize = newSize; + return ret; + } + Flow visitMemoryInit(MemoryInit* curr) { + NOTE_ENTER("MemoryInit"); + Flow dest = this->visit(curr->dest); + if (dest.breaking()) { + return dest; + } + Flow offset = this->visit(curr->offset); + if (offset.breaking()) { + return offset; + } + Flow size = this->visit(curr->size); + if (size.breaking()) { + return size; + } + NOTE_EVAL1(dest); + NOTE_EVAL1(offset); + NOTE_EVAL1(size); + + assert(curr->segment < instance.wasm.memory.segments.size()); + Memory::Segment& segment = instance.wasm.memory.segments[curr->segment]; + + Address destVal(dest.getSingleValue().getUnsigned()); + Address offsetVal(uint32_t(offset.getSingleValue().geti32())); + Address sizeVal(uint32_t(size.getSingleValue().geti32())); + + if (offsetVal + sizeVal > 0 && + instance.droppedSegments.count(curr->segment)) { + trap("out of bounds segment access in memory.init"); + } + if ((uint64_t)offsetVal + sizeVal > segment.data.size()) { + trap("out of bounds segment access in memory.init"); + } + if (destVal + sizeVal > instance.memorySize * Memory::kPageSize) { + trap("out of bounds memory access in memory.init"); + } + for (size_t i = 0; i < sizeVal; ++i) { + Literal addr(destVal + i); + instance.externalInterface->store8( + instance.getFinalAddressWithoutOffset(addr, 1), + segment.data[offsetVal + i]); + } + return {}; + } + Flow visitDataDrop(DataDrop* curr) { + NOTE_ENTER("DataDrop"); + instance.droppedSegments.insert(curr->segment); + return {}; + } + Flow visitMemoryCopy(MemoryCopy* curr) { + NOTE_ENTER("MemoryCopy"); + Flow dest = this->visit(curr->dest); + if (dest.breaking()) { + return dest; + } + Flow source = this->visit(curr->source); + if (source.breaking()) { + return source; + } + Flow size = this->visit(curr->size); + if (size.breaking()) { + return size; + } + NOTE_EVAL1(dest); + NOTE_EVAL1(source); + NOTE_EVAL1(size); + Address destVal(dest.getSingleValue().getUnsigned()); + Address sourceVal(source.getSingleValue().getUnsigned()); + Address sizeVal(size.getSingleValue().getUnsigned()); + + if (sourceVal + sizeVal > instance.memorySize * Memory::kPageSize || + destVal + sizeVal > instance.memorySize * Memory::kPageSize || + // FIXME: better/cheaper way to detect wrapping? + sourceVal + sizeVal < sourceVal || sourceVal + sizeVal < sizeVal || + destVal + sizeVal < destVal || destVal + sizeVal < sizeVal) { + trap("out of bounds segment access in memory.copy"); + } + + int64_t start = 0; + int64_t end = sizeVal; + int step = 1; + // Reverse direction if source is below dest + if (sourceVal < destVal) { + start = int64_t(sizeVal) - 1; + end = -1; + step = -1; + } + for (int64_t i = start; i != end; i += step) { + instance.externalInterface->store8( + instance.getFinalAddressWithoutOffset(Literal(destVal + i), 1), + instance.externalInterface->load8s( + instance.getFinalAddressWithoutOffset(Literal(sourceVal + i), 1))); + } + return {}; + } + Flow visitMemoryFill(MemoryFill* curr) { + NOTE_ENTER("MemoryFill"); + Flow dest = this->visit(curr->dest); + if (dest.breaking()) { + return dest; } - } else { - assert(value.type == Type::i64); - switch (bytes) { - case 1: { - return value.and_(Literal(uint64_t(0xff))); - } - case 2: { - return value.and_(Literal(uint64_t(0xffff))); - } - case 4: { - return value.and_(Literal(uint64_t(0xffffffffUL))); + Flow value = this->visit(curr->value); + if (value.breaking()) { + return value; + } + Flow size = this->visit(curr->size); + if (size.breaking()) { + return size; + } + NOTE_EVAL1(dest); + NOTE_EVAL1(value); + NOTE_EVAL1(size); + Address destVal(dest.getSingleValue().getUnsigned()); + Address sizeVal(size.getSingleValue().getUnsigned()); + + // FIXME: cheaper wrapping detection? + if (destVal > instance.memorySize * Memory::kPageSize || + sizeVal > instance.memorySize * Memory::kPageSize || + destVal + sizeVal > instance.memorySize * Memory::kPageSize) { + trap("out of bounds memory access in memory.fill"); + } + uint8_t val(value.getSingleValue().geti32()); + for (size_t i = 0; i < sizeVal; ++i) { + instance.externalInterface->store8( + instance.getFinalAddressWithoutOffset(Literal(destVal + i), 1), val); + } + return {}; + } + Flow visitTry(Try* curr) { + NOTE_ENTER("Try"); + try { + return this->visit(curr->body); + } catch (const WasmException& e) { + instance.multiValues.push_back(e.exn); + return this->visit(curr->catchBody); + } + } + Flow visitPop(Pop* curr) { + NOTE_ENTER("Pop"); + assert(!instance.multiValues.empty()); + auto ret = instance.multiValues.back(); + instance.multiValues.pop_back(); + return ret; + } + + void trap(const char* why) override { + instance.externalInterface->trap(why); + } + + void throwException(Literal exn) override { + instance.externalInterface->throwException(exn); + } + + // Given a value, wrap it to a smaller given number of bytes. + Literal wrapToSmallerSize(Literal value, Index bytes) { + if (value.type == Type::i32) { + switch (bytes) { + case 1: { + return value.and_(Literal(uint32_t(0xff))); + } + case 2: { + return value.and_(Literal(uint32_t(0xffff))); + } + case 4: { + break; + } + default: + WASM_UNREACHABLE("unexpected bytes"); } - case 8: { - break; + } else { + assert(value.type == Type::i64); + switch (bytes) { + case 1: { + return value.and_(Literal(uint64_t(0xff))); + } + case 2: { + return value.and_(Literal(uint64_t(0xffff))); + } + case 4: { + return value.and_(Literal(uint64_t(0xffffffffUL))); + } + case 8: { + break; + } + default: + WASM_UNREACHABLE("unexpected bytes"); } - default: - WASM_UNREACHABLE("unexpected bytes"); } + return value; } - return value; - } + }; +public: // Call a function, starting an invocation. - Literals callFunction(Name name, const Literals& arguments) { + Literals callFunction(Name name, const LiteralList& arguments) { // if the last call ended in a jump up the stack, it might have left stuff // for us to clean up here callDepth = 0; @@ -3540,7 +3010,7 @@ // Internal function call. Must be public so that callTable implementations // can use it (refactor?) - Literals callFunctionInternal(Name name, const Literals& arguments) { + Literals callFunctionInternal(Name name, const LiteralList& arguments) { if (callDepth > maxDepth) { externalInterface->trap("stack limit"); } @@ -3551,7 +3021,7 @@ Function* function = wasm.getFunction(name); assert(function); - FunctionScope scope(function, arguments, *self()); + FunctionScope scope(function, arguments); #ifdef WASM_INTERPRETER_DEBUG std::cout << "entering " << function->name << "\n with arguments:\n"; @@ -3560,20 +3030,20 @@ } #endif - Flow flow = self()->visit(function->body); + Flow flow = + RuntimeExpressionRunner(*this, scope, maxDepth).visit(function->body); // cannot still be breaking, it means we missed our stop assert(!flow.breaking() || flow.breakTo == RETURN_FLOW); auto type = flow.getType(); - if (!Type::isSubType(type, function->getResults())) { + if (!Type::isSubType(type, function->sig.results)) { std::cerr << "calling " << function->name << " resulted in " << type - << " but the function type is " << function->getResults() + << " but the function type is " << function->sig.results << '\n'; WASM_UNREACHABLE("unexpected result type"); } // may decrease more than one, if we jumped up the stack callDepth = previousCallDepth; // if we jumped up the stack, we also need to pop higher frames - // TODO can FunctionScope handle this automatically? while (functionStack.size() > previousFunctionStackSize) { functionStack.pop_back(); } @@ -3584,12 +3054,11 @@ return flow.values; } - // The maximum call stack depth to evaluate into. - static const Index maxDepth = 250; - protected: Address memorySize; // in pages + static const Index maxDepth = 250; + void trapIfGt(uint64_t lhs, uint64_t rhs, const char* msg) { if (lhs > rhs) { std::stringstream ss; @@ -3671,16 +3140,15 @@ } ExternalInterface* externalInterface; - std::map> linkedInstances; }; -class ModuleRunner : public ModuleRunnerBase { +// The default ModuleInstance uses a trivial global manager +using TrivialGlobalManager = std::map; +class ModuleInstance + : public ModuleInstanceBase { public: - ModuleRunner( - Module& wasm, - ExternalInterface* externalInterface, - std::map> linkedInstances = {}) - : ModuleRunnerBase(wasm, externalInterface, linkedInstances) {} + ModuleInstance(Module& wasm, ExternalInterface* externalInterface) + : ModuleInstanceBase(wasm, externalInterface) {} }; } // namespace wasm diff -Nru binaryen-108/src/wasm-io.h binaryen-99/src/wasm-io.h --- binaryen-108/src/wasm-io.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-io.h 2021-01-07 20:01:06.000000000 +0000 @@ -27,32 +27,14 @@ namespace wasm { -class ModuleIOBase { -protected: - bool debugInfo; - +class ModuleReader { public: - // Whether we support debug info (the names section). - void setDebugInfo(bool debugInfo_) { debugInfo = debugInfo_; } -}; - -class ModuleReader : public ModuleIOBase { -public: - // Reading defaults to loading the names section. Name section info is used in - // various internal ways that we do not opt-in to currently. - ModuleReader() { setDebugInfo(true); } - // If DWARF support is enabled, we track the locations of all IR nodes in // the binary, so that we can update DWARF sections later when writing. void setDWARF(bool DWARF_) { DWARF = DWARF_; } void setProfile(IRProfile profile_) { profile = profile_; } - // TODO: add support for this in the text format as well - void setSkipFunctionBodies(bool skipFunctionBodies_) { - skipFunctionBodies = skipFunctionBodies_; - } - // read text void readText(std::string filename, Module& wasm); // read binary @@ -71,8 +53,6 @@ IRProfile profile = IRProfile::Normal; - bool skipFunctionBodies = false; - void readStdin(Module& wasm, std::string sourceMapFilename); void readBinaryData(std::vector& input, @@ -80,22 +60,16 @@ std::string sourceMapFilename); }; -class ModuleWriter : public ModuleIOBase { +class ModuleWriter { bool binary = true; - - // TODO: Remove `emitModuleName`. See the comment in wasm-binary.h - bool emitModuleName = false; - + bool debugInfo = false; std::string symbolMap; std::string sourceMapFilename; std::string sourceMapUrl; public: - // Writing defaults to not storing the names section. Storing it is a user- - // observable fact that must be opted into. - ModuleWriter() { setDebugInfo(false); } - void setBinary(bool binary_) { binary = binary_; } + void setDebugInfo(bool debugInfo_) { debugInfo = debugInfo_; } void setSymbolMap(std::string symbolMap_) { symbolMap = symbolMap_; } void setSourceMapFilename(std::string sourceMapFilename_) { sourceMapFilename = sourceMapFilename_; @@ -103,7 +77,6 @@ void setSourceMapUrl(std::string sourceMapUrl_) { sourceMapUrl = sourceMapUrl_; } - void setEmitModuleName(bool set) { emitModuleName = set; } // write text void writeText(Module& wasm, Output& output); diff -Nru binaryen-108/src/wasm-module-building.h binaryen-99/src/wasm-module-building.h --- binaryen-108/src/wasm-module-building.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-module-building.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,7 +17,6 @@ #ifndef wasm_wasm_module_building_h #define wasm_wasm_module_building_h -#include "pass.h" #include #include diff -Nru binaryen-108/src/wasm-s-parser.h binaryen-99/src/wasm-s-parser.h --- binaryen-108/src/wasm-s-parser.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-s-parser.h 2021-01-07 20:01:06.000000000 +0000 @@ -70,8 +70,6 @@ List& list(); Element* operator[](unsigned i); size_t size() { return list().size(); } - List::Iterator begin() { return list().begin(); } - List::Iterator end() { return list().end(); } // string methods cashew::IString str() const; @@ -125,33 +123,22 @@ std::unordered_map typeIndices; std::vector functionNames; - std::vector tableNames; std::vector globalNames; - std::vector tagNames; + std::vector eventNames; int functionCounter = 0; int globalCounter = 0; - int tagCounter = 0; + int eventCounter = 0; int tableCounter = 0; - int elemCounter = 0; int memoryCounter = 0; // we need to know function return types before we parse their contents - std::map functionTypes; + std::map functionSignatures; std::unordered_map debugInfoFileIndices; - // Maps type indexes to a mapping of field index => name. This is not the same - // as the field names stored on the wasm object, as that maps types after - // their canonicalization. Canonicalization loses information, which means - // that structurally identical types cannot have different names. However, - // while parsing the text format we keep this mapping of type indexes to names - // which does allow reading such content. - std::unordered_map> fieldNames; - public: // Assumes control of and modifies the input. SExpressionWasmBuilder(Module& wasm, Element& module, IRProfile profile); private: - void preParseHeapTypes(Element& module); // pre-parse types and function definitions, so we know function return types // before parsing their contents void preParseFunctionType(Element& s); @@ -166,9 +153,8 @@ UniqueNameMapper nameMapper; Name getFunctionName(Element& s); - Name getTableName(Element& s); Name getGlobalName(Element& s); - Name getTagName(Element& s); + Name getEventName(Element& s); void parseStart(Element& s) { wasm.addStart(getFunctionName(*s[1])); } // returns the next index in s @@ -191,7 +177,6 @@ bool isType(cashew::IString str) { return stringToType(str, true) != Type::none; } - HeapType getFunctionType(Name name, Element& s); public: Expression* parseExpression(Element* s) { return parseExpression(*s); } @@ -235,6 +220,7 @@ Expression* makeSIMDShift(Element& s, SIMDShiftOp op); Expression* makeSIMDLoad(Element& s, SIMDLoadOp op); Expression* makeSIMDLoadStoreLane(Element& s, SIMDLoadStoreLaneOp op); + Expression* makePrefetch(Element& s, PrefetchOp op); Expression* makeMemoryInit(Element& s); Expression* makeDataDrop(Element& s); Expression* makeMemoryCopy(Element& s); @@ -246,62 +232,44 @@ Expression* makeLoop(Element& s); Expression* makeCall(Element& s, bool isReturn); Expression* makeCallIndirect(Element& s, bool isReturn); - template void parseOperands(Element& s, Index i, Index j, T& list) { + template + void parseCallOperands(Element& s, Index i, Index j, T* call) { while (i < j) { - list.push_back(parseExpression(s[i])); + call->operands.push_back(parseExpression(s[i])); i++; } } - template - void parseCallOperands(Element& s, Index i, Index j, T* call) { - parseOperands(s, i, j, call->operands); - } - enum class LabelType { Break, Exception }; - Name getLabel(Element& s, LabelType labelType = LabelType::Break); + Name getLabel(Element& s); Expression* makeBreak(Element& s); Expression* makeBreakTable(Element& s); Expression* makeReturn(Element& s); Expression* makeRefNull(Element& s); - Expression* makeRefIs(Element& s, RefIsOp op); + Expression* makeRefIsNull(Element& s); Expression* makeRefFunc(Element& s); Expression* makeRefEq(Element& s); - Expression* makeTableGet(Element& s); - Expression* makeTableSet(Element& s); - Expression* makeTableSize(Element& s); - Expression* makeTableGrow(Element& s); Expression* makeTry(Element& s); Expression* makeTryOrCatchBody(Element& s, Type type, bool isTry); Expression* makeThrow(Element& s); Expression* makeRethrow(Element& s); + Expression* makeBrOnExn(Element& s); Expression* makeTupleMake(Element& s); Expression* makeTupleExtract(Element& s); Expression* makeCallRef(Element& s, bool isReturn); Expression* makeI31New(Element& s); Expression* makeI31Get(Element& s, bool signed_); Expression* makeRefTest(Element& s); - Expression* makeRefTestStatic(Element& s); Expression* makeRefCast(Element& s); - Expression* makeRefCastStatic(Element& s); - Expression* makeRefCastNopStatic(Element& s); - Expression* makeBrOn(Element& s, BrOnOp op); - Expression* makeBrOnStatic(Element& s, BrOnOp op); + Expression* makeBrOnCast(Element& s); Expression* makeRttCanon(Element& s); Expression* makeRttSub(Element& s); - Expression* makeRttFreshSub(Element& s); Expression* makeStructNew(Element& s, bool default_); - Expression* makeStructNewStatic(Element& s, bool default_); - Index getStructIndex(Element& type, Element& field); + Index getStructIndex(const HeapType& type, Element& s); Expression* makeStructGet(Element& s, bool signed_ = false); Expression* makeStructSet(Element& s); Expression* makeArrayNew(Element& s, bool default_); - Expression* makeArrayNewStatic(Element& s, bool default_); - Expression* makeArrayInit(Element& s); - Expression* makeArrayInitStatic(Element& s); Expression* makeArrayGet(Element& s, bool signed_ = false); Expression* makeArraySet(Element& s); Expression* makeArrayLen(Element& s); - Expression* makeArrayCopy(Element& s); - Expression* makeRefAs(Element& s, RefAsOp op); // Helper functions Type parseOptionalResultType(Element& s, Index& i); @@ -310,12 +278,13 @@ std::vector parseParamOrLocal(Element& s); std::vector parseParamOrLocal(Element& s, size_t& localIndex); std::vector parseResults(Element& s); - HeapType parseTypeRef(Element& s); + Signature parseTypeRef(Element& s); size_t parseTypeUse(Element& s, size_t startPos, - HeapType& functionType, + Signature& functionSignature, std::vector& namedParams); - size_t parseTypeUse(Element& s, size_t startPos, HeapType& functionType); + size_t + parseTypeUse(Element& s, size_t startPos, Signature& functionSignature); void stringToBinary(const char* input, size_t size, std::vector& data); void parseMemory(Element& s, bool preParseImport = false); @@ -326,16 +295,14 @@ void parseImport(Element& s); void parseGlobal(Element& s, bool preParseImport = false); void parseTable(Element& s, bool preParseImport = false); - void parseElem(Element& s, Table* table = nullptr); - ElementSegment* parseElemFinish(Element& s, - std::unique_ptr& segment, - Index i = 1, - bool usesExpressions = false); + void parseElem(Element& s); + void parseInnerElem(Element& s, Index i = 1, Expression* offset = nullptr); // Parses something like (func ..), (array ..), (struct) HeapType parseHeapType(Element& s); - void parseTag(Element& s, bool preParseImport = false); + void parseType(Element& s); + void parseEvent(Element& s, bool preParseImport = false); Function::DebugLocation getDebugLocation(const SourceLocation& loc); diff -Nru binaryen-108/src/wasm-stack.h binaryen-99/src/wasm-stack.h --- binaryen-108/src/wasm-stack.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-stack.h 2021-01-07 20:01:06.000000000 +0000 @@ -20,7 +20,6 @@ #include "ir/branch-utils.h" #include "ir/properties.h" #include "pass.h" -#include "support/insert_ordered.h" #include "wasm-binary.h" #include "wasm-traversal.h" #include "wasm.h" @@ -71,8 +70,6 @@ LoopEnd, // the ending of a loop TryBegin, // the beginning of a try Catch, // the catch within a try - CatchAll, // the catch_all within a try - Delegate, // the delegate within a try TryEnd // the ending of a try } op; @@ -105,13 +102,11 @@ #define DELEGATE(CLASS_TO_VISIT) \ void visit##CLASS_TO_VISIT(CLASS_TO_VISIT* curr); -#include "wasm-delegations.def" +#include "wasm-delegations.h" void emitResultType(Type type); void emitIfElse(If* curr); - void emitCatch(Try* curr, Index i); - void emitCatchAll(Try* curr); - void emitDelegate(Try* curr); + void emitCatch(Try* curr); // emit an end at the end of a block/loop/if/try void emitScopeEnd(Expression* curr); // emit an end at the end of a function @@ -119,8 +114,6 @@ void emitUnreachable(); void mapLocalsAndEmitHeader(); - MappedLocals mappedLocals; - private: void emitMemoryAccess(size_t alignment, size_t bytes, uint32_t offset); int32_t getBreakIndex(Name name); @@ -133,16 +126,14 @@ std::vector breakStack; - // The types of locals in the compact form, in order. - std::vector localTypes; // type => number of locals of that type in the compact form - std::unordered_map numLocalsByType; - - void noteLocalType(Type type); + std::map numLocalsByType; + // (local index, tuple index) => binary local index + std::map, size_t> mappedLocals; // Keeps track of the binary index of the scratch locals used to lower // tuple.extract. - InsertOrderedMap scratchLocals; + std::map scratchLocals; void countScratchLocals(); void setScratchLocals(); }; @@ -170,15 +161,7 @@ void emit(Expression* curr) { static_cast(this)->emit(curr); } void emitHeader() { static_cast(this)->emitHeader(); } void emitIfElse(If* curr) { static_cast(this)->emitIfElse(curr); } - void emitCatch(Try* curr, Index i) { - static_cast(this)->emitCatch(curr, i); - } - void emitCatchAll(Try* curr) { - static_cast(this)->emitCatchAll(curr); - } - void emitDelegate(Try* curr) { - static_cast(this)->emitDelegate(curr); - } + void emitCatch(Try* curr) { static_cast(this)->emitCatch(curr); } void emitScopeEnd(Expression* curr) { static_cast(this)->emitScopeEnd(curr); } @@ -345,21 +328,9 @@ template void BinaryenIRWriter::visitTry(Try* curr) { emit(curr); visitPossibleBlockContents(curr->body); - for (Index i = 0; i < curr->catchTags.size(); i++) { - emitCatch(curr, i); - visitPossibleBlockContents(curr->catchBodies[i]); - } - if (curr->hasCatchAll()) { - emitCatchAll(curr); - visitPossibleBlockContents(curr->catchBodies.back()); - } - if (curr->isDelegate()) { - emitDelegate(curr); - // Note that when we emit a delegate we do not need to also emit a scope - // ending, as the delegate ends the scope. - } else { - emitScopeEnd(curr); - } + emitCatch(curr); + visitPossibleBlockContents(curr->catchBody); + emitScopeEnd(curr); if (curr->type == Type::unreachable) { emitUnreachable(); } @@ -389,9 +360,7 @@ writer.mapLocalsAndEmitHeader(); } void emitIfElse(If* curr) { writer.emitIfElse(curr); } - void emitCatch(Try* curr, Index i) { writer.emitCatch(curr, i); } - void emitCatchAll(Try* curr) { writer.emitCatchAll(curr); } - void emitDelegate(Try* curr) { writer.emitDelegate(curr); } + void emitCatch(Try* curr) { writer.emitCatch(curr); } void emitScopeEnd(Expression* curr) { writer.emitScopeEnd(curr); } void emitFunctionEnd() { if (func->epilogLocation.size()) { @@ -406,8 +375,6 @@ } } - MappedLocals& getMappedLocals() { return writer.mappedLocals; } - private: WasmBinaryWriter& parent; BinaryInstWriter writer; @@ -427,15 +394,9 @@ void emitIfElse(If* curr) { stackIR.push_back(makeStackInst(StackInst::IfElse, curr)); } - void emitCatch(Try* curr, Index i) { + void emitCatch(Try* curr) { stackIR.push_back(makeStackInst(StackInst::Catch, curr)); } - void emitCatchAll(Try* curr) { - stackIR.push_back(makeStackInst(StackInst::CatchAll, curr)); - } - void emitDelegate(Try* curr) { - stackIR.push_back(makeStackInst(StackInst::Delegate, curr)); - } void emitFunctionEnd() {} void emitUnreachable() { stackIR.push_back(makeStackInst(Builder(module).makeUnreachable())); @@ -465,8 +426,6 @@ void write(); - MappedLocals& getMappedLocals() { return writer.mappedLocals; } - private: BinaryInstWriter writer; Function* func; diff -Nru binaryen-108/src/wasm-traversal.h binaryen-99/src/wasm-traversal.h --- binaryen-108/src/wasm-traversal.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-traversal.h 2021-01-07 20:01:06.000000000 +0000 @@ -41,16 +41,15 @@ ReturnType visit##CLASS_TO_VISIT(CLASS_TO_VISIT* curr) { \ return ReturnType(); \ } -#include "wasm-delegations.def" +#include "wasm-delegations.h" // Module-level visitors ReturnType visitExport(Export* curr) { return ReturnType(); } ReturnType visitGlobal(Global* curr) { return ReturnType(); } ReturnType visitFunction(Function* curr) { return ReturnType(); } ReturnType visitTable(Table* curr) { return ReturnType(); } - ReturnType visitElementSegment(ElementSegment* curr) { return ReturnType(); } ReturnType visitMemory(Memory* curr) { return ReturnType(); } - ReturnType visitTag(Tag* curr) { return ReturnType(); } + ReturnType visitEvent(Event* curr) { return ReturnType(); } ReturnType visitModule(Module* curr) { return ReturnType(); } ReturnType visit(Expression* curr) { @@ -62,7 +61,7 @@ return static_cast(this)->visit##CLASS_TO_VISIT( \ static_cast(curr)) -#include "wasm-delegations.def" +#include "wasm-delegations.h" default: WASM_UNREACHABLE("unexpected expression type"); @@ -84,7 +83,7 @@ WASM_UNREACHABLE("Derived class must implement visit" #CLASS_TO_VISIT); \ } -#include "wasm-delegations.def" +#include "wasm-delegations.h" ReturnType visit(Expression* curr) { assert(curr); @@ -95,7 +94,7 @@ return static_cast(this)->visit##CLASS_TO_VISIT( \ static_cast(curr)) -#include "wasm-delegations.def" +#include "wasm-delegations.h" default: WASM_UNREACHABLE("unexpected expression type"); @@ -117,7 +116,7 @@ return static_cast(this)->visitExpression(curr); \ } -#include "wasm-delegations.def" +#include "wasm-delegations.h" }; // @@ -176,7 +175,9 @@ setFunction(nullptr); } - void walkTag(Tag* tag) { static_cast(this)->visitTag(tag); } + void walkEvent(Event* event) { + static_cast(this)->visitEvent(event); + } void walkFunctionInModule(Function* func, Module* module) { setModule(module); @@ -190,17 +191,10 @@ // override this to provide custom functionality void doWalkFunction(Function* func) { walk(func->body); } - void walkElementSegment(ElementSegment* segment) { - if (segment->table.is()) { - walk(segment->offset); - } - for (auto* expr : segment->data) { - walk(expr); - } - static_cast(this)->visitElementSegment(segment); - } - void walkTable(Table* table) { + for (auto& segment : table->segments) { + walk(segment.offset); + } static_cast(this)->visitTable(table); } @@ -241,41 +235,17 @@ self->walkFunction(curr.get()); } } - for (auto& curr : module->tags) { + for (auto& curr : module->events) { if (curr->imported()) { - self->visitTag(curr.get()); + self->visitEvent(curr.get()); } else { - self->walkTag(curr.get()); + self->walkEvent(curr.get()); } } - for (auto& curr : module->tables) { - self->walkTable(curr.get()); - } - for (auto& curr : module->elementSegments) { - self->walkElementSegment(curr.get()); - } + self->walkTable(&module->table); self->walkMemory(&module->memory); } - // Walks module-level code, that is, code that is not in functions. - void walkModuleCode(Module* module) { - // Dispatch statically through the SubType. - SubType* self = static_cast(this); - for (auto& curr : module->globals) { - if (!curr->imported()) { - self->walk(curr->init); - } - } - for (auto& curr : module->elementSegments) { - if (curr->offset) { - self->walk(curr->offset); - } - for (auto* item : curr->data) { - self->walk(item); - } - } - } - // Walk implementation. We don't use recursion as ASTs may be highly // nested. @@ -325,7 +295,7 @@ self->visit##CLASS_TO_VISIT((*currp)->cast()); \ } -#include "wasm-delegations.def" +#include "wasm-delegations.h" void setModule(Module* module) { currModule = module; } @@ -355,27 +325,26 @@ auto* cast = curr->cast(); \ WASM_UNUSED(cast); -#define DELEGATE_GET_FIELD(id, field) cast->field +#define DELEGATE_GET_FIELD(id, name) cast->name -#define DELEGATE_FIELD_CHILD(id, field) \ - self->pushTask(SubType::scan, &cast->field); +#define DELEGATE_FIELD_CHILD(id, name) \ + self->pushTask(SubType::scan, &cast->name); -#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field) \ - self->maybePushTask(SubType::scan, &cast->field); +#define DELEGATE_FIELD_OPTIONAL_CHILD(id, name) \ + self->maybePushTask(SubType::scan, &cast->name); -#define DELEGATE_FIELD_INT(id, field) -#define DELEGATE_FIELD_INT_ARRAY(id, field) -#define DELEGATE_FIELD_LITERAL(id, field) -#define DELEGATE_FIELD_NAME(id, field) -#define DELEGATE_FIELD_NAME_VECTOR(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) -#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) -#define DELEGATE_FIELD_TYPE(id, field) -#define DELEGATE_FIELD_HEAPTYPE(id, field) -#define DELEGATE_FIELD_ADDRESS(id, field) +#define DELEGATE_FIELD_INT(id, name) +#define DELEGATE_FIELD_INT_ARRAY(id, name) +#define DELEGATE_FIELD_LITERAL(id, name) +#define DELEGATE_FIELD_NAME(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_USE(id, name) +#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, name) +#define DELEGATE_FIELD_SIGNATURE(id, name) +#define DELEGATE_FIELD_TYPE(id, name) +#define DELEGATE_FIELD_ADDRESS(id, name) -#include "wasm-delegations-fields.def" +#include "wasm-delegations-fields.h" } }; @@ -519,6 +488,123 @@ } }; +// Traversal in the order of execution. This is quick and simple, but +// does not provide the same comprehensive information that a full +// conversion to basic blocks would. What it does give is a quick +// way to view straightline execution traces, i.e., that have no +// branching. This can let optimizations get most of what they +// want without the cost of creating another AST. +// +// When execution is no longer linear, this notifies via a call +// to noteNonLinear(). + +template> +struct LinearExecutionWalker : public PostWalker { + LinearExecutionWalker() = default; + + // subclasses should implement this + void noteNonLinear(Expression* curr) { abort(); } + + static void doNoteNonLinear(SubType* self, Expression** currp) { + self->noteNonLinear(*currp); + } + + static void scan(SubType* self, Expression** currp) { + + Expression* curr = *currp; + + switch (curr->_id) { + case Expression::Id::InvalidId: + abort(); + case Expression::Id::BlockId: { + self->pushTask(SubType::doVisitBlock, currp); + if (curr->cast()->name.is()) { + self->pushTask(SubType::doNoteNonLinear, currp); + } + auto& list = curr->cast()->list; + for (int i = int(list.size()) - 1; i >= 0; i--) { + self->pushTask(SubType::scan, &list[i]); + } + break; + } + case Expression::Id::IfId: { + self->pushTask(SubType::doVisitIf, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->maybePushTask(SubType::scan, &curr->cast()->ifFalse); + self->pushTask(SubType::doNoteNonLinear, currp); + self->pushTask(SubType::scan, &curr->cast()->ifTrue); + self->pushTask(SubType::doNoteNonLinear, currp); + self->pushTask(SubType::scan, &curr->cast()->condition); + break; + } + case Expression::Id::LoopId: { + self->pushTask(SubType::doVisitLoop, currp); + self->pushTask(SubType::scan, &curr->cast()->body); + self->pushTask(SubType::doNoteNonLinear, currp); + break; + } + case Expression::Id::BreakId: { + self->pushTask(SubType::doVisitBreak, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->maybePushTask(SubType::scan, &curr->cast()->condition); + self->maybePushTask(SubType::scan, &curr->cast()->value); + break; + } + case Expression::Id::SwitchId: { + self->pushTask(SubType::doVisitSwitch, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->maybePushTask(SubType::scan, &curr->cast()->value); + self->pushTask(SubType::scan, &curr->cast()->condition); + break; + } + case Expression::Id::ReturnId: { + self->pushTask(SubType::doVisitReturn, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->maybePushTask(SubType::scan, &curr->cast()->value); + break; + } + case Expression::Id::TryId: { + self->pushTask(SubType::doVisitTry, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->pushTask(SubType::scan, &curr->cast()->catchBody); + self->pushTask(SubType::doNoteNonLinear, currp); + self->pushTask(SubType::scan, &curr->cast()->body); + break; + } + case Expression::Id::ThrowId: { + self->pushTask(SubType::doVisitThrow, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + auto& list = curr->cast()->operands; + for (int i = int(list.size()) - 1; i >= 0; i--) { + self->pushTask(SubType::scan, &list[i]); + } + break; + } + case Expression::Id::RethrowId: { + self->pushTask(SubType::doVisitRethrow, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->pushTask(SubType::scan, &curr->cast()->exnref); + break; + } + case Expression::Id::BrOnExnId: { + self->pushTask(SubType::doVisitBrOnExn, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + self->pushTask(SubType::scan, &curr->cast()->exnref); + break; + } + case Expression::Id::UnreachableId: { + self->pushTask(SubType::doVisitUnreachable, currp); + self->pushTask(SubType::doNoteNonLinear, currp); + break; + } + default: { + // other node types do not have control flow, use regular post-order + PostWalker::scan(self, currp); + } + } + } +}; + } // namespace wasm #endif // wasm_wasm_traversal_h diff -Nru binaryen-108/src/wasm-type.h binaryen-99/src/wasm-type.h --- binaryen-108/src/wasm-type.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-type.h 2021-01-07 20:01:06.000000000 +0000 @@ -17,17 +17,10 @@ #ifndef wasm_wasm_type_h #define wasm_wasm_type_h -#include -#include -#include -#include -#include -#include - -#include "support/index.h" #include "support/name.h" -#include "support/parent_index_iterator.h" #include "wasm-features.h" +#include +#include // TODO: At various code locations we were assuming that single types are basic // types, but this is going to change with the introduction of the compound @@ -35,33 +28,15 @@ // prepare for this change, the following macro marks affected code locations. #define TODO_SINGLE_COMPOUND(type) \ assert(!type.isTuple() && "Unexpected tuple type"); \ - assert(type.isBasic() && "TODO: handle compound types"); + assert(!type.isCompound() && "TODO: handle compound types"); namespace wasm { -enum class TypeSystem { - Equirecursive, - Nominal, - Isorecursive, -}; - -// This should only ever be called before any Types or HeapTypes have been -// created. The default system is equirecursive. -void setTypeSystem(TypeSystem system); - -TypeSystem getTypeSystem(); - -// Dangerous! Frees all types and heap types that have ever been created and -// resets the type system's internal state. This is only really meant to be used -// for tests. -void destroyAllTypesForTestingPurposesOnly(); - // The types defined in this file. All of them are small and typically passed by // value except for `Tuple` and `Struct`, which may own an unbounded amount of // data. class Type; class HeapType; -class RecGroup; struct Tuple; struct Signature; struct Field; @@ -72,17 +47,6 @@ enum Nullability { NonNullable, Nullable }; enum Mutability { Immutable, Mutable }; -// HeapType name information used for printing. -struct TypeNames { - // The name of the type. - Name name; - // For a Struct, names of fields. - std::unordered_map fieldNames; -}; - -// Used to generate HeapType names. -using HeapTypeNameGenerator = std::function; - // The type used for interning IDs in the public interfaces of Type and // HeapType. using TypeID = uint64_t; @@ -107,12 +71,13 @@ f64, v128, funcref, + externref, + exnref, anyref, eqref, i31ref, - dataref, }; - static constexpr BasicType _last_basic_type = dataref; + static constexpr BasicType _last_basic_type = i31ref; Type() : id(none) {} @@ -150,16 +115,18 @@ // │ v128 ║ x │ │ x │ x │ V │ ┘ // ├─ Aliases ───╫───┼───┼───┼───┤───────┤ // │ funcref ║ x │ │ x │ x │ f n │ ┐ Ref - // │ anyref ║ x │ │ x │ x │ f? n │ │ f_unc - // │ eqref ║ x │ │ x │ x │ n │ │ n_ullable - // │ i31ref ║ x │ │ x │ x │ │ │ - // │ dataref ║ x │ │ x │ x │ │ │ + // │ externref ║ x │ │ x │ x │ f? n │ │ f_unc + // │ exnref ║ x │ │ x │ x │ n │ │ n_ullable + // │ anyref ║ x │ │ x │ x │ f? n │ │ + // │ eqref ║ x │ │ x │ x │ n │ │ ┐ TODO (GC) + // │ i31ref ║ x │ │ x │ x │ │ │ ┘ // ├─ Compound ──╫───┼───┼───┼───┤───────┤ │ // │ Ref ║ │ x │ x │ x │ f? n? │◄┘ // │ Tuple ║ │ x │ │ x │ │ // │ Rtt ║ │ x │ x │ x │ │ // └─────────────╨───┴───┴───┴───┴───────┘ constexpr bool isBasic() const { return id <= _last_basic_type; } + constexpr bool isCompound() const { return id > _last_basic_type; } constexpr bool isConcrete() const { return id >= i32; } constexpr bool isInteger() const { return id == i32 || id == i64; } constexpr bool isFloat() const { return id == f32 || id == f64; } @@ -169,29 +136,11 @@ bool isSingle() const { return isConcrete() && !isTuple(); } bool isRef() const; bool isFunction() const; - bool isData() const; - // Checks whether a type is a reference and is nullable. This returns false - // for a value that is not a reference, that is, for which nullability is - // irrelevant. + bool isException() const; bool isNullable() const; - // Checks whether a type is a reference and is non-nullable. This returns - // false for a value that is not a reference, that is, for which nullability - // is irrelevant. (For that reason, this is only the negation of isNullable() - // on references, but both return false on non-references.) - bool isNonNullable() const; bool isRtt() const; bool isStruct() const; bool isArray() const; - bool isDefaultable() const; - - // Check if a type is either defaultable or non-nullable. This is useful in - // the case where we allow non-nullable types, but we disallow other things - // that are non-defaultable. For example, when GC-non-nullable references are - // allowed we can have a non-nullable reference, but we cannot have any other - // nondefaultable type. - bool isDefaultableOrNonNullable() const; - - Nullability getNullability() const; private: template bool hasPredicate() { @@ -221,15 +170,12 @@ bool operator!=(const Type& other) const { return id != other.id; } bool operator!=(const BasicType& other) const { return id != other; } + // Order types by some notion of simplicity + bool operator<(const Type& other) const; + // Returns the type size in bytes. Only single types are supported. unsigned getByteSize() const; - // Returns whether the type has a size in bytes. This is the same as whether - // it can be stored in linear memory. Things like references do not have this - // property, while numbers do. Tuples may or may not depending on their - // contents. - unsigned hasByteSize() const; - // Reinterpret an integer type to a float type with the same size and vice // versa. Only single integer and float types are supported. Type reinterpret() const; @@ -237,10 +183,6 @@ // Returns the feature set required to use this type. FeatureSet getFeatures() const; - // Returns the tuple, assuming that this is a tuple type. Note that it is - // normally simpler to use operator[] and size() on the Type directly. - const Tuple& getTuple() const; - // Gets the heap type corresponding to this type, assuming that it is a // reference or Rtt type. HeapType getHeapType() const; @@ -255,77 +197,88 @@ // Returns true if left is a subtype of right. Subtype includes itself. static bool isSubType(Type left, Type right); - // Return the ordered HeapType children, looking through child Types. - std::vector getHeapTypeChildren(); - // Computes the least upper bound from the type lattice. // If one of the type is unreachable, the other type becomes the result. If // the common supertype does not exist, returns none, a poison value. - static bool hasLeastUpperBound(Type a, Type b); static Type getLeastUpperBound(Type a, Type b); - template static bool hasLeastUpperBound(const T& types) { - auto first = types.begin(), end = types.end(); - if (first == end) { - return false; - } - for (auto second = std::next(first); second != end;) { - if (!hasLeastUpperBound(*first++, *second++)) { - return false; - } - } - return true; - } - template static Type getLeastUpperBound(const T& types) { - auto it = types.begin(), end = types.end(); - if (it == end) { - return Type::none; - } - Type lub = *it++; - for (; it != end; ++it) { - lub = getLeastUpperBound(lub, *it); - if (lub == Type::none) { - return Type::none; - } + + // Computes the least upper bound for all types in the given list. + template static Type mergeTypes(const T& types) { + Type type = Type::unreachable; + for (auto other : types) { + type = Type::getLeastUpperBound(type, other); } - return lub; + return type; } - // Helper allowing the value of `print(...)` to be sent to an ostream. Stores - // a `TypeID` because `Type` is incomplete at this point and using a reference - // makes it less convenient to use. - struct Printed { - TypeID typeID; - HeapTypeNameGenerator generateName; + std::string toString() const; + + struct Iterator + : std::iterator { + const Type* parent; + size_t index; + Iterator(const Type* parent, size_t index) : parent(parent), index(index) {} + bool operator==(const Iterator& other) const { + return index == other.index && parent == other.parent; + } + bool operator!=(const Iterator& other) const { return !(*this == other); } + Iterator& operator++() { + ++index; + return *this; + } + Iterator& operator--() { + --index; + return *this; + } + Iterator operator++(int) { + auto it = *this; + index++; + return it; + } + Iterator operator--(int) { + auto it = *this; + index--; + return it; + } + Iterator& operator+=(difference_type off) { + index += off; + return *this; + } + Iterator operator+(difference_type off) const { + return Iterator(*this) += off; + } + Iterator& operator-=(difference_type off) { + index -= off; + return *this; + } + Iterator operator-(difference_type off) const { + return Iterator(*this) -= off; + } + difference_type operator-(const Iterator& other) const { + assert(parent == other.parent); + return index - other.index; + } + const value_type& operator*() const; }; - // Given a function for generating non-basic HeapType names, print this Type - // to `os`.`generateName` should return the same name each time it is called - // with the same HeapType and it should return different names for different - // types. - Printed print(HeapTypeNameGenerator generateName) { - return Printed{getID(), generateName}; - } + Iterator begin() const { return Iterator(this, 0); } + Iterator end() const; + size_t size() const { return end() - begin(); } + const Type& operator[](size_t i) const; +}; +// Wrapper type for formatting types as "(param i32 i64 f32)" +struct ParamType { + Type type; + ParamType(Type type) : type(type) {} std::string toString() const; +}; - size_t size() const; - - struct Iterator : ParentIndexIterator { - using value_type = Type; - using pointer = const Type*; - using reference = const Type&; - reference operator*() const; - }; - - Iterator begin() const { return Iterator{{this, 0}}; } - Iterator end() const { return Iterator{{this, size()}}; } - std::reverse_iterator rbegin() const { - return std::make_reverse_iterator(end()); - } - std::reverse_iterator rend() const { - return std::make_reverse_iterator(begin()); - } - const Type& operator[](size_t i) const { return *Iterator{{this, i}}; } +// Wrapper type for formatting types as "(result i32 i64 f32)" +struct ResultType { + Type type; + ResultType(Type type) : type(type) {} + std::string toString() const; }; class HeapType { @@ -338,12 +291,13 @@ public: enum BasicHeapType : uint32_t { func, + ext, + exn, any, eq, i31, - data, }; - static constexpr BasicHeapType _last_basic_type = data; + static constexpr BasicHeapType _last_basic_type = i31; // BasicHeapType can be implicitly upgraded to HeapType constexpr HeapType(BasicHeapType id) : id(id) {} @@ -351,26 +305,14 @@ // But converting raw TypeID is more dangerous, so make it explicit explicit HeapType(TypeID id) : id(id) {} - // Choose an arbitrary heap type as the default. - constexpr HeapType() : HeapType(func) {} - - // Construct a HeapType referring to the single canonical HeapType for the - // given signature. In nominal mode, this is the first HeapType created with - // this signature. HeapType(Signature signature); - - // Create a HeapType with the given structure. In equirecursive mode, this may - // be the same as a previous HeapType created with the same contents. In - // nominal mode, this will be a fresh type distinct from all previously - // created HeapTypes. - // TODO: make these explicit to differentiate them. HeapType(const Struct& struct_); HeapType(Struct&& struct_); HeapType(Array array); constexpr bool isBasic() const { return id <= _last_basic_type; } + constexpr bool isCompound() const { return id > _last_basic_type; } bool isFunction() const; - bool isData() const; bool isSignature() const; bool isStruct() const; bool isArray() const; @@ -379,18 +321,6 @@ const Struct& getStruct() const; Array getArray() const; - // If there is a nontrivial (i.e. non-basic) nominal supertype, return it, - // else an empty optional. - std::optional getSuperType() const; - - // Return the depth of this heap type in the nominal type hierarchy, i.e. the - // number of supertypes in its supertype chain. - size_t getDepth() const; - - // Get the recursion group for this non-basic type. - RecGroup getRecGroup() const; - size_t getRecGroupIndex() const; - constexpr TypeID getID() const { return id; } constexpr BasicHeapType getBasic() const { assert(isBasic() && "Basic heap type expected"); @@ -405,64 +335,10 @@ bool operator!=(const HeapType& other) const { return id != other.id; } bool operator!=(const BasicHeapType& other) const { return id != other; } - // Returns true if left is a subtype of right. Subtype includes itself. - static bool isSubType(HeapType left, HeapType right); - - // Return the ordered HeapType children, looking through child Types. - std::vector getHeapTypeChildren() const; - - // Similar to `getHeapTypeChildren`, but also includes the supertype if it - // exists. - std::vector getReferencedHeapTypes() const; - - // Return the LUB of two HeapTypes. The LUB always exists. - static HeapType getLeastUpperBound(HeapType a, HeapType b); - - // Helper allowing the value of `print(...)` to be sent to an ostream. Stores - // a `TypeID` because `Type` is incomplete at this point and using a reference - // makes it less convenient to use. - struct Printed { - TypeID typeID; - HeapTypeNameGenerator generateName; - }; - - // Given a function for generating HeapType names, print the definition of - // this HeapType to `os`. `generateName` should return the same - // name each time it is called with the same HeapType and it should return - // different names for different types. - Printed print(HeapTypeNameGenerator generateName) { - return Printed{getID(), generateName}; - } - + bool operator<(const HeapType& other) const; std::string toString() const; }; -// A recursion group consisting of one or more HeapTypes. HeapTypes with single -// members are encoded without using any additional memory, which is why -// `getHeapTypes` has to return a vector by value; it might have to create one -// on the fly. -class RecGroup { - uintptr_t id; - -public: - explicit RecGroup(uintptr_t id) : id(id) {} - constexpr TypeID getID() const { return id; } - bool operator==(const RecGroup& other) const { return id == other.id; } - bool operator!=(const RecGroup& other) const { return id != other.id; } - size_t size() const; - - struct Iterator : ParentIndexIterator { - using value_type = HeapType; - using pointer = const HeapType*; - using reference = const HeapType&; - value_type operator*() const; - }; - - Iterator begin() const { return Iterator{{this, 0}}; } - Iterator end() const { return Iterator{{this, size()}}; } - HeapType operator[](size_t i) const { return *Iterator{{this, i}}; } -}; - typedef std::vector TypeList; // Passed by reference rather than by value because it can own an unbounded @@ -473,17 +349,14 @@ Tuple(std::initializer_list types) : types(types) { validate(); } Tuple(const TypeList& types) : types(types) { validate(); } Tuple(TypeList&& types) : types(std::move(types)) { validate(); } - - // Allow copies when constructing. - Tuple(const Tuple& other) : types(other.types) { validate(); } - - // Prevent accidental copies. - Tuple& operator=(const Tuple&) = delete; - bool operator==(const Tuple& other) const { return types == other.types; } bool operator!=(const Tuple& other) const { return !(*this == other); } + bool operator<(const Tuple& other) const { return types < other.types; } std::string toString() const; + // Prevent accidental copies + Tuple& operator=(const Tuple&) = delete; + private: void validate() { #ifndef NDEBUG @@ -503,6 +376,7 @@ return params == other.params && results == other.results; } bool operator!=(const Signature& other) const { return !(*this == other); } + bool operator<(const Signature& other) const; std::string toString() const; }; @@ -514,13 +388,12 @@ i16, } packedType; // applicable iff type=i32 Mutability mutable_; + Name name; - // Arbitrary defaults for convenience. - Field() : type(Type::i32), packedType(not_packed), mutable_(Mutable) {} - Field(Type type, Mutability mutable_) - : type(type), packedType(not_packed), mutable_(mutable_) {} - Field(PackedType packedType, Mutability mutable_) - : type(Type::i32), packedType(packedType), mutable_(mutable_) {} + Field(Type type, Mutability mutable_, Name name = Name()) + : type(type), packedType(not_packed), mutable_(mutable_), name(name) {} + Field(PackedType packedType, Mutability mutable_, Name name = Name()) + : type(Type::i32), packedType(packedType), mutable_(mutable_), name(name) {} constexpr bool isPacked() const { if (packedType != not_packed) { @@ -531,13 +404,14 @@ } bool operator==(const Field& other) const { + // Note that the name is not checked here - it is pure metadata for printing + // purposes only. return type == other.type && packedType == other.packedType && mutable_ == other.mutable_; } bool operator!=(const Field& other) const { return !(*this == other); } + bool operator<(const Field& other) const; std::string toString() const; - - unsigned getByteSize() const; }; typedef std::vector FieldList; @@ -546,12 +420,12 @@ // amount of data. struct Struct { FieldList fields; - Struct() = default; Struct(const Struct& other) : fields(other.fields) {} Struct(const FieldList& fields) : fields(fields) {} Struct(FieldList&& fields) : fields(std::move(fields)) {} bool operator==(const Struct& other) const { return fields == other.fields; } bool operator!=(const Struct& other) const { return !(*this == other); } + bool operator<(const Struct& other) const { return fields < other.fields; } std::string toString() const; // Prevent accidental copies @@ -560,11 +434,11 @@ struct Array { Field element; - Array() = default; Array(const Array& other) : element(other.element) {} Array(Field element) : element(element) {} bool operator==(const Array& other) const { return element == other.element; } bool operator!=(const Array& other) const { return !(*this == other); } + bool operator<(const Array& other) const { return element < other.element; } std::string toString() const; }; @@ -573,13 +447,14 @@ static constexpr uint32_t NoDepth = -1; uint32_t depth; HeapType heapType; - explicit Rtt(HeapType heapType) : depth(NoDepth), heapType(heapType) {} + Rtt(HeapType heapType) : depth(NoDepth), heapType(heapType) {} Rtt(uint32_t depth, HeapType heapType) : depth(depth), heapType(heapType) {} bool operator==(const Rtt& other) const { return depth == other.depth && heapType == other.heapType; } bool operator!=(const Rtt& other) const { return !(*this == other); } - bool hasDepth() const { return depth != uint32_t(NoDepth); } + bool operator<(const Rtt& other) const; + bool hasDepth() { return depth != uint32_t(NoDepth); } std::string toString() const; }; @@ -595,137 +470,40 @@ std::unique_ptr impl; TypeBuilder(size_t n); - TypeBuilder() : TypeBuilder(0) {} ~TypeBuilder(); TypeBuilder(TypeBuilder& other) = delete; + TypeBuilder(TypeBuilder&& other) = delete; TypeBuilder& operator=(TypeBuilder&) = delete; - TypeBuilder(TypeBuilder&& other); - TypeBuilder& operator=(TypeBuilder&& other); - - // Append `n` new uninitialized HeapType slots to the end of the TypeBuilder. - void grow(size_t n); - - // The number of HeapType slots in the TypeBuilder. - size_t size(); - - // Sets the heap type at index `i`. May only be called before `build`. The - // BasicHeapType overload may not be used in nominal mode. - void setHeapType(size_t i, HeapType::BasicHeapType basic); + // Sets the heap type at index `i`. May only be called before `build`. void setHeapType(size_t i, Signature signature); void setHeapType(size_t i, const Struct& struct_); void setHeapType(size_t i, Struct&& struct_); void setHeapType(size_t i, Array array); - // This is an ugly hack around the fact that temp heap types initialized with - // BasicHeapTypes are not themselves considered basic, so `HeapType::isBasic` - // and `HeapType::getBasic` do not work as expected with them. Call these - // methods instead. - bool isBasic(size_t i); - HeapType::BasicHeapType getBasic(size_t i); - - // Gets the temporary HeapType at index `i`. This HeapType should only be used - // to construct temporary Types using the methods below. - HeapType getTempHeapType(size_t i); - // Gets a temporary type or heap type for use in initializing the - // TypeBuilder's HeapTypes. For Ref and Rtt types, the HeapType may be a - // temporary HeapType owned by this builder or a canonical HeapType. + // TypeBuilder's HeapTypes. Temporary Ref and Rtt types are backed by the + // HeapType at index `i`. Type getTempTupleType(const Tuple&); - Type getTempRefType(HeapType heapType, Nullability nullable); - Type getTempRttType(Rtt rtt); - - // In nominal mode, or for nominal types, declare the HeapType being built at - // index `i` to be an immediate subtype of the HeapType being built at index - // `j`. Does nothing for equirecursive types. - void setSubType(size_t i, size_t j); - - // Create a new recursion group covering slots [i, i + length). Groups must - // not overlap or go out of bounds. - void createRecGroup(size_t i, size_t length); - - enum class ErrorReason { - // There is a cycle in the supertype relation. - SelfSupertype, - // The declared supertype of a type is invalid. - InvalidSupertype, - // The declared supertype is an invalid forward reference. - ForwardSupertypeReference, - // A child of the type is an invalid forward reference. - ForwardChildReference, - }; + Type getTempRefType(size_t i, Nullability nullable); + Type getTempRttType(size_t i, uint32_t depth); - struct Error { - // The index of the type causing the failure. - size_t index; - ErrorReason reason; - }; - - struct BuildResult : std::variant, Error> { - operator bool() const { - return bool(std::get_if>(this)); - } - const std::vector& operator*() const { - return std::get>(*this); - } - const Error* getError() const { return std::get_if(this); } - }; - - // Returns all of the newly constructed heap types. May only be called once - // all of the heap types have been initialized with `setHeapType`. In nominal - // mode, all of the constructed HeapTypes will be fresh and distinct. In - // nominal mode, will also produce a fatal error if the declared subtype - // relationships are not valid. - BuildResult build(); - - // Utility for ergonomically using operator[] instead of explicit setHeapType - // and getTempHeapType methods. - struct Entry { - TypeBuilder& builder; - size_t index; - operator HeapType() const { return builder.getTempHeapType(index); } - Entry& operator=(HeapType::BasicHeapType basic) { - builder.setHeapType(index, basic); - return *this; - } - Entry& operator=(Signature signature) { - builder.setHeapType(index, signature); - return *this; - } - Entry& operator=(const Struct& struct_) { - builder.setHeapType(index, struct_); - return *this; - } - Entry& operator=(Struct&& struct_) { - builder.setHeapType(index, std::move(struct_)); - return *this; - } - Entry& operator=(Array array) { - builder.setHeapType(index, array); - return *this; - } - Entry& subTypeOf(Entry other) { - assert(&builder == &other.builder); - builder.setSubType(index, other.index); - return *this; - } - }; - - Entry operator[](size_t i) { return Entry{*this, i}; } + // Canonicalizes and returns all of the heap types. May only be called once + // all of the heap types have been initialized with `setHeapType`. + std::vector build(); }; std::ostream& operator<<(std::ostream&, Type); -std::ostream& operator<<(std::ostream&, Type::Printed); -std::ostream& operator<<(std::ostream&, HeapType); -std::ostream& operator<<(std::ostream&, HeapType::Printed); +std::ostream& operator<<(std::ostream&, ParamType); +std::ostream& operator<<(std::ostream&, ResultType); std::ostream& operator<<(std::ostream&, Tuple); std::ostream& operator<<(std::ostream&, Signature); std::ostream& operator<<(std::ostream&, Field); std::ostream& operator<<(std::ostream&, Struct); std::ostream& operator<<(std::ostream&, Array); +std::ostream& operator<<(std::ostream&, HeapType); std::ostream& operator<<(std::ostream&, Rtt); -std::ostream& operator<<(std::ostream&, TypeBuilder::ErrorReason); } // namespace wasm @@ -763,10 +541,6 @@ public: size_t operator()(const wasm::Rtt&) const; }; -template<> class hash { -public: - size_t operator()(const wasm::RecGroup&) const; -}; } // namespace std diff -Nru binaryen-108/src/wasm-type-printing.h binaryen-99/src/wasm-type-printing.h --- binaryen-108/src/wasm-type-printing.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/src/wasm-type-printing.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -/* - * Copyright 2022 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_wasm_type_printing_h -#define wasm_wasm_type_printing_h - -#include -#include -#include - -#include "support/name.h" -#include "support/utilities.h" -#include "wasm-type.h" - -namespace wasm { - -// CRTP base that all other type name generators should subclass. Provides the -// ability to use the generator as a function to print Types and HeapTypes to -// streams. -template struct TypeNameGeneratorBase { - TypeNames getNames(HeapType type) { - static_assert(&TypeNameGeneratorBase::getNames != - &Subclass::getNames, - "Derived class must implement getNames"); - WASM_UNREACHABLE("Derived class must implement getNames"); - } - HeapType::Printed operator()(HeapType type) { - return type.print( - [&](HeapType ht) { return static_cast(this)->getNames(ht); }); - } - Type::Printed operator()(Type type) { - return type.print( - [&](HeapType ht) { return static_cast(this)->getNames(ht); }); - } -}; - -// Generates names like "func.0", "struct.1", "array.2", etc. Struct fields are -// not given names. -struct DefaultTypeNameGenerator - : TypeNameGeneratorBase { - size_t funcCount = 0; - size_t structCount = 0; - size_t arrayCount = 0; - - // Cached names for types that have already been seen. - std::unordered_map nameCache; - - TypeNames getNames(HeapType type); -}; - -// Generates names based on the indices of types in some collection, falling -// back to the given FallbackGenerator when encountering a type not in the -// collection. Struct fields are not given names. -template -struct IndexedTypeNameGenerator - : TypeNameGeneratorBase> { - DefaultTypeNameGenerator defaultGenerator; - FallbackGenerator& fallback; - std::unordered_map names; - - template - IndexedTypeNameGenerator(T& types, - FallbackGenerator& fallback, - const std::string& prefix = "") - : fallback(fallback) { - for (size_t i = 0; i < types.size(); ++i) { - names.insert({types[i], {prefix + std::to_string(i), {}}}); - } - } - template - IndexedTypeNameGenerator(T& types, const std::string& prefix = "") - : IndexedTypeNameGenerator(types, defaultGenerator, prefix) {} - - TypeNames getNames(HeapType type) { - if (auto it = names.find(type); it != names.end()) { - return it->second; - } else { - return fallback.getNames(type); - } - } -}; - -} // namespace wasm - -#endif // wasm_wasm_type_printing_h diff -Nru binaryen-108/test/atomics64.wast.fromBinary binaryen-99/test/atomics64.wast.fromBinary --- binaryen-108/test/atomics64.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/atomics64.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,184 +1,184 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 (shared i64 23 256)) (func $atomic-loadstore - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (i32.atomic.load8_u offset=4 - (local.get $0) + (local.get $1) ) ) (drop (i32.atomic.load16_u offset=4 - (local.get $0) + (local.get $1) ) ) (drop (i32.atomic.load offset=4 - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load8_u - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load16_u - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load32_u - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load - (local.get $0) + (local.get $1) ) ) (i32.atomic.store offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) (i32.atomic.store8 offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) (i32.atomic.store16 offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) (i64.atomic.store offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) (i64.atomic.store8 offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) (i64.atomic.store16 offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) (i64.atomic.store32 offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) ) (func $atomic-rmw - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (i32.atomic.rmw.add offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (i32.atomic.rmw8.add_u offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (i32.atomic.rmw16.and_u + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (i64.atomic.rmw32.or_u - (local.get $0) (local.get $1) + (local.get $2) ) ) (drop (i32.atomic.rmw8.xchg_u + (local.get $1) (local.get $0) - (local.get $2) ) ) ) (func $atomic-cmpxchg - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (i32.atomic.rmw.cmpxchg offset=4 + (local.get $1) + (local.get $0) (local.get $0) - (local.get $2) - (local.get $2) ) ) (drop (i32.atomic.rmw8.cmpxchg_u + (local.get $1) + (local.get $0) (local.get $0) - (local.get $2) - (local.get $2) ) ) (drop (i64.atomic.rmw.cmpxchg offset=4 - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) (drop (i64.atomic.rmw32.cmpxchg_u - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) ) (func $atomic-wait-notify - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (memory.atomic.wait32 + (local.get $1) (local.get $0) (local.get $2) - (local.get $1) ) ) (drop (memory.atomic.wait32 offset=4 + (local.get $1) (local.get $0) (local.get $2) - (local.get $1) ) ) (drop (memory.atomic.notify + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (memory.atomic.notify offset=24 + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (memory.atomic.wait64 - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) (drop (memory.atomic.wait64 offset=16 - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) ) diff -Nru binaryen-108/test/atomics64.wast.fromBinary.noDebugInfo binaryen-99/test/atomics64.wast.fromBinary.noDebugInfo --- binaryen-108/test/atomics64.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/atomics64.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -2,183 +2,183 @@ (type $none_=>_none (func)) (memory $0 (shared i64 23 256)) (func $0 - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (i32.atomic.load8_u offset=4 - (local.get $0) + (local.get $1) ) ) (drop (i32.atomic.load16_u offset=4 - (local.get $0) + (local.get $1) ) ) (drop (i32.atomic.load offset=4 - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load8_u - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load16_u - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load32_u - (local.get $0) + (local.get $1) ) ) (drop (i64.atomic.load - (local.get $0) + (local.get $1) ) ) (i32.atomic.store offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) (i32.atomic.store8 offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) (i32.atomic.store16 offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) (i64.atomic.store offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) (i64.atomic.store8 offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) (i64.atomic.store16 offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) (i64.atomic.store32 offset=4 - (local.get $0) (local.get $1) + (local.get $2) ) ) (func $1 - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (i32.atomic.rmw.add offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (i32.atomic.rmw8.add_u offset=4 + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (i32.atomic.rmw16.and_u + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (i64.atomic.rmw32.or_u - (local.get $0) (local.get $1) + (local.get $2) ) ) (drop (i32.atomic.rmw8.xchg_u + (local.get $1) (local.get $0) - (local.get $2) ) ) ) (func $2 - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (i32.atomic.rmw.cmpxchg offset=4 + (local.get $1) + (local.get $0) (local.get $0) - (local.get $2) - (local.get $2) ) ) (drop (i32.atomic.rmw8.cmpxchg_u + (local.get $1) + (local.get $0) (local.get $0) - (local.get $2) - (local.get $2) ) ) (drop (i64.atomic.rmw.cmpxchg offset=4 - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) (drop (i64.atomic.rmw32.cmpxchg_u - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) ) (func $3 - (local $0 i64) + (local $0 i32) (local $1 i64) - (local $2 i32) + (local $2 i64) (drop (memory.atomic.wait32 + (local.get $1) (local.get $0) (local.get $2) - (local.get $1) ) ) (drop (memory.atomic.wait32 offset=4 + (local.get $1) (local.get $0) (local.get $2) - (local.get $1) ) ) (drop (memory.atomic.notify + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (memory.atomic.notify offset=24 + (local.get $1) (local.get $0) - (local.get $2) ) ) (drop (memory.atomic.wait64 - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) (drop (memory.atomic.wait64 offset=16 - (local.get $0) - (local.get $1) (local.get $1) + (local.get $2) + (local.get $2) ) ) ) diff -Nru binaryen-108/test/atomics64.wast.from-wast binaryen-99/test/atomics64.wast.from-wast --- binaryen-108/test/atomics64.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/atomics64.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 (shared i64 23 256)) (func $atomic-loadstore (local $0 i64) diff -Nru binaryen-108/test/atomics.wast.fromBinary binaryen-99/test/atomics.wast.fromBinary --- binaryen-108/test/atomics.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/atomics.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 (shared 23 256)) (func $atomic-loadstore (local $0 i32) diff -Nru binaryen-108/test/atomics.wast.from-wast binaryen-99/test/atomics.wast.from-wast --- binaryen-108/test/atomics.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/atomics.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 (shared 23 256)) (func $atomic-loadstore (local $0 i32) diff -Nru binaryen-108/test/bigswitch.cpp binaryen-99/test/bigswitch.cpp --- binaryen-108/test/bigswitch.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/bigswitch.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,7 @@ -#include "SDL/SDL_opengl.h" -#include #include #include - -// clang-format off +#include +#include "SDL/SDL_opengl.h" const char *WWWGLEnumToString(GLenum e) { @@ -7945,3 +7943,4 @@ i = 3060; printf("%d: %s\n", i, WWWGLEnumToString(i)); } + diff -Nru binaryen-108/test/binaryen.js/debug-info.js.txt binaryen-99/test/binaryen.js/debug-info.js.txt --- binaryen-108/test/binaryen.js/debug-info.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/debug-info.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -12,7 +12,7 @@ === with debug info === debugInfo=true (module - (type $v (func)) + (type $none_=>_none (func)) (memory $0 0) (export "test" (func $test)) (func $test diff -Nru binaryen-108/test/binaryen.js/debug-names.js.txt binaryen-99/test/binaryen.js/debug-names.js.txt --- binaryen-108/test/binaryen.js/debug-names.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/debug-names.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -11,9 +11,9 @@ === parsed wast === (module $hel (type $i32_=>_none (func (param i32))) - (global $ld i32 (i32.const 0)) (memory $lo 0 0) (table $wor 0 0 funcref) + (global $ld i32 (i32.const 0)) (func $of (param $wasm i32) (local $!#$%&'*+-./:<=>?@\^_`|~ f64) (nop) @@ -23,9 +23,9 @@ === roundtripped === (module $hel (type $i32_=>_none (func (param i32))) - (global $ld i32 (i32.const 0)) (memory $lo 0 0) (table $wor 0 0 funcref) + (global $ld i32 (i32.const 0)) (func $of (param $js i32) (local $!#$%&'*+-./:<=>?@\5c^_`|~ f64) (nop) @@ -35,9 +35,9 @@ === roundtripped again === (module $hel (type $i32_=>_none (func (param i32))) - (global $ld i32 (i32.const 0)) (memory $lo 0 0) (table $wor 0 0 funcref) + (global $ld i32 (i32.const 0)) (func $of (param $js i32) (local $!#$%&'*+-./:<=>?@\5c^_`|~ f64) (nop) diff -Nru binaryen-108/test/binaryen.js/event.js binaryen-99/test/binaryen.js/event.js --- binaryen-108/test/binaryen.js/event.js 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/binaryen.js/event.js 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,33 @@ +function cleanInfo(info) { + var ret = {}; + for (var x in info) { + ret[x] = info[x]; + } + return ret; +} + +var module = new binaryen.Module(); +module.setFeatures(binaryen.Features.ReferenceTypes | + binaryen.Features.ExceptionHandling | + binaryen.Features.Multivalue); + +var pairType = binaryen.createType([binaryen.i32, binaryen.f32]); + +var event_ = module.addEvent("a-event", 0, binaryen.i32, binaryen.none); + +console.log("GetEvent is equal: " + (event_ === module.getEvent("a-event"))); + +var eventInfo = binaryen.getEventInfo(event_); +console.log("getEventInfo=" + JSON.stringify(cleanInfo(eventInfo))); + +module.addEventExport("a-event", "a-event-exp"); +module.addEventImport("a-event-imp", "module", "base", 0, pairType, binaryen.none); + +assert(module.validate()); +console.log(module.emitText()); + +module.removeExport("a-event-exp"); +module.removeEvent("a-event"); + +assert(module.validate()); +console.log(module.emitText()); diff -Nru binaryen-108/test/binaryen.js/event.js.txt binaryen-99/test/binaryen.js/event.js.txt --- binaryen-108/test/binaryen.js/event.js.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/binaryen.js/event.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,15 @@ +GetEvent is equal: true +getEventInfo={"name":"a-event","module":"","base":"","attribute":0,"params":2,"results":0} +(module + (type $i32_=>_none (func (param i32))) + (type $i32_f32_=>_none (func (param i32 f32))) + (import "module" "base" (event $a-event-imp (attr 0) (param i32 f32))) + (event $a-event (attr 0) (param i32)) + (export "a-event-exp" (event $a-event)) +) + +(module + (type $i32_f32_=>_none (func (param i32 f32))) + (import "module" "base" (event $a-event-imp (attr 0) (param i32 f32))) +) + diff -Nru binaryen-108/test/binaryen.js/exception-handling.js binaryen-99/test/binaryen.js/exception-handling.js --- binaryen-108/test/binaryen.js/exception-handling.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/exception-handling.js 2021-01-07 20:01:06.000000000 +0000 @@ -1,10 +1,7 @@ function cleanInfo(info) { var ret = {}; for (var x in info) { - // Filter out address pointers and only print meaningful info - if (x == 'id' || x == 'type' || x == 'name' || x == 'tag' || - x == 'target' || x == 'hasCatchAll' || x == 'delegateTarget' || - x == 'isDelegate') { + if (x == 'id' || x == 'type' || x == 'name' || x == 'event') { ret[x] = info[x]; } } @@ -19,67 +16,43 @@ module.setFeatures(binaryen.Features.ReferenceTypes | binaryen.Features.ExceptionHandling); -module.addTag("e", binaryen.i32, binaryen.none); +var event_ = module.addEvent("e", 0, binaryen.i32, binaryen.none); -// (try $l0 +// (try // (do // (throw $e (i32.const 0)) // ) // (catch -// (drop (pop i32)) -// (rethrow $l0) +// ;; We don't support multi-value yet. Use locals instead. +// (local.set 0 (exnref.pop)) +// (drop +// (block $l (result i32) +// (rethrow +// (br_on_exn $l $e (local.get 0)) +// ) +// ) +// ) // ) // ) var throw_ = module.throw("e", [module.i32.const(0)]); -var rethrow = module.rethrow("l0"); -var try_catch = module.try( - "l0", +var br_on_exn = module.br_on_exn("l", "e", module.local.get(0, binaryen.exnref)); +var rethrow = module.rethrow(br_on_exn); +var try_ = module.try( throw_, - ["e"], - [ - module.block(null, - [ - module.drop(module.i32.pop()), - rethrow - ], - binaryen.none + module.block(null, [ + module.local.set(0, module.exnref.pop()), + module.drop( + module.block("l", [rethrow], binaryen.i32) ) - ], - '' -); - -// (try $try_outer -// (do -// (try -// (do -// (throw $a-tag (i32.const 0)) -// ) -// (delegate $try_outer) -// ) -// ) -// (catch_all) -// ) -var try_delegate = module.try( - 'try_outer', - module.try( - '', - throw_, - [], - [], - 'try_outer' - ), - [], - [module.nop()], - '' + ] + ) ); - -var body = module.block('', [try_catch, try_delegate]) -var func = module.addFunction("test", binaryen.none, binaryen.none, [], body); +var func = module.addFunction("test", binaryen.none, binaryen.none, [binaryen.exnref], try_); console.log(module.emitText()); assert(module.validate()); console.log("getExpressionInfo(throw) = " + stringify(throw_)); +console.log("getExpressionInfo(br_on_exn) = " + stringify(br_on_exn)); console.log("getExpressionInfo(rethrow) = " + stringify(rethrow)); -console.log("getExpressionInfo(try_catch) = " + stringify(try_catch)); -console.log("getExpressionInfo(try_delegate) = " + stringify(try_delegate)); +console.log("getExpressionInfo(try) = " + stringify(try_)); diff -Nru binaryen-108/test/binaryen.js/exception-handling.js.txt binaryen-99/test/binaryen.js/exception-handling.js.txt --- binaryen-108/test/binaryen.js/exception-handling.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/exception-handling.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,40 +1,34 @@ (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) - (tag $e (param i32)) + (type $i32_=>_none (func (param i32))) + (event $e (attr 0) (param i32)) (func $test - (try $l0 + (local $0 exnref) + (try (do (throw $e (i32.const 0) ) ) - (catch $e - (drop - (pop i32) + (catch + (local.set $0 + (pop exnref) ) - (rethrow $l0) - ) - ) - (try $try_outer - (do - (try - (do - (throw $e - (i32.const 0) + (drop + (block $l (result i32) + (rethrow + (br_on_exn $l $e + (local.get $0) + ) ) ) - (delegate $try_outer) ) ) - (catch_all - (nop) - ) ) ) ) -getExpressionInfo(throw) = {"id":50,"type":1,"tag":"e"} -getExpressionInfo(rethrow) = {"id":51,"type":1,"target":"l0"} -getExpressionInfo(try_catch) = {"id":49,"type":1,"name":"l0","hasCatchAll":0,"delegateTarget":"","isDelegate":0} -getExpressionInfo(try_delegate) = {"id":49,"type":0,"name":"try_outer","hasCatchAll":1,"delegateTarget":"","isDelegate":0} +getExpressionInfo(throw) = {"id":47,"type":1,"event":"e"} +getExpressionInfo(br_on_exn) = {"id":49,"type":9,"name":"l","event":"e"} +getExpressionInfo(rethrow) = {"id":48,"type":1} +getExpressionInfo(try) = {"id":46,"type":0} diff -Nru binaryen-108/test/binaryen.js/expressions.js binaryen-99/test/binaryen.js/expressions.js --- binaryen-108/test/binaryen.js/expressions.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/expressions.js 2021-01-07 20:01:06.000000000 +0000 @@ -37,7 +37,6 @@ assert(theBlock.type === binaryen.i32); assert(theBlock.numChildren === 0); assertDeepEqual(theBlock.children, []); - assertDeepEqual(theBlock.getChildren(), []); var child1 = module.i32.const(1); theBlock.appendChild(child1); @@ -206,12 +205,11 @@ assert(theSwitch.value === value); assert(theSwitch.type === binaryen.unreachable); - names = [ + theSwitch.names = names = [ "1", // set - "2", //set - "3" // append - ] - theSwitch.setNames(names); + "2", // set + "3" // append + ]; assertDeepEqual(theSwitch.names, names); theSwitch.names = names = [ "x", // set @@ -219,7 +217,6 @@ // remove ]; assertDeepEqual(theSwitch.names, names); - assertDeepEqual(theSwitch.getNames(), names); theSwitch.insertNameAt(1, "y"); theSwitch.condition = condition = module.i32.const(3); assert(theSwitch.condition === condition); @@ -251,7 +248,6 @@ assert(theCall instanceof binaryen.Expression); assert(theCall.target === target); assertDeepEqual(theCall.operands, operands); - assertDeepEqual(theCall.getOperands(), operands); assert(theCall.return === false); assert(theCall.type === binaryen.i32); @@ -263,12 +259,11 @@ module.i32.const(5) // append ]; assertDeepEqual(theCall.operands, operands); - operands = [ + theCall.operands = operands = [ module.i32.const(6) // set // remove // remove ]; - theCall.setOperands(operands); assertDeepEqual(theCall.operands, operands); theCall.insertOperandAt(0, module.i32.const(7)); theCall.return = true; @@ -295,7 +290,6 @@ (function testCallIndirect() { const module = new binaryen.Module(); - var table = "0"; var target = module.i32.const(42); var params = binaryen.none; var results = binaryen.none; @@ -303,10 +297,9 @@ module.i32.const(1), module.i32.const(2) ]; - const theCallIndirect = binaryen.CallIndirect(module.call_indirect(table, target, operands, params, results)); + const theCallIndirect = binaryen.CallIndirect(module.call_indirect(target, operands, params, results)); assert(theCallIndirect instanceof binaryen.CallIndirect); assert(theCallIndirect instanceof binaryen.Expression); - assert(theCallIndirect.table === table); assert(theCallIndirect.target === target); assertDeepEqual(theCallIndirect.operands, operands); assert(theCallIndirect.params === params); @@ -322,14 +315,12 @@ module.i32.const(5) // append ]; assertDeepEqual(theCallIndirect.operands, operands); - operands = [ + theCallIndirect.operands = operands = [ module.i32.const(6) // set // remove // remove ]; - theCallIndirect.setOperands(operands); assertDeepEqual(theCallIndirect.operands, operands); - assertDeepEqual(theCallIndirect.getOperands(), operands); theCallIndirect.insertOperandAt(0, module.i32.const(7)); theCallIndirect.return = true; assert(theCallIndirect.return === true); @@ -348,7 +339,7 @@ assert( theCallIndirect.toText() == - "(call_indirect $0 (type $i32_i32_=>_i32)\n (i32.const 7)\n (i32.const 6)\n (i32.const 9000)\n)\n" + "(call_indirect (type $i32_i32_=>_i32)\n (i32.const 7)\n (i32.const 6)\n (i32.const 9000)\n)\n" ); module.dispose(); @@ -1079,7 +1070,7 @@ var left = module.v128.const([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]); var right = module.v128.const([2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]); var mask = [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]; - const theSIMDShuffle = binaryen.SIMDShuffle(module.i8x16.shuffle(left, right, mask)); + const theSIMDShuffle = binaryen.SIMDShuffle(module.v8x16.shuffle(left, right, mask)); assert(theSIMDShuffle instanceof binaryen.SIMDShuffle); assert(theSIMDShuffle instanceof binaryen.Expression); assert(theSIMDShuffle.left === left); @@ -1101,7 +1092,7 @@ assert( theSIMDShuffle.toText() == - "(i8x16.shuffle 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3\n (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101)\n (v128.const i32x4 0x02020202 0x02020202 0x02020202 0x02020202)\n)\n" + "(v8x16.shuffle 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3\n (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101)\n (v128.const i32x4 0x02020202 0x02020202 0x02020202 0x02020202)\n)\n" ); module.dispose(); @@ -1124,11 +1115,23 @@ assert(theSIMDTernary.c === c); assert(theSIMDTernary.type === binaryen.v128); - console.log(theSIMDTernary.toText() + "\n"); + theSIMDTernary.op = op = binaryen.Operations.QFMAVecF64x2; + assert(theSIMDTernary.op === op); + theSIMDTernary.a = a = module.v128.const([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]); + assert(theSIMDTernary.a === a); + theSIMDTernary.b = b = module.v128.const([2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]); + assert(theSIMDTernary.b === b); + theSIMDTernary.c = c = module.v128.const([3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]); + assert(theSIMDTernary.c === c); + theSIMDTernary.type = binaryen.f64; + theSIMDTernary.finalize(); + assert(theSIMDTernary.type === binaryen.v128); + + console.log(theSIMDTernary.toText()); assert( theSIMDTernary.toText() == - "(v128.bitselect\n (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)\n (v128.const i32x4 0x05040302 0x09080706 0x0d0c0b0a 0x11100f0e)\n (v128.const i32x4 0x06050403 0x0a090807 0x0e0d0c0b 0x1211100f)\n)\n" + "(f64x2.qfma\n (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101)\n (v128.const i32x4 0x02020202 0x02020202 0x02020202 0x02020202)\n (v128.const i32x4 0x03030303 0x03030303 0x03030303 0x03030303)\n)\n" ); module.dispose(); @@ -1173,11 +1176,11 @@ (function testSIMDLoad() { const module = new binaryen.Module(); - var op = binaryen.Operations.Load8x8SVec128; + var op = binaryen.Operations.LoadExtSVec8x8ToVecI16x8; var offset = 16; var align = 2; var ptr = module.i32.const(1); - const theSIMDLoad = binaryen.SIMDLoad(module.v128.load8x8_s(offset, align, ptr)); + const theSIMDLoad = binaryen.SIMDLoad(module.i16x8.load8x8_s(offset, align, ptr)); assert(theSIMDLoad instanceof binaryen.SIMDLoad); assert(theSIMDLoad instanceof binaryen.Expression); assert(theSIMDLoad.offset === offset); @@ -1185,7 +1188,7 @@ assert(theSIMDLoad.ptr === ptr); assert(theSIMDLoad.type === binaryen.v128); - theSIMDLoad.op = op = binaryen.Operations.Load8SplatVec128; + theSIMDLoad.op = op = binaryen.Operations.LoadSplatVec8x16; assert(theSIMDLoad.op === op); theSIMDLoad.offset = offset = 32; assert(theSIMDLoad.offset === offset); @@ -1201,69 +1204,7 @@ assert( theSIMDLoad.toText() == - "(v128.load8_splat offset=32 align=4\n (i32.const 2)\n)\n" - ); - - module.dispose(); -})(); - -console.log("# SIMDLoadStoreLane"); -(function testSIMDLoadStoreLane() { - const module = new binaryen.Module(); - - var op = binaryen.Operations.Load8LaneVec128; - var offset = 16; - var index = 1; - var align = 1; - var ptr = module.i32.const(1); - var vec = module.v128.const([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]); - const theSIMDLoadStoreLane = binaryen.SIMDLoadStoreLane(module.v128.load8_lane(offset, align, index, ptr, vec)); - assert(theSIMDLoadStoreLane instanceof binaryen.SIMDLoadStoreLane); - assert(theSIMDLoadStoreLane instanceof binaryen.Expression); - assert(theSIMDLoadStoreLane.op === op); - assert(theSIMDLoadStoreLane.offset === offset); - assert(theSIMDLoadStoreLane.align === align); - assert(theSIMDLoadStoreLane.index === index); - assert(theSIMDLoadStoreLane.ptr === ptr); - assert(theSIMDLoadStoreLane.vec === vec); - assert(theSIMDLoadStoreLane.type === binaryen.v128); - assert(theSIMDLoadStoreLane.store === false); - - theSIMDLoadStoreLane.op = op = binaryen.Operations.Load16LaneVec128; - assert(theSIMDLoadStoreLane.op === op); - theSIMDLoadStoreLane.offset = offset = 32; - assert(theSIMDLoadStoreLane.offset === offset); - theSIMDLoadStoreLane.align = align = 2; - assert(theSIMDLoadStoreLane.align === align); - theSIMDLoadStoreLane.index = index = 2; - assert(theSIMDLoadStoreLane.index === index); - theSIMDLoadStoreLane.ptr = ptr = module.i32.const(2); - assert(theSIMDLoadStoreLane.ptr === ptr); - theSIMDLoadStoreLane.vec = vec = module.v128.const([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]); - assert(theSIMDLoadStoreLane.vec === vec); - theSIMDLoadStoreLane.type = binaryen.f64; - theSIMDLoadStoreLane.finalize(); - assert(theSIMDLoadStoreLane.type === binaryen.v128); - - console.log(theSIMDLoadStoreLane.toText()); - assert( - theSIMDLoadStoreLane.toText() - == - "(v128.load16_lane offset=32 2\n (i32.const 2)\n (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101)\n)\n" - ); - - theSIMDLoadStoreLane.op = op = binaryen.Operations.Store16LaneVec128; - assert(theSIMDLoadStoreLane.op === op); - theSIMDLoadStoreLane.type = binaryen.f64; - assert(theSIMDLoadStoreLane.store === true); - theSIMDLoadStoreLane.finalize(); - assert(theSIMDLoadStoreLane.type === binaryen.none); - - console.log(theSIMDLoadStoreLane.toText()); - assert( - theSIMDLoadStoreLane.toText() - == - "(v128.store16_lane offset=32 2\n (i32.const 2)\n (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101)\n)\n" + "(v8x16.load_splat offset=32 align=4\n (i32.const 2)\n)\n" ); module.dispose(); @@ -1405,99 +1346,30 @@ module.dispose(); })(); -console.log("# RefIs"); -(function testRefIs() { +console.log("# RefIsNull"); +(function testRefIsNull() { const module = new binaryen.Module(); - var op = binaryen.Operations.RefIsNull; var value = module.local.get(1, binaryen.externref); - const theRefIs = binaryen.RefIs(module.ref.is_null(value)); - assert(theRefIs instanceof binaryen.RefIs); - assert(theRefIs instanceof binaryen.Expression); - assert(theRefIs.op === op); - assert(theRefIs.value === value); - assert(theRefIs.type === binaryen.i32); - - theRefIs.op = op = binaryen.Operations.RefIsFunc; - assert(theRefIs.op === op); - theRefIs.op = op = binaryen.Operations.RefIsNull; - theRefIs.value = value = module.local.get(2, binaryen.externref); - assert(theRefIs.value === value); - theRefIs.type = binaryen.f64; - theRefIs.finalize(); - assert(theRefIs.type === binaryen.i32); + const theRefIsNull = binaryen.RefIsNull(module.ref.is_null(value)); + assert(theRefIsNull instanceof binaryen.RefIsNull); + assert(theRefIsNull instanceof binaryen.Expression); + assert(theRefIsNull.value === value); + assert(theRefIsNull.type === binaryen.i32); + + theRefIsNull.value = value = module.local.get(2, binaryen.externref); + assert(theRefIsNull.value === value); + theRefIsNull.type = binaryen.f64; + theRefIsNull.finalize(); + assert(theRefIsNull.type === binaryen.i32); - console.log(theRefIs.toText()); + console.log(theRefIsNull.toText()); assert( - theRefIs.toText() + theRefIsNull.toText() == "(ref.is_null\n (local.get $2)\n)\n" ); - assert( - binaryen.RefIs(module.ref.is_func(value)).toText() - == - "(ref.is_func\n (local.get $2)\n)\n" - ); - assert( - binaryen.RefIs(module.ref.is_data(value)).toText() - == - "(ref.is_data\n (local.get $2)\n)\n" - ); - assert( - binaryen.RefIs(module.ref.is_i31(value)).toText() - == - "(ref.is_i31\n (local.get $2)\n)\n" - ); - - module.dispose(); -})(); - -console.log("# RefAs"); -(function testRefAs() { - const module = new binaryen.Module(); - - var op = binaryen.Operations.RefAsNonNull; - var value = module.local.get(1, binaryen.anyref); - const theRefAs = binaryen.RefAs(module.ref.as_non_null(value)); - assert(theRefAs instanceof binaryen.RefAs); - assert(theRefAs instanceof binaryen.Expression); - assert(theRefAs.op === op); - assert(theRefAs.value === value); - assert(theRefAs.type !== binaryen.i32); // TODO: === (ref any) - - theRefAs.op = op = binaryen.Operations.RefAsFunc; - assert(theRefAs.op === op); - theRefAs.op = op = binaryen.Operations.RefAsNull; - theRefAs.value = value = module.local.get(2, binaryen.anyref); - assert(theRefAs.value === value); - theRefAs.type = binaryen.f64; - theRefAs.finalize(); - assert(theRefAs.type !== binaryen.f64); // TODO: === (ref any) - - console.log(theRefAs.toText()); - assert( - theRefAs.toText() - == - "(ref.as_non_null\n (local.get $2)\n)\n" - ); - - assert( - binaryen.RefAs(module.ref.as_func(value)).toText() - == - "(ref.as_func\n (local.get $2)\n)\n" - ); - assert( - binaryen.RefAs(module.ref.as_data(value)).toText() - == - "(ref.as_data\n (local.get $2)\n)\n" - ); - assert( - binaryen.RefAs(module.ref.as_i31(value)).toText() - == - "(ref.as_i31\n (local.get $2)\n)\n" - ); - module.dispose(); })(); @@ -1510,9 +1382,7 @@ assert(theRefFunc instanceof binaryen.RefFunc); assert(theRefFunc instanceof binaryen.Expression); assert(theRefFunc.func === func); - // TODO: check the type. the type is (ref func), that is, a non-nullable func, - // which differs from funcref. we don't have the ability to create such - // a type in the C/JS APIs yet. + assert(theRefFunc.type === binaryen.funcref); theRefFunc.func = func = "b"; assert(theRefFunc.func === func); @@ -1565,76 +1435,30 @@ console.log("# Try"); (function testTry() { const module = new binaryen.Module(); - module.addTag("tag1", 0, binaryen.none, binaryen.none); - module.addTag("tag2", 0, binaryen.none, binaryen.none); - module.addTag("tag3", 0, binaryen.none, binaryen.none); var body = module.i32.const(1); - var catchBodies = [ - module.i32.const(2), - module.i32.const(3) - ]; - const theTry = binaryen.Try(module.try('', body, ["tag1"], catchBodies, '')); + var catchBody = module.i32.const(2); + const theTry = binaryen.Try(module.try(body, catchBody)); assert(theTry instanceof binaryen.Try); assert(theTry instanceof binaryen.Expression); assert(theTry.body === body); - assertDeepEqual(theTry.catchBodies, catchBodies); + assert(theTry.catchBody === catchBody); assert(theTry.type === binaryen.i32); - assert(theTry.getNumCatchTags() == 1); - assert(theTry.getNumCatchBodies() == 2); - assert(theTry.hasCatchAll() == 1); - console.log(theTry.toText()); - theTry.body = body = module.i32.const(4); + theTry.body = body = module.i32.const(3); assert(theTry.body === body); - catchBodies = [ - module.i32.const(5) // set - //remove - ]; - theTry.setCatchBodies(catchBodies); - assertDeepEqual(theTry.catchBodies, catchBodies); - assertDeepEqual(theTry.getCatchBodies(), catchBodies); - console.log(theTry.toText()); - - theTry.insertCatchTagAt(1, "tag2"); - theTry.insertCatchBodyAt(0, module.i32.const(6)); - assert(theTry.getNumCatchTags() == 2); - assert(theTry.getNumCatchBodies() == 2); - assert(theTry.hasCatchAll() == 0); - console.log(theTry.toText()); - - assert(theTry.removeCatchTagAt(1) == "tag2"); - theTry.removeCatchBodyAt(1); - assert(theTry.getNumCatchTags() == 1); - assert(theTry.getNumCatchBodies() == 1); - console.log(theTry.toText()); - - theTry.appendCatchTag("tag3"); - theTry.appendCatchBody(module.drop(module.i32.const(7))); - assert(theTry.getCatchTagAt(0) == "tag1"); - assert(theTry.getCatchTagAt(1) == "tag3"); - theTry.setCatchTags(["tag2", "tag3"]); - assertDeepEqual(theTry.getCatchTags(), ["tag2", "tag3"]); - theTry.setCatchBodies([module.i32.const(8), module.i32.const(9)]); - assert(theTry.getCatchTagAt(0) == "tag2"); - assert(theTry.getCatchTagAt(1) == "tag3"); - theTry.setCatchTagAt(1, "tag1"); - theTry.setCatchBodyAt(1, module.i32.const(10)); - assert(theTry.getCatchTagAt(1) == "tag1"); - console.log(theTry.toText()); - + theTry.catchBody = catchBody = module.i32.const(4); + assert(theTry.catchBody === catchBody); theTry.type = binaryen.f64; theTry.finalize(); assert(theTry.type === binaryen.i32); console.log(theTry.toText()); - - const tryDelegate = binaryen.Try(module.try('', body, [], [], "try_blah")); - assert(tryDelegate.isDelegate() == 1); - assert(tryDelegate.getDelegateTarget() == "try_blah"); - tryDelegate.setDelegateTarget("try_outer"); - assert(tryDelegate.getDelegateTarget() == "try_outer"); - console.log(tryDelegate.toText()); + assert( + theTry.toText() + == + "(try (result i32)\n (do\n (i32.const 3)\n )\n (catch\n (i32.const 4)\n )\n)\n" + ); module.dispose(); })(); @@ -1643,33 +1467,31 @@ (function testThrow() { const module = new binaryen.Module(); - var tag = "foo"; + var event = "foo"; var operands = [ module.i32.const(1), module.i32.const(2) ]; - const theThrow = binaryen.Throw(module.throw(tag, operands)); + const theThrow = binaryen.Throw(module.throw(event, operands)); assert(theThrow instanceof binaryen.Throw); assert(theThrow instanceof binaryen.Expression); - assert(theThrow.tag === tag); + assert(theThrow.event === event); assertDeepEqual(theThrow.operands, operands); assert(theThrow.type === binaryen.unreachable); - theThrow.tag = "bar"; - assert(theThrow.tag === "bar"); + theThrow.event = "bar"; + assert(theThrow.event === "bar"); theThrow.operands = operands = [ module.i32.const(3), // set module.i32.const(4), // set module.i32.const(5) // append ]; assertDeepEqual(theThrow.operands, operands); - assertDeepEqual(theThrow.getOperands(), operands); - operands = [ + theThrow.operands = operands = [ module.i32.const(6) // set // remove // remove ]; - theThrow.setOperands(operands); assertDeepEqual(theThrow.operands, operands); theThrow.insertOperandAt(1, module.i32.const(7)); theThrow.type = binaryen.f64; @@ -1690,14 +1512,15 @@ (function testRethrow() { const module = new binaryen.Module(); - const theRethrow = binaryen.Rethrow(module.rethrow("l0")); + var exnref = module.local.get(1, binaryen.exnref); + const theRethrow = binaryen.Rethrow(module.rethrow(exnref)); assert(theRethrow instanceof binaryen.Rethrow); assert(theRethrow instanceof binaryen.Expression); - assert(theRethrow.target === "l0"); + assert(theRethrow.exnref === exnref); assert(theRethrow.type === binaryen.unreachable); - theRethrow.target = "l1"; - assert(theRethrow.target === "l1"); + theRethrow.exnref = exnref = module.local.get(2, binaryen.exnref); + assert(theRethrow.exnref === exnref); theRethrow.type = binaryen.f64; theRethrow.finalize(); assert(theRethrow.type === binaryen.unreachable); @@ -1706,7 +1529,44 @@ assert( theRethrow.toText() == - "(rethrow $l1)\n" + "(rethrow\n (local.get $2)\n)\n" + ); + + module.dispose(); +})(); + +console.log("# BrOnExn"); +(function testBrOnExn() { + const module = new binaryen.Module(); + module.addEvent("event1", 0, binaryen.none, binaryen.none); + module.addEvent("event2", 0, binaryen.none, binaryen.none); + + var name = "foo"; + var event = "event1"; + var exnref = module.local.get(1, binaryen.exnref); + const theBrOnExn = binaryen.BrOnExn(module.br_on_exn(name, event, exnref)); + assert(theBrOnExn instanceof binaryen.BrOnExn); + assert(theBrOnExn instanceof binaryen.Expression); + assert(theBrOnExn.name === name); + assert(theBrOnExn.event === event); + assert(theBrOnExn.exnref === exnref); + assert(theBrOnExn.type === binaryen.exnref); + + theBrOnExn.name = name = "bar"; + assert(theBrOnExn.name === name); + theBrOnExn.event = event = "event2"; + assert(theBrOnExn.event === event); + theBrOnExn.exnref = exnref = module.local.get(2, binaryen.exnref); + assert(theBrOnExn.exnref === exnref); + theBrOnExn.type = binaryen.f64; + theBrOnExn.finalize(); + assert(theBrOnExn.type === binaryen.exnref); + + console.log(theBrOnExn.toText()); + assert( + theBrOnExn.toText() + == + "(br_on_exn $bar $event2\n (local.get $2)\n)\n" ); module.dispose(); @@ -1733,14 +1593,12 @@ module.i32.const(5) // append ]; assertDeepEqual(theTupleMake.operands, operands); - operands = [ + theTupleMake.operands = operands = [ module.i32.const(6) // set // remove // remove ]; - theTupleMake.setOperands(operands); assertDeepEqual(theTupleMake.operands, operands); - assertDeepEqual(theTupleMake.getOperands(), operands); theTupleMake.insertOperandAt(1, module.i32.const(7)); theTupleMake.type = binaryen.f64; theTupleMake.finalize(); diff -Nru binaryen-108/test/binaryen.js/expressions.js.txt binaryen-99/test/binaryen.js/expressions.js.txt --- binaryen-108/test/binaryen.js/expressions.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/expressions.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -42,7 +42,7 @@ ) # CallIndirect -(call_indirect $0 (type $i32_i32_=>_i32) +(call_indirect (type $i32_i32_=>_i32) (i32.const 7) (i32.const 6) (i32.const 9000) @@ -155,19 +155,18 @@ ) # SIMDShuffle -(i8x16.shuffle 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +(v8x16.shuffle 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) (v128.const i32x4 0x02020202 0x02020202 0x02020202 0x02020202) ) # SIMDTernary -(v128.bitselect - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x05040302 0x09080706 0x0d0c0b0a 0x11100f0e) - (v128.const i32x4 0x06050403 0x0a090807 0x0e0d0c0b 0x1211100f) +(f64x2.qfma + (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) + (v128.const i32x4 0x02020202 0x02020202 0x02020202 0x02020202) + (v128.const i32x4 0x03030303 0x03030303 0x03030303 0x03030303) ) - # SIMDShift (i8x16.shr_s (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) @@ -175,19 +174,8 @@ ) # SIMDLoad -(v128.load8_splat offset=32 align=4 - (i32.const 2) -) - -# SIMDLoadStoreLane -(v128.load16_lane offset=32 2 - (i32.const 2) - (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) -) - -(v128.store16_lane offset=32 2 +(v8x16.load_splat offset=32 align=4 (i32.const 2) - (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) ) # MemoryInit @@ -214,16 +202,11 @@ (i32.const 6) ) -# RefIs +# RefIsNull (ref.is_null (local.get $2) ) -# RefAs -(ref.as_non_null - (local.get $2) -) - # RefFunc (ref.func $b) @@ -236,75 +219,11 @@ # Try (try (result i32) (do - (i32.const 1) - ) - (catch $tag1 - (i32.const 2) - ) - (catch_all (i32.const 3) ) -) - -(try (result i32) - (do - (i32.const 4) - ) - (catch $tag1 - (i32.const 5) - ) -) - -(try (result i32) - (do + (catch (i32.const 4) ) - (catch $tag1 - (i32.const 6) - ) - (catch $tag2 - (i32.const 5) - ) -) - -(try (result i32) - (do - (i32.const 4) - ) - (catch $tag1 - (i32.const 6) - ) -) - -(try (result i32) - (do - (i32.const 4) - ) - (catch $tag2 - (i32.const 8) - ) - (catch $tag1 - (i32.const 10) - ) -) - -(try (result i32) - (do - (i32.const 4) - ) - (catch $tag2 - (i32.const 8) - ) - (catch $tag1 - (i32.const 10) - ) -) - -(try (result i32) - (do - (i32.const 4) - ) - (delegate $try_outer) ) # Throw @@ -314,7 +233,14 @@ ) # Rethrow -(rethrow $l1) +(rethrow + (local.get $2) +) + +# BrOnExn +(br_on_exn $bar $event2 + (local.get $2) +) # TupleMake (tuple.make diff -Nru binaryen-108/test/binaryen.js/inlining-options.js.txt binaryen-99/test/binaryen.js/inlining-options.js.txt --- binaryen-108/test/binaryen.js/inlining-options.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/inlining-options.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,4 @@ // alwaysInlineMaxSize=2 // flexibleInlineMaxSize=20 -// oneCallerInlineMaxSize=-1 +// oneCallerInlineMaxSize=15 // allowInliningFunctionsWithLoops=false diff -Nru binaryen-108/test/binaryen.js/kitchen-sink.js binaryen-99/test/binaryen.js/kitchen-sink.js --- binaryen-108/test/binaryen.js/kitchen-sink.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/kitchen-sink.js 2021-01-07 20:01:06.000000000 +0000 @@ -74,6 +74,9 @@ console.log(" // BinaryenTypeExternref: " + binaryen.externref); console.log(" //", binaryen.expandType(binaryen.externref).join(",")); + console.log(" // BinaryenTypeExnref: " + binaryen.exnref); + console.log(" //", binaryen.expandType(binaryen.exnref).join(",")); + console.log(" // BinaryenTypeAnyref: " + binaryen.anyref); console.log(" //", binaryen.expandType(binaryen.anyref).join(",")); @@ -83,9 +86,6 @@ console.log(" // BinaryenTypeI31ref: " + binaryen.i31ref); console.log(" //", binaryen.expandType(binaryen.i31ref).join(",")); - console.log(" // BinaryenTypeDataref: " + binaryen.dataref); - console.log(" //", binaryen.expandType(binaryen.dataref).join(",")); - console.log(" // BinaryenTypeAuto: " + binaryen.auto); var i32_pair = binaryen.createType([binaryen.i32, binaryen.i32]); @@ -114,9 +114,6 @@ console.log("Features.Multivalue: " + binaryen.Features.Multivalue); console.log("Features.GC: " + binaryen.Features.GC); console.log("Features.Memory64: " + binaryen.Features.Memory64); - console.log("Features.TypedFunctionReferences: " + binaryen.Features.TypedFunctionReferences); - console.log("Features.RelaxedSIMD: " + binaryen.Features.RelaxedSIMD); - console.log("Features.ExtendedConst: " + binaryen.Features.ExtendedConst); console.log("Features.All: " + binaryen.Features.All); } @@ -155,23 +152,19 @@ console.log("SIMDTernaryId: " + binaryen.SIMDTernaryId); console.log("SIMDShiftId: " + binaryen.SIMDShiftId); console.log("SIMDLoadId: " + binaryen.SIMDLoadId); - console.log("SIMDLoadStoreLaneId: " + binaryen.SIMDLoadStoreLaneId); console.log("MemoryInitId: " + binaryen.MemoryInitId); console.log("DataDropId: " + binaryen.DataDropId); console.log("MemoryCopyId: " + binaryen.MemoryCopyId); console.log("MemoryFillId: " + binaryen.MemoryFillId); console.log("PopId: " + binaryen.PopId); console.log("RefNullId: " + binaryen.RefNullId); - console.log("RefIsId: " + binaryen.RefIsId); + console.log("RefIsNullId: " + binaryen.RefIsNullId); console.log("RefFuncId: " + binaryen.RefFuncId); console.log("RefEqId: " + binaryen.RefEqId); - console.log("TableGetId: " + binaryen.TableGetId); - console.log("TableSetId: " + binaryen.TableSetId); - console.log("TableSizeId: " + binaryen.TableSizeId); - console.log("TableGrowId: " + binaryen.TableGrowId); console.log("TryId: " + binaryen.TryId); console.log("ThrowId: " + binaryen.ThrowId); console.log("RethrowId: " + binaryen.RethrowId); + console.log("BrOnExnId: " + binaryen.BrOnExnId); console.log("TupleMakeId: " + binaryen.TupleMakeId); console.log("TupleExtractId: " + binaryen.TupleExtractId); console.log("I31NewId: " + binaryen.I31NewId); @@ -179,14 +172,13 @@ console.log("CallRefId: " + binaryen.CallRefId); console.log("RefTestId: " + binaryen.RefTestId); console.log("RefCastId: " + binaryen.RefCastId); - console.log("BrOnId: " + binaryen.BrOnId); + console.log("BrOnCastId: " + binaryen.BrOnCastId); console.log("RttCanonId: " + binaryen.RttCanonId); console.log("RttSubId: " + binaryen.RttSubId); console.log("StructNewId: " + binaryen.StructNewId); console.log("StructGetId: " + binaryen.StructGetId); console.log("StructSetId: " + binaryen.StructSetId); console.log("ArrayNewId: " + binaryen.ArrayNewId); - console.log("ArrayInitId: " + binaryen.ArrayInitId); console.log("ArrayGetId: " + binaryen.ArrayGetId); console.log("ArraySetId: " + binaryen.ArraySetId); console.log("ArrayLenId: " + binaryen.ArrayLenId); @@ -198,8 +190,8 @@ module = new binaryen.Module(); - // Create a tag - var tag = module.addTag("a-tag", binaryen.i32, binaryen.none); + // Create an event + var event_ = module.addEvent("a-event", 0, binaryen.i32, binaryen.none); // Literals and consts @@ -273,56 +265,44 @@ module.f32x4.splat(module.f32.const(42.0)), module.f64x2.splat(module.f64.const(42.0)), module.v128.not(module.v128.const(v128_bytes)), - module.v128.any_true(module.v128.const(v128_bytes)), - module.i8x16.popcnt(module.v128.const(v128_bytes)), module.i8x16.abs(module.v128.const(v128_bytes)), module.i8x16.neg(module.v128.const(v128_bytes)), + module.i8x16.any_true(module.v128.const(v128_bytes)), module.i8x16.all_true(module.v128.const(v128_bytes)), module.i8x16.bitmask(module.v128.const(v128_bytes)), module.i16x8.abs(module.v128.const(v128_bytes)), module.i16x8.neg(module.v128.const(v128_bytes)), + module.i16x8.any_true(module.v128.const(v128_bytes)), module.i16x8.all_true(module.v128.const(v128_bytes)), module.i16x8.bitmask(module.v128.const(v128_bytes)), - module.i16x8.extadd_pairwise_i8x16_s(module.v128.const(v128_bytes)), - module.i16x8.extadd_pairwise_i8x16_u(module.v128.const(v128_bytes)), module.i32x4.abs(module.v128.const(v128_bytes)), module.i32x4.neg(module.v128.const(v128_bytes)), + module.i32x4.any_true(module.v128.const(v128_bytes)), module.i32x4.all_true(module.v128.const(v128_bytes)), module.i32x4.bitmask(module.v128.const(v128_bytes)), - module.i32x4.extadd_pairwise_i16x8_s(module.v128.const(v128_bytes)), - module.i32x4.extadd_pairwise_i16x8_u(module.v128.const(v128_bytes)), - module.i64x2.abs(module.v128.const(v128_bytes)), module.i64x2.neg(module.v128.const(v128_bytes)), - module.i64x2.all_true(module.v128.const(v128_bytes)), - module.i64x2.bitmask(module.v128.const(v128_bytes)), module.f32x4.abs(module.v128.const(v128_bytes)), module.f32x4.neg(module.v128.const(v128_bytes)), module.f32x4.sqrt(module.v128.const(v128_bytes)), module.f64x2.abs(module.v128.const(v128_bytes)), module.f64x2.neg(module.v128.const(v128_bytes)), module.f64x2.sqrt(module.v128.const(v128_bytes)), - module.f64x2.convert_low_i32x4_s(module.v128.const(v128_bytes)), - module.f64x2.convert_low_i32x4_u(module.v128.const(v128_bytes)), - module.f64x2.promote_low_f32x4(module.v128.const(v128_bytes)), module.i32x4.trunc_sat_f32x4_s(module.v128.const(v128_bytes)), module.i32x4.trunc_sat_f32x4_u(module.v128.const(v128_bytes)), + module.i64x2.trunc_sat_f64x2_s(module.v128.const(v128_bytes)), + module.i64x2.trunc_sat_f64x2_u(module.v128.const(v128_bytes)), module.f32x4.convert_i32x4_s(module.v128.const(v128_bytes)), module.f32x4.convert_i32x4_u(module.v128.const(v128_bytes)), - module.f32x4.demote_f64x2_zero(module.v128.const(v128_bytes)), - module.i16x8.extend_low_i8x16_s(module.v128.const(v128_bytes)), - module.i16x8.extend_high_i8x16_s(module.v128.const(v128_bytes)), - module.i16x8.extend_low_i8x16_u(module.v128.const(v128_bytes)), - module.i16x8.extend_high_i8x16_u(module.v128.const(v128_bytes)), - module.i32x4.extend_low_i16x8_s(module.v128.const(v128_bytes)), - module.i32x4.extend_high_i16x8_s(module.v128.const(v128_bytes)), - module.i32x4.extend_low_i16x8_u(module.v128.const(v128_bytes)), - module.i32x4.extend_high_i16x8_u(module.v128.const(v128_bytes)), - module.i32x4.trunc_sat_f64x2_s_zero(module.v128.const(v128_bytes)), - module.i32x4.trunc_sat_f64x2_u_zero(module.v128.const(v128_bytes)), - module.i64x2.extend_low_i32x4_s(module.v128.const(v128_bytes)), - module.i64x2.extend_high_i32x4_s(module.v128.const(v128_bytes)), - module.i64x2.extend_low_i32x4_u(module.v128.const(v128_bytes)), - module.i64x2.extend_high_i32x4_u(module.v128.const(v128_bytes)), + module.f64x2.convert_i64x2_s(module.v128.const(v128_bytes)), + module.f64x2.convert_i64x2_u(module.v128.const(v128_bytes)), + module.i16x8.widen_low_i8x16_s(module.v128.const(v128_bytes)), + module.i16x8.widen_high_i8x16_s(module.v128.const(v128_bytes)), + module.i16x8.widen_low_i8x16_u(module.v128.const(v128_bytes)), + module.i16x8.widen_high_i8x16_u(module.v128.const(v128_bytes)), + module.i32x4.widen_low_i16x8_s(module.v128.const(v128_bytes)), + module.i32x4.widen_high_i16x8_s(module.v128.const(v128_bytes)), + module.i32x4.widen_low_i16x8_u(module.v128.const(v128_bytes)), + module.i32x4.widen_high_i16x8_u(module.v128.const(v128_bytes)), // Binary module.i32.add(module.i32.const(-10), module.i32.const(-11)), module.f64.sub(module.f64.const(-9005.841), module.f64.const(-9007.333)), @@ -386,12 +366,6 @@ module.i32x4.le_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.ge_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.ge_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.eq(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.ne(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.lt_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.gt_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.le_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.ge_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.f32x4.eq(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.f32x4.ne(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.f32x4.lt(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), @@ -414,6 +388,7 @@ module.i8x16.sub(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i8x16.sub_saturate_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i8x16.sub_saturate_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), + module.i8x16.mul(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i8x16.min_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i8x16.min_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i8x16.max_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), @@ -431,11 +406,6 @@ module.i16x8.max_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i16x8.max_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i16x8.avgr_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i16x8.q15mulr_sat_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i16x8.extmul_low_i8x16_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i16x8.extmul_high_i8x16_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i16x8.extmul_low_i8x16_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i16x8.extmul_high_i8x16_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.add(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.sub(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.mul(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), @@ -444,17 +414,9 @@ module.i32x4.max_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.max_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i32x4.dot_i16x8_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i32x4.extmul_low_i16x8_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i32x4.extmul_high_i16x8_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i32x4.extmul_low_i16x8_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i32x4.extmul_high_i16x8_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i64x2.add(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i64x2.sub(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i64x2.mul(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.extmul_low_i32x4_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.extmul_high_i32x4_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.extmul_low_i32x4_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i64x2.extmul_high_i32x4_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.f32x4.add(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.f32x4.sub(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.f32x4.mul(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), @@ -483,7 +445,7 @@ module.i8x16.narrow_i16x8_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i16x8.narrow_i32x4_s(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), module.i16x8.narrow_i32x4_u(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), - module.i8x16.swizzle(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), + module.v8x16.swizzle(module.v128.const(v128_bytes), module.v128.const(v128_bytes)), // SIMD lane manipulation module.i8x16.extract_lane_s(module.v128.const(v128_bytes), 1), module.i8x16.extract_lane_u(module.v128.const(v128_bytes), 1), @@ -513,38 +475,23 @@ module.i64x2.shr_s(module.v128.const(v128_bytes), module.i32.const(1)), module.i64x2.shr_u(module.v128.const(v128_bytes), module.i32.const(1)), // SIMD load - module.v128.load8_splat(0, 1, module.i32.const(128)), - module.v128.load16_splat(16, 1, module.i32.const(128)), - module.v128.load32_splat(16, 4, module.i32.const(128)), - module.v128.load64_splat(0, 4, module.i32.const(128)), - module.v128.load8x8_s(0, 8, module.i32.const(128)), - module.v128.load8x8_u(0, 8, module.i32.const(128)), - module.v128.load16x4_s(0, 8, module.i32.const(128)), - module.v128.load16x4_u(0, 8, module.i32.const(128)), - module.v128.load32x2_s(0, 8, module.i32.const(128)), - module.v128.load32x2_u(0, 8, module.i32.const(128)), - module.v128.load32_zero(0, 4, module.i32.const(128)), - module.v128.load64_zero(0, 8, module.i32.const(128)), - // SIMD load/store lane - module.v128.load8_lane(0, 1, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load8_lane(1, 1, 15, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load16_lane(0, 2, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load16_lane(2, 1, 7, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load32_lane(0, 4, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load32_lane(4, 2, 3, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load64_lane(0, 8, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.load64_lane(8, 4, 1, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store8_lane(0, 1, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store8_lane(1, 1, 15, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store16_lane(0, 2, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store16_lane(2, 1, 7, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store32_lane(0, 4, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store32_lane(4, 2, 3, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store64_lane(0, 8, 0, module.i32.const(128), module.v128.const(v128_bytes)), - module.v128.store64_lane(8, 4, 1, module.i32.const(128), module.v128.const(v128_bytes)), + module.v8x16.load_splat(0, 1, module.i32.const(128)), + module.v16x8.load_splat(16, 1, module.i32.const(128)), + module.v32x4.load_splat(16, 4, module.i32.const(128)), + module.v64x2.load_splat(0, 4, module.i32.const(128)), + module.i16x8.load8x8_s(0, 8, module.i32.const(128)), + module.i16x8.load8x8_u(0, 8, module.i32.const(128)), + module.i32x4.load16x4_s(0, 8, module.i32.const(128)), + module.i32x4.load16x4_u(0, 8, module.i32.const(128)), + module.i64x2.load32x2_s(0, 8, module.i32.const(128)), + module.i64x2.load32x2_u(0, 8, module.i32.const(128)), // Other SIMD - module.i8x16.shuffle(module.v128.const(v128_bytes), module.v128.const(v128_bytes), v128_bytes), + module.v8x16.shuffle(module.v128.const(v128_bytes), module.v128.const(v128_bytes), v128_bytes), module.v128.bitselect(module.v128.const(v128_bytes), module.v128.const(v128_bytes), module.v128.const(v128_bytes)), + module.f32x4.qfma(module.v128.const(v128_bytes), module.v128.const(v128_bytes), module.v128.const(v128_bytes)), + module.f32x4.qfms(module.v128.const(v128_bytes), module.v128.const(v128_bytes), module.v128.const(v128_bytes)), + module.f64x2.qfma(module.v128.const(v128_bytes), module.v128.const(v128_bytes), module.v128.const(v128_bytes)), + module.f64x2.qfms(module.v128.const(v128_bytes), module.v128.const(v128_bytes), module.v128.const(v128_bytes)), // Bulk memory module.memory.init(0, makeInt32(1024), makeInt32(0), makeInt32(12)), module.data.drop(0), @@ -571,7 +518,7 @@ ) ), module.i32.eqz( // check the output type of the call node - module.call_indirect("t0", makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32) + module.call_indirect(makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32) ), module.drop(module.local.get(0, binaryen.i32)), module.local.set(0, makeInt32(101)), @@ -586,7 +533,7 @@ module.return(makeInt32(1337)), // Tail Call module.return_call("kitchen()sinker", [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], binaryen.i32), - module.return_call_indirect("t0", makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32), + module.return_call_indirect(makeInt32(2449), [ makeInt32(13), makeInt64(37, 0), makeFloat32(1.3), makeFloat64(3.7) ], iIfF, binaryen.i32), // Reference types module.ref.is_null(module.ref.null(binaryen.externref)), @@ -599,11 +546,19 @@ // Exception handling module.try( - '', - module.throw("a-tag", [module.i32.const(0)]), - ["a-tag"], - [module.drop(module.i32.pop())], - '' + module.throw("a-event", [module.i32.const(0)]), + module.block(null, [ + module.local.set(5, module.exnref.pop()), + module.drop( + module.block("try-block", [ + module.rethrow( + module.br_on_exn("try-block", "a-event", + module.local.get(5, binaryen.exnref)), + ) + ], binaryen.i32) + ) + ] + ) ), // Atomics @@ -646,10 +601,10 @@ module.v128.pop(), module.funcref.pop(), module.externref.pop(), + module.exnref.pop(), module.anyref.pop(), module.eqref.pop(), module.i31ref.pop(), - module.dataref.pop(), // Memory module.memory.size(), @@ -697,7 +652,7 @@ var body = module.block("the-body", [ nothing, makeInt32(42) ]); // Create the function - var sinker = module.addFunction("kitchen()sinker", iIfF, binaryen.i32, [ binaryen.i32 ], body); + var sinker = module.addFunction("kitchen()sinker", iIfF, binaryen.i32, [ binaryen.i32, binaryen.exnref ], body); // Create a global var initExpr = module.i32.const(1); @@ -709,34 +664,17 @@ module.addFunctionImport("an-imported", "module", "base", iF, binaryen.f32); module.addGlobalImport("a-global-imp", "module", "base", binaryen.i32, false); module.addGlobalImport("a-mut-global-imp", "module", "base", binaryen.i32, true); - module.addTagImport("a-tag-imp", "module", "base", binaryen.i32, binaryen.none); + module.addEventImport("a-event-imp", "module", "base", 0, binaryen.i32, binaryen.none); // Exports module.addFunctionExport("kitchen()sinker", "kitchen_sinker"); module.addGlobalExport("a-global", "a-global-exp"); - module.addTagExport("a-tag", "a-tag-exp"); + module.addEventExport("a-event", "a-event-exp"); + + // Function table. One per module - // Tables - module.addTable("t1", 0, 2); - var tablePtr = module.getTable("t1"); - assert(tablePtr !== 0); - assert(tablePtr === module.getTableByIndex(0)); - - var table = binaryen.getTableInfo(tablePtr); - assert(table.name === "t1"); - assert(table.module === ""); - assert(table.base === ""); - assert(table.initial === 0); - assert(table.max === 2); - - module.removeTable("t1"); - assert(module.getNumTables() === 0); - - module.addTable("t0", 1, 0xffffffff); - module.addActiveElementSegment("t0", "e0", [ binaryen.getFunctionInfo(sinker).name ]); - assert(module.getNumTables() === 1); - assert(module.getNumElementSegments() === 1); + module.setFunctionTable(1, 0xffffffff, [ binaryen.getFunctionInfo(sinker).name ]); // Memory. One per module @@ -840,7 +778,7 @@ var block0 = relooper.addBlock(makeCallCheck(0)); var block1 = relooper.addBlock(makeCallCheck(1)); var block2 = relooper.addBlock(makeCallCheck(2)); - var temp = makeDroppedInt32(10); + temp = makeDroppedInt32(10); relooper.addBranch(block0, block1, makeInt32(55), temp); relooper.addBranch(block0, block2, null, makeDroppedInt32(20)); var body = relooper.renderAndDispose(block0, 0, module); @@ -980,7 +918,7 @@ var adder = module.addFunction("adder", ii, binaryen.i32, [], add); var initExpr = module.i32.const(3); var global = module.addGlobal("a-global", binaryen.i32, false, initExpr) - var tag = module.addTag("a-tag", binaryen.createType([binaryen.i32, binaryen.i32]), binaryen.none); + var event_ = module.addEvent("a-event", 0, binaryen.createType([binaryen.i32, binaryen.i32]), binaryen.none); binaryen.setDebugInfo(true); // include names section buffer = module.emitBinary(); binaryen.setDebugInfo(false); @@ -1007,7 +945,7 @@ module = new binaryen.Module(); module.addFunctionImport("print-i32", "spectest", "print", binaryen.i32, binaryen.none); - var call = module.call("print-i32", [ makeInt32(1234) ], binaryen.None); + call = module.call("print-i32", [ makeInt32(1234) ], binaryen.None); var starter = module.addFunction("starter", binaryen.none, binaryen.none, [], call); module.setStart(starter); @@ -1045,7 +983,7 @@ var adder = module.addFunction("adder", ii, binaryen.i32, [], add); var initExpr = module.i32.const(3); var global = module.addGlobal("a-global", binaryen.i32, false, initExpr) - var tag = module.addTag("a-tag", binaryen.i32, binaryen.none); + var event_ = module.addEvent("a-event", 0, binaryen.i32, binaryen.none); text = module.emitText(); module.dispose(); module = null; @@ -1126,23 +1064,16 @@ assert(expected_passive[i] === segment.passive); } - module.addTable("t0", 1, 0xffffffff); - var ftable = module.getTable("t0"); var constExprRef = module.i32.const(0); - module.addActiveElementSegment("t0", "e0", funcNames, constExprRef); + module.setFunctionTable(1, 0xffffffff, funcNames, constExprRef); - var tableInfo = binaryen.getTableInfo(ftable); - assert("" === tableInfo.module); - assert("" === tableInfo.base); - - var segments = module.getTableSegments(ftable); - assert(1 === segments.length); - - var elemSegment = binaryen.getElementSegmentInfo(segments[0]); - assert(constExprRef === elemSegment.offset); - assert(3 === elemSegment.data.length); - for (i = 0; i < elemSegment.data.length; i++) { - assert(funcNames[i] === elemSegment.data[i]); + var ftable = module.getFunctionTable(); + assert(false === ftable.imported); + assert(1 === ftable.segments.length); + assert(constExprRef === ftable.segments[0].offset); + assert(3 === ftable.segments[0].names.length); + for (i = 0; i < ftable.segments[0].names.length; i++) { + assert(funcNames[i] === ftable.segments[0].names[i]); } console.log(module.emitText()); diff -Nru binaryen-108/test/binaryen.js/kitchen-sink.js.txt binaryen-99/test/binaryen.js/kitchen-sink.js.txt --- binaryen-108/test/binaryen.js/kitchen-sink.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/kitchen-sink.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -16,14 +16,14 @@ // 7 // BinaryenTypeExternref: 8 // 8 - // BinaryenTypeAnyref: 8 - // 8 - // BinaryenTypeEqref: 9 + // BinaryenTypeExnref: 9 // 9 - // BinaryenTypeI31ref: 10 + // BinaryenTypeAnyref: 10 // 10 - // BinaryenTypeDataref: 11 + // BinaryenTypeEqref: 11 // 11 + // BinaryenTypeI31ref: 12 + // 12 // BinaryenTypeAuto: -1 // 2,2 // 2,2 @@ -41,10 +41,7 @@ Features.Multivalue: 512 Features.GC: 1024 Features.Memory64: 2048 -Features.TypedFunctionReferences: 4096 -Features.RelaxedSIMD: 16384 -Features.ExtendedConst: 32768 -Features.All: 57343 +Features.All: 8191 InvalidId: 0 BlockId: 1 IfId: 2 @@ -68,52 +65,47 @@ MemorySizeId: 20 MemoryGrowId: 21 NopId: 22 -UnreachableId: 23 -AtomicCmpxchgId: 25 -AtomicRMWId: 24 -AtomicWaitId: 26 -AtomicNotifyId: 27 -SIMDExtractId: 29 -SIMDReplaceId: 30 -SIMDShuffleId: 31 -SIMDTernaryId: 32 -SIMDShiftId: 33 -SIMDLoadId: 34 -SIMDLoadStoreLaneId: 35 -MemoryInitId: 36 -DataDropId: 37 -MemoryCopyId: 38 -MemoryFillId: 39 -PopId: 40 -RefNullId: 41 -RefIsId: 42 -RefFuncId: 43 -RefEqId: 44 -TableGetId: 45 -TableSetId: 46 -TableSizeId: 47 -TableGrowId: 48 -TryId: 49 -ThrowId: 50 -RethrowId: 51 -TupleMakeId: 52 -TupleExtractId: 53 -I31NewId: 54 -I31GetId: 55 -CallRefId: 56 -RefTestId: 57 -RefCastId: 58 -BrOnId: 59 -RttCanonId: 60 -RttSubId: 61 -StructNewId: 62 -StructGetId: 63 -StructSetId: 64 -ArrayNewId: 65 -ArrayInitId: 66 -ArrayGetId: 67 -ArraySetId: 68 -ArrayLenId: 69 +UnreachableId: 24 +AtomicCmpxchgId: 26 +AtomicRMWId: 25 +AtomicWaitId: 27 +AtomicNotifyId: 28 +SIMDExtractId: 30 +SIMDReplaceId: 31 +SIMDShuffleId: 32 +SIMDTernaryId: 33 +SIMDShiftId: 34 +SIMDLoadId: 35 +MemoryInitId: 37 +DataDropId: 38 +MemoryCopyId: 39 +MemoryFillId: 40 +PopId: 41 +RefNullId: 42 +RefIsNullId: 43 +RefFuncId: 44 +RefEqId: 45 +TryId: 46 +ThrowId: 47 +RethrowId: 48 +BrOnExnId: 49 +TupleMakeId: 50 +TupleExtractId: 51 +I31NewId: 52 +I31GetId: 53 +CallRefId: 54 +RefTestId: 55 +RefCastId: 56 +BrOnCastId: 57 +RttCanonId: 58 +RttSubId: 59 +StructNewId: 60 +StructGetId: 61 +StructSetId: 62 +ArrayNewId: 63 +ArrayGetId: 64 +ArraySetId: 65 +ArrayLenId: 66 getExpressionInfo={"id":15,"type":4,"op":6} (f32.neg (f32.const -33.61199951171875) @@ -130,26 +122,27 @@ (module (type $i32_i64_f32_f64_=>_i32 (func (param i32 i64 f32 f64) (result i32))) (type $i32_=>_none (func (param i32))) - (type $i32_f64_=>_f32 (func (param i32 f64) (result f32))) (type $none_=>_none (func)) + (type $i32_f64_=>_f32 (func (param i32 f64) (result f32))) (import "module" "base" (global $a-global-imp i32)) (import "module" "base" (global $a-mut-global-imp (mut i32))) (import "module" "base" (func $an-imported (param i32 f64) (result f32))) - (import "module" "base" (tag $a-tag-imp (param i32))) - (global $a-global i32 (i32.const 1)) + (import "module" "base" (event $a-event-imp (attr 0) (param i32))) (memory $0 (shared 1 256)) (data (i32.const 10) "hello, world") - (data "I am passive") - (table $t0 1 funcref) - (elem $e0 (i32.const 0) "$kitchen()sinker") - (tag $a-tag (param i32)) + (data passive "I am passive") + (table $0 1 funcref) + (elem (i32.const 0) "$kitchen()sinker") + (global $a-global i32 (i32.const 1)) + (event $a-event (attr 0) (param i32)) (export "kitchen_sinker" (func "$kitchen()sinker")) (export "a-global-exp" (global $a-global)) - (export "a-tag-exp" (tag $a-tag)) + (export "a-event-exp" (event $a-event)) (export "mem" (memory $0)) (start $starter) (func "$kitchen()sinker" (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32) (local $4 i32) + (local $5 exnref) (block $the-body (result i32) (block $the-nothing (drop @@ -410,22 +403,17 @@ ) ) (drop - (v128.any_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i8x16.popcnt + (i8x16.abs (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.abs + (i8x16.neg (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.neg + (i8x16.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -450,22 +438,17 @@ ) ) (drop - (i16x8.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.bitmask + (i16x8.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extadd_pairwise_i8x16_s + (i16x8.all_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extadd_pairwise_i8x16_u + (i16x8.bitmask (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -480,27 +463,17 @@ ) ) (drop - (i32x4.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.bitmask - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extadd_pairwise_i16x8_s + (i32x4.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extadd_pairwise_i16x8_u + (i32x4.all_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.abs + (i32x4.bitmask (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -510,16 +483,6 @@ ) ) (drop - (i64x2.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.bitmask - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.abs (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -550,21 +513,6 @@ ) ) (drop - (f64x2.convert_low_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (f64x2.convert_low_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (f64x2.promote_low_f32x4 - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i32x4.trunc_sat_f32x4_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -575,87 +523,72 @@ ) ) (drop - (f32x4.convert_i32x4_s + (i64x2.trunc_sat_f64x2_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f32x4.convert_i32x4_u + (i64x2.trunc_sat_f64x2_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f32x4.demote_f64x2_zero - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_low_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_high_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_low_i8x16_u + (f32x4.convert_i32x4_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extend_high_i8x16_u + (f32x4.convert_i32x4_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_low_i16x8_s + (f64x2.convert_i64x2_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_high_i16x8_s + (f64x2.convert_i64x2_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_low_i16x8_u + (i16x8.widen_low_i8x16_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_high_i16x8_u + (i16x8.widen_high_i8x16_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.trunc_sat_f64x2_s_zero + (i16x8.widen_low_i8x16_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.trunc_sat_f64x2_u_zero + (i16x8.widen_high_i8x16_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_low_i32x4_s + (i32x4.widen_low_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_high_i32x4_s + (i32x4.widen_high_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_low_i32x4_u + (i32x4.widen_low_i16x8_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_high_i32x4_u + (i32x4.widen_high_i16x8_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -1032,42 +965,6 @@ ) ) (drop - (i64x2.eq - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.ne - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.lt_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.gt_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.le_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.ge_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.eq (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1170,13 +1067,13 @@ ) ) (drop - (i8x16.add_sat_s + (i8x16.add_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.add_sat_u + (i8x16.add_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1188,13 +1085,19 @@ ) ) (drop - (i8x16.sub_sat_s + (i8x16.sub_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.sub_sat_u + (i8x16.sub_saturate_u + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + ) + ) + (drop + (i8x16.mul (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1236,13 +1139,13 @@ ) ) (drop - (i16x8.add_sat_s + (i16x8.add_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.add_sat_u + (i16x8.add_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1254,13 +1157,13 @@ ) ) (drop - (i16x8.sub_sat_s + (i16x8.sub_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.sub_sat_u + (i16x8.sub_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1302,36 +1205,6 @@ ) ) (drop - (i16x8.q15mulr_sat_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_low_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_high_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_low_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_high_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i32x4.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1380,30 +1253,6 @@ ) ) (drop - (i32x4.extmul_low_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_high_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_low_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_high_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i64x2.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1422,30 +1271,6 @@ ) ) (drop - (i64x2.extmul_low_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_high_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_low_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_high_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1606,7 +1431,7 @@ ) ) (drop - (i8x16.swizzle + (v8x16.swizzle (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1760,153 +1585,91 @@ ) ) (drop - (v128.load8_splat - (i32.const 128) - ) - ) - (drop - (v128.load16_splat offset=16 align=1 - (i32.const 128) - ) - ) - (drop - (v128.load32_splat offset=16 + (v8x16.load_splat (i32.const 128) ) ) (drop - (v128.load64_splat align=4 + (v16x8.load_splat offset=16 align=1 (i32.const 128) ) ) (drop - (v128.load8x8_s + (v32x4.load_splat offset=16 (i32.const 128) ) ) (drop - (v128.load8x8_u + (v64x2.load_splat align=4 (i32.const 128) ) ) (drop - (v128.load16x4_s + (i16x8.load8x8_s (i32.const 128) ) ) (drop - (v128.load16x4_u + (i16x8.load8x8_u (i32.const 128) ) ) (drop - (v128.load32x2_s + (i32x4.load16x4_s (i32.const 128) ) ) (drop - (v128.load32x2_u + (i32x4.load16x4_u (i32.const 128) ) ) (drop - (v128.load32_zero + (i64x2.load32x2_s (i32.const 128) ) ) (drop - (v128.load64_zero + (i64x2.load32x2_u (i32.const 128) ) ) (drop - (v128.load8_lane 0 - (i32.const 128) + (v8x16.shuffle 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load8_lane offset=1 15 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load16_lane 0 - (i32.const 128) + (v128.bitselect (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load16_lane offset=2 align=1 7 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load32_lane 0 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load32_lane offset=4 align=2 3 - (i32.const 128) + (f32x4.qfma + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load64_lane 0 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load64_lane offset=8 align=4 1 - (i32.const 128) + (f32x4.qfms + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) - (v128.store8_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store8_lane offset=1 15 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store16_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store16_lane offset=2 align=1 7 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store32_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store32_lane offset=4 align=2 3 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store64_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store64_lane offset=8 align=4 1 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) (drop - (i8x16.shuffle 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + (f64x2.qfma + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.bitselect + (f64x2.qfms (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1997,7 +1760,7 @@ ) (drop (i32.eqz - (call_indirect $t0 (type $i32_i64_f32_f64_=>_i32) + (call_indirect (type $i32_i64_f32_f64_=>_i32) (i32.const 13) (i64.const 37) (f32.const 1.2999999523162842) @@ -2061,7 +1824,7 @@ (f32.const 1.2999999523162842) (f64.const 3.7) ) - (return_call_indirect $t0 (type $i32_i64_f32_f64_=>_i32) + (return_call_indirect (type $i32_i64_f32_f64_=>_i32) (i32.const 13) (i64.const 37) (f32.const 1.2999999523162842) @@ -2070,7 +1833,7 @@ ) (drop (ref.is_null - (ref.null any) + (ref.null extern) ) ) (drop @@ -2098,13 +1861,22 @@ ) (try (do - (throw $a-tag + (throw $a-event (i32.const 0) ) ) - (catch $a-tag + (catch + (local.set $5 + (pop exnref) + ) (drop - (pop i32) + (block $try-block (result i32) + (rethrow + (br_on_exn $try-block $a-event + (local.get $5) + ) + ) + ) ) ) ) @@ -2165,7 +1937,10 @@ (pop funcref) ) (drop - (pop anyref) + (pop externref) + ) + (drop + (pop exnref) ) (drop (pop anyref) @@ -2177,9 +1952,6 @@ (pop i31ref) ) (drop - (pop dataref) - ) - (drop (memory.size) ) (drop @@ -2222,26 +1994,27 @@ (module (type $i32_i64_f32_f64_=>_i32 (func (param i32 i64 f32 f64) (result i32))) (type $i32_=>_none (func (param i32))) - (type $i32_f64_=>_f32 (func (param i32 f64) (result f32))) (type $none_=>_none (func)) + (type $i32_f64_=>_f32 (func (param i32 f64) (result f32))) (import "module" "base" (global $a-global-imp i32)) (import "module" "base" (global $a-mut-global-imp (mut i32))) (import "module" "base" (func $an-imported (param i32 f64) (result f32))) - (import "module" "base" (tag $a-tag-imp (param i32))) - (global $a-global i32 (i32.const 1)) + (import "module" "base" (event $a-event-imp (attr 0) (param i32))) (memory $0 (shared 1 256)) (data (i32.const 10) "hello, world") - (data "I am passive") - (table $t0 1 funcref) - (elem $e0 (i32.const 0) "$kitchen()sinker") - (tag $a-tag (param i32)) + (data passive "I am passive") + (table $0 1 funcref) + (elem (i32.const 0) "$kitchen()sinker") + (global $a-global i32 (i32.const 1)) + (event $a-event (attr 0) (param i32)) (export "kitchen_sinker" (func "$kitchen()sinker")) (export "a-global-exp" (global $a-global)) - (export "a-tag-exp" (tag $a-tag)) + (export "a-event-exp" (event $a-event)) (export "mem" (memory $0)) (start $starter) (func "$kitchen()sinker" (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32) (local $4 i32) + (local $5 exnref) (block $the-body (result i32) (block $the-nothing (drop @@ -2502,22 +2275,17 @@ ) ) (drop - (v128.any_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i8x16.popcnt + (i8x16.abs (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.abs + (i8x16.neg (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.neg + (i8x16.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -2542,22 +2310,17 @@ ) ) (drop - (i16x8.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.bitmask + (i16x8.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extadd_pairwise_i8x16_s + (i16x8.all_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extadd_pairwise_i8x16_u + (i16x8.bitmask (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -2572,27 +2335,17 @@ ) ) (drop - (i32x4.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.bitmask + (i32x4.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extadd_pairwise_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extadd_pairwise_i16x8_u + (i32x4.all_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.abs + (i32x4.bitmask (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -2602,16 +2355,6 @@ ) ) (drop - (i64x2.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.bitmask - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.abs (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -2642,21 +2385,6 @@ ) ) (drop - (f64x2.convert_low_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (f64x2.convert_low_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (f64x2.promote_low_f32x4 - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i32x4.trunc_sat_f32x4_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -2667,87 +2395,72 @@ ) ) (drop - (f32x4.convert_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (f32x4.convert_i32x4_u + (i64x2.trunc_sat_f64x2_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f32x4.demote_f64x2_zero + (i64x2.trunc_sat_f64x2_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extend_low_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_high_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_low_i8x16_u + (f32x4.convert_i32x4_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extend_high_i8x16_u + (f32x4.convert_i32x4_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_low_i16x8_s + (f64x2.convert_i64x2_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_high_i16x8_s + (f64x2.convert_i64x2_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_low_i16x8_u + (i16x8.widen_low_i8x16_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_high_i16x8_u + (i16x8.widen_high_i8x16_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.trunc_sat_f64x2_s_zero + (i16x8.widen_low_i8x16_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.trunc_sat_f64x2_u_zero + (i16x8.widen_high_i8x16_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_low_i32x4_s + (i32x4.widen_low_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_high_i32x4_s + (i32x4.widen_high_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_low_i32x4_u + (i32x4.widen_low_i16x8_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_high_i32x4_u + (i32x4.widen_high_i16x8_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -3124,42 +2837,6 @@ ) ) (drop - (i64x2.eq - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.ne - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.lt_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.gt_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.le_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.ge_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.eq (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -3262,13 +2939,13 @@ ) ) (drop - (i8x16.add_sat_s + (i8x16.add_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.add_sat_u + (i8x16.add_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -3280,13 +2957,19 @@ ) ) (drop - (i8x16.sub_sat_s + (i8x16.sub_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.sub_sat_u + (i8x16.sub_saturate_u + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + ) + ) + (drop + (i8x16.mul (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -3328,13 +3011,13 @@ ) ) (drop - (i16x8.add_sat_s + (i16x8.add_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.add_sat_u + (i16x8.add_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -3346,13 +3029,13 @@ ) ) (drop - (i16x8.sub_sat_s + (i16x8.sub_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.sub_sat_u + (i16x8.sub_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -3394,36 +3077,6 @@ ) ) (drop - (i16x8.q15mulr_sat_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_low_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_high_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_low_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_high_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i32x4.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -3472,30 +3125,6 @@ ) ) (drop - (i32x4.extmul_low_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_high_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_low_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_high_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i64x2.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -3514,30 +3143,6 @@ ) ) (drop - (i64x2.extmul_low_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_high_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_low_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_high_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -3698,7 +3303,7 @@ ) ) (drop - (i8x16.swizzle + (v8x16.swizzle (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -3852,153 +3457,91 @@ ) ) (drop - (v128.load8_splat - (i32.const 128) - ) - ) - (drop - (v128.load16_splat offset=16 align=1 + (v8x16.load_splat (i32.const 128) ) ) (drop - (v128.load32_splat offset=16 + (v16x8.load_splat offset=16 align=1 (i32.const 128) ) ) (drop - (v128.load64_splat align=4 + (v32x4.load_splat offset=16 (i32.const 128) ) ) (drop - (v128.load8x8_s + (v64x2.load_splat align=4 (i32.const 128) ) ) (drop - (v128.load8x8_u + (i16x8.load8x8_s (i32.const 128) ) ) (drop - (v128.load16x4_s + (i16x8.load8x8_u (i32.const 128) ) ) (drop - (v128.load16x4_u + (i32x4.load16x4_s (i32.const 128) ) ) (drop - (v128.load32x2_s + (i32x4.load16x4_u (i32.const 128) ) ) (drop - (v128.load32x2_u + (i64x2.load32x2_s (i32.const 128) ) ) (drop - (v128.load32_zero + (i64x2.load32x2_u (i32.const 128) ) ) (drop - (v128.load64_zero - (i32.const 128) - ) - ) - (drop - (v128.load8_lane 0 - (i32.const 128) + (v8x16.shuffle 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load8_lane offset=1 15 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load16_lane 0 - (i32.const 128) + (v128.bitselect (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load16_lane offset=2 align=1 7 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load32_lane 0 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load32_lane offset=4 align=2 3 - (i32.const 128) + (f32x4.qfma + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (v128.load64_lane 0 - (i32.const 128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load64_lane offset=8 align=4 1 - (i32.const 128) + (f32x4.qfms + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) - (v128.store8_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store8_lane offset=1 15 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store16_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store16_lane offset=2 align=1 7 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store32_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store32_lane offset=4 align=2 3 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store64_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store64_lane offset=8 align=4 1 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) (drop - (i8x16.shuffle 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 + (f64x2.qfma + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.bitselect + (f64x2.qfms (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -4089,7 +3632,7 @@ ) (drop (i32.eqz - (call_indirect $t0 (type $i32_i64_f32_f64_=>_i32) + (call_indirect (type $i32_i64_f32_f64_=>_i32) (i32.const 13) (i64.const 37) (f32.const 1.2999999523162842) @@ -4153,7 +3696,7 @@ (f32.const 1.2999999523162842) (f64.const 3.7) ) - (return_call_indirect $t0 (type $i32_i64_f32_f64_=>_i32) + (return_call_indirect (type $i32_i64_f32_f64_=>_i32) (i32.const 13) (i64.const 37) (f32.const 1.2999999523162842) @@ -4162,7 +3705,7 @@ ) (drop (ref.is_null - (ref.null any) + (ref.null extern) ) ) (drop @@ -4190,13 +3733,22 @@ ) (try (do - (throw $a-tag + (throw $a-event (i32.const 0) ) ) - (catch $a-tag + (catch + (local.set $5 + (pop exnref) + ) (drop - (pop i32) + (block $try-block (result i32) + (rethrow + (br_on_exn $try-block $a-event + (local.get $5) + ) + ) + ) ) ) ) @@ -4257,7 +3809,10 @@ (pop funcref) ) (drop - (pop anyref) + (pop externref) + ) + (drop + (pop exnref) ) (drop (pop anyref) @@ -4269,9 +3824,6 @@ (pop i31ref) ) (drop - (pop dataref) - ) - (drop (memory.size) ) (drop @@ -4786,7 +4338,7 @@ (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (global $a-global i32 (i32.const 3)) - (tag $tag$0 (param i32 i32)) + (event $event$0 (attr 0) (param i32 i32)) (func $adder (param $0 i32) (param $1 i32) (result i32) (i32.add (local.get $0) @@ -4796,8 +4348,8 @@ ) (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (import "spectest" "print" (func $print-i32 (param i32))) (start $starter) (func $starter @@ -4828,7 +4380,7 @@ (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (global $a-global i32 (i32.const 3)) - (tag $a-tag (param i32)) + (event $a-event (attr 0) (param i32)) (func $adder (param $0 i32) (param $1 i32) (result i32) (i32.add (local.get $0) @@ -4842,7 +4394,7 @@ (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (global $a-global i32 (i32.const 3)) - (tag $a-tag (param i32)) + (event $a-event (attr 0) (param i32)) (func $ADD_ER (param $0 i32) (param $1 i32) (result i32) (i32.add (local.get $0) @@ -4854,14 +4406,14 @@ sizeof Literal: 24 (module (type $none_=>_none (func)) - (global $a-global i32 (i32.const 125)) - (global $a-global2 i32 (i32.const 2)) - (global $a-global3 i32 (i32.const 3)) (memory $0 1 256) (data (i32.const 10) "hello, world") (data (global.get $a-global) "segment data 2") - (table $t0 1 funcref) - (elem $e0 (i32.const 0) $fn0 $fn1 $fn2) + (table $0 1 funcref) + (elem (i32.const 0) $fn0 $fn1 $fn2) + (global $a-global i32 (i32.const 125)) + (global $a-global2 i32 (i32.const 2)) + (global $a-global3 i32 (i32.const 3)) (export "export0" (func $fn0)) (export "export1" (func $fn1)) (export "export2" (func $fn2)) diff -Nru binaryen-108/test/binaryen.js/optimize-levels.js.txt binaryen-99/test/binaryen.js/optimize-levels.js.txt --- binaryen-108/test/binaryen.js/optimize-levels.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/optimize-levels.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -16,7 +16,7 @@ === unoptimized === (module - (type $i (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 0) (export "test" (func $test)) (func $test (param $0 i32) (result i32) @@ -34,10 +34,14 @@ optimizeLevel=2 shrinkLevel=1 (module - (type $i (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (export "test" (func $test)) (func $test (; has Stack IR ;) (param $0 i32) (result i32) - (local.get $0) + (select + (local.get $0) + (i32.const 0) + (local.get $0) + ) ) ) @@ -45,10 +49,14 @@ optimizeLevel=0 shrinkLevel=0 (module - (type $i (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (export "test" (func $test)) (func $test (param $0 i32) (result i32) - (local.get $0) + (select + (local.get $0) + (i32.const 0) + (local.get $0) + ) ) ) @@ -56,10 +64,14 @@ optimizeLevel=2 shrinkLevel=1 (module - (type $i (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (export "test" (func $test)) (func $test (; has Stack IR ;) (param $0 i32) (result i32) - (local.get $0) + (select + (local.get $0) + (i32.const 0) + (local.get $0) + ) ) ) diff -Nru binaryen-108/test/binaryen.js/reloc.js binaryen-99/test/binaryen.js/reloc.js --- binaryen-108/test/binaryen.js/reloc.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/reloc.js 2021-01-07 20:01:06.000000000 +0000 @@ -15,7 +15,7 @@ var func = module.addFunction("func", binaryen.none, binaryen.none, [], module.nop()); module.addGlobalImport("table_base", "env", "table_base", binaryen.i32, false); -module.addTable("0", 1, -1, binaryen.funcref); -module.addActiveElementSegment("0", "0", [ "func", "func" ], module.global.get("table_base", binaryen.i32)); +module.setFunctionTable(1, -1, [ "func", "func" ], module.global.get("table_base", binaryen.i32)); + assert(module.validate()); console.log(module.emitText()); diff -Nru binaryen-108/test/binaryen.js/reloc.js.txt binaryen-99/test/binaryen.js/reloc.js.txt --- binaryen-108/test/binaryen.js/reloc.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/reloc.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -5,7 +5,7 @@ (memory $0 1) (data (global.get $memory_base) "data data") (table $0 1 funcref) - (elem $0 (global.get $table_base) $func $func) + (elem (global.get $table_base) $func $func) (func $func (nop) ) diff -Nru binaryen-108/test/binaryen.js/sideffects.js binaryen-99/test/binaryen.js/sideffects.js --- binaryen-108/test/binaryen.js/sideffects.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/sideffects.js 2021-01-07 20:01:06.000000000 +0000 @@ -7,44 +7,37 @@ console.log("SideEffects.WritesGlobal=" + binaryen.SideEffects.WritesGlobal); console.log("SideEffects.ReadsMemory=" + binaryen.SideEffects.ReadsMemory); console.log("SideEffects.WritesMemory=" + binaryen.SideEffects.WritesMemory); -console.log("SideEffects.ReadsTable=" + binaryen.SideEffects.ReadsTable); -console.log("SideEffects.WritesTable=" + binaryen.SideEffects.WritesTable); console.log("SideEffects.ImplicitTrap=" + binaryen.SideEffects.ImplicitTrap); console.log("SideEffects.IsAtomic=" + binaryen.SideEffects.IsAtomic); console.log("SideEffects.Throws=" + binaryen.SideEffects.Throws); console.log("SideEffects.DanglingPop=" + binaryen.SideEffects.DanglingPop); -console.log("SideEffects.TrapsNeverHappen=" + binaryen.SideEffects.TrapsNeverHappen); console.log("SideEffects.Any=" + binaryen.SideEffects.Any); var module = new binaryen.Module(); assert( binaryen.getSideEffects( - module.i32.const(1), - module + module.i32.const(1) ) == binaryen.SideEffects.None ); assert( binaryen.getSideEffects( - module.br("test"), - module + module.br("test") ) == binaryen.SideEffects.Branches ); assert( binaryen.getSideEffects( - module.call("test", [], binaryen.i32), - module + module.call("test", [], binaryen.i32) ) == binaryen.SideEffects.Calls ); assert( binaryen.getSideEffects( - module.local.get("test", binaryen.i32), - module + module.local.get("test", binaryen.i32) ) == binaryen.SideEffects.ReadsLocal @@ -53,28 +46,21 @@ binaryen.getSideEffects( module.local.set("test", module.i32.const(1) - ), - module + ) ) == binaryen.SideEffects.WritesLocal ); - -// Add a global for the test, as computing side effects will look for it. -module.addGlobal('test', binaryen.i32, true, module.i32.const(42)); - assert( binaryen.getSideEffects( - module.global.get("test", binaryen.i32), - module + module.global.get("test", binaryen.i32) ) == binaryen.SideEffects.ReadsGlobal ); assert( binaryen.getSideEffects( - module.global.set("test", module.i32.const(1)), - module + module.global.set("test", module.i32.const(1)) ) == binaryen.SideEffects.WritesGlobal @@ -83,8 +69,7 @@ binaryen.getSideEffects( module.i32.load(0, 0, module.i32.const(0) - ), - module + ) ) == binaryen.SideEffects.ReadsMemory | binaryen.SideEffects.ImplicitTrap @@ -94,8 +79,7 @@ module.i32.store(0, 0, module.i32.const(0), module.i32.const(1) - ), - module + ) ) == binaryen.SideEffects.WritesMemory | binaryen.SideEffects.ImplicitTrap @@ -105,8 +89,7 @@ module.i32.div_s( module.i32.const(1), module.i32.const(0) - ), - module + ) ) == binaryen.SideEffects.ImplicitTrap @@ -117,7 +100,7 @@ assert( binaryen.getSideEffects( module.call("test", [], binaryen.i32), - module + module.getFeatures() ) == binaryen.SideEffects.Calls | binaryen.SideEffects.Throws @@ -125,8 +108,8 @@ assert( binaryen.getSideEffects( - module.drop(module.i32.pop()), - module + module.drop(module.exnref.pop()), + module.getFeatures() ) == binaryen.SideEffects.DanglingPop diff -Nru binaryen-108/test/binaryen.js/sideffects.js.txt binaryen-99/test/binaryen.js/sideffects.js.txt --- binaryen-108/test/binaryen.js/sideffects.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/sideffects.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -7,11 +7,8 @@ SideEffects.WritesGlobal=32 SideEffects.ReadsMemory=64 SideEffects.WritesMemory=128 -SideEffects.ReadsTable=256 -SideEffects.WritesTable=512 -SideEffects.ImplicitTrap=1024 -SideEffects.IsAtomic=2048 -SideEffects.Throws=4096 -SideEffects.DanglingPop=8192 -SideEffects.TrapsNeverHappen=16384 -SideEffects.Any=32767 +SideEffects.ImplicitTrap=256 +SideEffects.IsAtomic=512 +SideEffects.Throws=1024 +SideEffects.DanglingPop=2048 +SideEffects.Any=4095 diff -Nru binaryen-108/test/binaryen.js/stackir.js.txt binaryen-99/test/binaryen.js/stackir.js.txt --- binaryen-108/test/binaryen.js/stackir.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/stackir.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -18,7 +18,7 @@ === default === (module - (type $i (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 0) (export "test" (func $test)) (func $test (param $0 i32) (result i32) @@ -35,7 +35,7 @@ === optimize === (module - (type $i (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 0) (export "test" (func $test)) (func $test (param $0 i32) (result i32) diff -Nru binaryen-108/test/binaryen.js/tag.js binaryen-99/test/binaryen.js/tag.js --- binaryen-108/test/binaryen.js/tag.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/tag.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -function cleanInfo(info) { - var ret = {}; - for (var x in info) { - ret[x] = info[x]; - } - return ret; -} - -var module = new binaryen.Module(); -module.setFeatures(binaryen.Features.ReferenceTypes | - binaryen.Features.ExceptionHandling | - binaryen.Features.Multivalue); - -var pairType = binaryen.createType([binaryen.i32, binaryen.f32]); - -var tag = module.addTag("a-tag", binaryen.i32, binaryen.none); - -console.log("GetTag is equal: " + (tag === module.getTag("a-tag"))); - -var tagInfo = binaryen.getTagInfo(tag); -console.log("getTagInfo=" + JSON.stringify(cleanInfo(tagInfo))); - -module.addTagExport("a-tag", "a-tag-exp"); -module.addTagImport("a-tag-imp", "module", "base", pairType, binaryen.none); - -assert(module.validate()); -console.log(module.emitText()); - -module.removeExport("a-tag-exp"); -module.removeTag("a-tag"); - -assert(module.validate()); -console.log(module.emitText()); diff -Nru binaryen-108/test/binaryen.js/tag.js.txt binaryen-99/test/binaryen.js/tag.js.txt --- binaryen-108/test/binaryen.js/tag.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/tag.js.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -GetTag is equal: true -getTagInfo={"name":"a-tag","module":"","base":"","params":2,"results":0} -(module - (type $i32_=>_none (func (param i32))) - (type $i32_f32_=>_none (func (param i32 f32))) - (import "module" "base" (tag $a-tag-imp (param i32 f32))) - (tag $a-tag (param i32)) - (export "a-tag-exp" (tag $a-tag)) -) - -(module - (type $i32_f32_=>_none (func (param i32 f32))) - (import "module" "base" (tag $a-tag-imp (param i32 f32))) -) - diff -Nru binaryen-108/test/binaryen.js/tail_calls.js binaryen-99/test/binaryen.js/tail_calls.js --- binaryen-108/test/binaryen.js/tail_calls.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/tail_calls.js 2021-01-07 20:01:06.000000000 +0000 @@ -18,7 +18,6 @@ binaryen.none, [], module.return_call_indirect( - "0", module.i32.const(0), [], binaryen.none, diff -Nru binaryen-108/test/binaryen.js/zero-filled-memory.js binaryen-99/test/binaryen.js/zero-filled-memory.js --- binaryen-108/test/binaryen.js/zero-filled-memory.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/zero-filled-memory.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -var wast = String.raw` -(module - (import "env" "memory" (memory $0 1)) - (data (i32.const 1024) "\00\00\00\00") - (export "memory" (memory $0)) -) -`; - -console.log("=== input wast ===" + wast); - -var module = binaryen.parseText(wast); - -console.log("=== unoptimized ==="); -assert(module.validate()); -console.log(module.emitText()); - -console.log("=== optimized, zeroFilledMemory=" + binaryen.getZeroFilledMemory() + " ==="); -module.optimize(); -assert(module.validate()); -console.log(module.emitText()); - -binaryen.setZeroFilledMemory(true); -assert(binaryen.getZeroFilledMemory()); -console.log(); - -console.log("=== optimized, zeroFilledMemory=" + binaryen.getZeroFilledMemory() + " ==="); -module.optimize(); -assert(module.validate()); -console.log(module.emitText()); - -module.dispose(); diff -Nru binaryen-108/test/binaryen.js/zero-filled-memory.js.txt binaryen-99/test/binaryen.js/zero-filled-memory.js.txt --- binaryen-108/test/binaryen.js/zero-filled-memory.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/binaryen.js/zero-filled-memory.js.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -=== input wast === -(module - (import "env" "memory" (memory $0 1)) - (data (i32.const 1024) "\00\00\00\00") - (export "memory" (memory $0)) -) - -=== unoptimized === -(module - (import "env" "memory" (memory $0 1)) - (data (i32.const 1024) "\00\00\00\00") - (export "memory" (memory $0)) -) - -=== optimized, zeroFilledMemory=false === -(module - (import "env" "memory" (memory $0 1)) - (data (i32.const 1024) "\00\00\00\00") - (export "memory" (memory $0)) -) - - -=== optimized, zeroFilledMemory=true === -(module - (import "env" "memory" (memory $0 1)) - (export "memory" (memory $0)) -) - Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/break-within-catch.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/break-within-catch.wasm differ diff -Nru binaryen-108/test/break-within-catch.wasm.fromBinary binaryen-99/test/break-within-catch.wasm.fromBinary --- binaryen-108/test/break-within-catch.wasm.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/break-within-catch.wasm.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,16 +1,14 @@ (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) - (tag $tag$0 (param i32)) (func $0 (block $label$2 - (try $label$3 + (try (do (nop) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) (br $label$2) ) Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/br_to_try.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/br_to_try.wasm differ diff -Nru binaryen-108/test/br_to_try.wasm.fromBinary binaryen-99/test/br_to_try.wasm.fromBinary --- binaryen-108/test/br_to_try.wasm.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/br_to_try.wasm.fromBinary 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -(module - (type $i32_=>_none (func (param i32))) - (type $none_=>_none (func)) - (tag $tag$0 (param i32)) - (func $0 - (try $label$3 - (do - (block $label$1 - (br $label$1) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - ) - ) -) - diff -Nru binaryen-108/test/calls.cpp binaryen-99/test/calls.cpp --- binaryen-108/test/calls.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/calls.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -2,18 +2,23 @@ extern "C" { -int inner(int x) { return x * x + 2; } +int inner(int x) { + return x*x + 2; +} -int EMSCRIPTEN_KEEPALIVE simple(int x) { return inner(x); } +int EMSCRIPTEN_KEEPALIVE simple(int x) { + return inner(x); +} int EMSCRIPTEN_KEEPALIVE fibo(int x) { - if (x == 0 || x == 1) - return 1; - return fibo(x - 1) + fibo(x - 2); + if (x == 0 || x == 1) return 1; + return fibo(x-1) + fibo(x-2); } int EMSCRIPTEN_KEEPALIVE run_script() { emscripten_run_script("Module.print('hello from called script')"); return emscripten_run_script_int("1+2+3+4-1"); } + } + diff -Nru binaryen-108/test/control_flow.cpp binaryen-99/test/control_flow.cpp --- binaryen-108/test/control_flow.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/control_flow.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,26 +1,23 @@ -#include #include +#include #include extern "C" { int EMSCRIPTEN_KEEPALIVE check_if(int x) { - if (x < 10) - x++; + if (x < 10) x++; return x; } int EMSCRIPTEN_KEEPALIVE check_loop(int x) { - while (x < 100) - x *= 2; + while (x < 100) x *= 2; return x; } int EMSCRIPTEN_KEEPALIVE check_loop_break(int x) { while (x < 100) { x *= 2; - if (x > 30) - break; + if (x > 30) break; x++; } return x; @@ -29,8 +26,7 @@ int EMSCRIPTEN_KEEPALIVE check_loop_continue(int x) { while (x < 100) { x *= 2; - if (x > 30) - continue; + if (x > 30) continue; x++; } return x; @@ -39,11 +35,9 @@ int EMSCRIPTEN_KEEPALIVE check_do_loop(int x) { do { x *= 2; - if (x > 1000) - break; + if (x > 1000) break; x--; - if (x > 30) - continue; + if (x > 30) continue; x++; } while (x < 100); return x; @@ -52,11 +46,9 @@ int EMSCRIPTEN_KEEPALIVE check_do_once(int x) { do { x *= 2; - if (x > 1000) - break; + if (x > 1000) break; x--; - if (x > 30) - continue; + if (x > 30) continue; x++; } while (0); return x; @@ -65,11 +57,9 @@ int EMSCRIPTEN_KEEPALIVE check_while_forever(int x) { while (1) { x *= 2; - if (x > 1000) - break; + if (x > 1000) break; x--; - if (x > 30) - continue; + if (x > 30) continue; x++; } return x; @@ -77,72 +67,51 @@ int EMSCRIPTEN_KEEPALIVE check_switch(int x) { switch (x) { - case 1: - return 10; - case 3: - return 20; - case 5: - return 30; - case 10: - return 40; - case 11: - return 50; - default: - return 60; + case 1: return 10; + case 3: return 20; + case 5: return 30; + case 10: return 40; + case 11: return 50; + default: return 60; } return 70; } int EMSCRIPTEN_KEEPALIVE check_switch_nodefault(int x) { switch (x) { - case 1: - return 10; - case 3: - return 20; - case 5: - return 30; - case 10: - return 40; - case 11: - return 50; + case 1: return 10; + case 3: return 20; + case 5: return 30; + case 10: return 40; + case 11: return 50; } return 70; } int EMSCRIPTEN_KEEPALIVE check_switch_rdefault(int x) { switch (x) { - default: - return -60; - case 1: - return 10; - case 3: - return 20; - case 5: - return 30; - case 10: - return 40; - case 11: - return 50; + default: return -60; + case 1: return 10; + case 3: return 20; + case 5: return 30; + case 10: return 40; + case 11: return 50; } return 70; } int EMSCRIPTEN_KEEPALIVE check_switch_fallthrough(int x) { switch (x) { - case 1: - return 10; + case 1: return 10; case 2: - case 3: - x++; - case 5: - return x; - case 10: - return 40; - case 11: - return 50; - default: - return 60; + case 3: x++; + case 5: return x; + case 10: return 40; + case 11: return 50; + default: return 60; } return 70; } + } + diff -Nru binaryen-108/test/ctor-eval/bad-indirect-call2.wast.out binaryen-99/test/ctor-eval/bad-indirect-call2.wast.out --- binaryen-108/test/ctor-eval/bad-indirect-call2.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/bad-indirect-call2.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $v (func)) + (type $none_=>_none (func)) (import "env" "_abort" (func $_abort)) (memory $0 256 256) (data (i32.const 10) "waka waka waka waka waka") @@ -7,7 +7,7 @@ (elem (i32.const 0) $_abort $call-indirect) (export "test1" (func $test1)) (func $test1 - (call_indirect $0 (type $v) + (call_indirect (type $none_=>_none) (i32.const 0) ) (i32.store8 diff -Nru binaryen-108/test/ctor-eval/bad-indirect-call3.wast binaryen-99/test/ctor-eval/bad-indirect-call3.wast --- binaryen-108/test/ctor-eval/bad-indirect-call3.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/bad-indirect-call3.wast 2021-01-07 20:01:06.000000000 +0000 @@ -4,7 +4,7 @@ (data (i32.const 10) "waka waka waka waka waka") (table funcref (elem $callee)) (export "sig_mismatch" (func $sig_mismatch)) - (func $callee (param $0 externref) + (func $callee (param $0 exnref) (i32.store8 (i32.const 40) (i32.const 67)) ) (func $sig_mismatch diff -Nru binaryen-108/test/ctor-eval/bad-indirect-call3.wast.out binaryen-99/test/ctor-eval/bad-indirect-call3.wast.out --- binaryen-108/test/ctor-eval/bad-indirect-call3.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/bad-indirect-call3.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,20 +1,20 @@ (module - (type $anyref_=>_none (func (param anyref))) (type $none_=>_none (func)) (type $funcref_=>_none (func (param funcref))) + (type $exnref_=>_none (func (param exnref))) (memory $0 256 256) (data (i32.const 10) "waka waka waka waka waka") (table $0 1 1 funcref) (elem (i32.const 0) $callee) (export "sig_mismatch" (func $sig_mismatch)) - (func $callee (param $0 anyref) + (func $callee (param $0 exnref) (i32.store8 (i32.const 40) (i32.const 67) ) ) (func $sig_mismatch - (call_indirect $0 (type $funcref_=>_none) + (call_indirect (type $funcref_=>_none) (ref.null func) (i32.const 0) ) diff -Nru binaryen-108/test/ctor-eval/bad-indirect-call.wast.out binaryen-99/test/ctor-eval/bad-indirect-call.wast.out --- binaryen-108/test/ctor-eval/bad-indirect-call.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/bad-indirect-call.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $v (func)) + (type $none_=>_none (func)) (memory $0 256 256) (data (i32.const 10) "waka waka waka waka waka") (table $0 1 1 funcref) (elem (i32.const 0) $call-indirect) (export "test1" (func $test1)) (func $test1 - (call_indirect $0 (type $v) + (call_indirect (type $none_=>_none) (i32.const 1) ) (i32.store8 diff -Nru binaryen-108/test/ctor-eval/basics-flatten.wast.out binaryen-99/test/ctor-eval/basics-flatten.wast.out --- binaryen-108/test/ctor-eval/basics-flatten.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/basics-flatten.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $v (func)) + (type $none_=>_none (func)) (memory $0 256 256) (data (i32.const 10) "nas\00\00\00aka\00yzkx waka wakm\00\00\00\00\00\00C") (func $call-indirect diff -Nru binaryen-108/test/ctor-eval/basics.wast.out binaryen-99/test/ctor-eval/basics.wast.out --- binaryen-108/test/ctor-eval/basics.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/basics.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $v (func)) + (type $none_=>_none (func)) (memory $0 256 256) (data (i32.const 10) "nas\00\00\00aka yzkx waka wakm\00\00\00\00\00\00C") (func $call-indirect diff -Nru binaryen-108/test/ctor-eval/gc-2.wast binaryen-99/test/ctor-eval/gc-2.wast --- binaryen-108/test/ctor-eval/gc-2.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc-2.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -(module - (type $struct (struct_subtype (field i32) data)) - - (import "import" "import" (func $import (param anyref))) - - ;; This struct is created in an immutable global, but it has the wrong type. - ;; We will create a new defining global for it that has the proper type, and - ;; read from it here. (This is necessary as when the global is used elsewhere - ;; we want to get the right type from the global.get.) - (global $global1 (ref any) - (struct.new $struct - (i32.const 1337) - ) - ) - - ;; Test reordering of globals. This global will be written a value that is - ;; actually defined after it. To handle that, we must create it earlier than - ;; this global. - (global $global2 (mut (ref null $struct)) - (ref.null $struct) - ) - - ;; This global is perfect to be a defining global (immutable, right type), but - ;; because of an earlier use, we will end up defining it earlier on, and - ;; reading it here. - (global $global3 (ref $struct) - (struct.new $struct - (i32.const 9999) - ) - ) - - (func "test1" - (global.set $global2 - (global.get $global3) - ) - ) - - (func "keepalive" (result i32) - (select - (struct.get $struct 0 - (ref.cast_static $struct - (global.get $global1) - ) - ) - (struct.get $struct 0 - (global.get $global2) - ) - (struct.get $struct 0 - (global.get $global3) - ) - ) - ) -) - diff -Nru binaryen-108/test/ctor-eval/gc-2.wast.ctors binaryen-99/test/ctor-eval/gc-2.wast.ctors --- binaryen-108/test/ctor-eval/gc-2.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc-2.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/gc-2.wast.out binaryen-99/test/ctor-eval/gc-2.wast.out --- binaryen-108/test/ctor-eval/gc-2.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc-2.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -(module - (type $struct (struct (field i32))) - (type $none_=>_i32 (func (result i32))) - (global $ctor-eval$global (ref $struct) (struct.new $struct - (i32.const 1337) - )) - (global $global1 (ref any) (global.get $ctor-eval$global)) - (global $ctor-eval$global_0 (ref $struct) (struct.new $struct - (i32.const 9999) - )) - (global $global2 (mut (ref null $struct)) (global.get $ctor-eval$global_0)) - (global $global3 (ref $struct) (global.get $ctor-eval$global_0)) - (export "keepalive" (func $1)) - (func $1 (result i32) - (select - (struct.get $struct 0 - (ref.cast_static $struct - (global.get $global1) - ) - ) - (struct.get $struct 0 - (global.get $global2) - ) - (struct.get $struct 0 - (global.get $global3) - ) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/gc-array.wast binaryen-99/test/ctor-eval/gc-array.wast --- binaryen-108/test/ctor-eval/gc-array.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc-array.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -(module - (type $array (array (mut i32))) - - (import "import" "import" (func $import (param anyref))) - - ;; This global will remain as it is. - (global $global1 (ref $array) - (array.init_static $array - (i32.const 10) - (i32.const 20) - (i32.const 30) - (i32.const 40) - ) - ) - - (global $global2 (ref $array) - (array.init_static $array - (i32.const 42) - ;; This location will be written with a new value, 1337 - (i32.const 0) - ) - ) - - (func "test1" - (array.set $array - (global.get $global2) - (i32.const 1) - (i32.const 1337) - ) - ) - - (func "keepalive" (result i32) - (i32.add - (array.get $array - (global.get $global1) - (i32.const 0) - ) - (array.get $array - (global.get $global2) - (i32.const 0) - ) - ) - ) -) - diff -Nru binaryen-108/test/ctor-eval/gc-array.wast.ctors binaryen-99/test/ctor-eval/gc-array.wast.ctors --- binaryen-108/test/ctor-eval/gc-array.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc-array.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/gc-array.wast.out binaryen-99/test/ctor-eval/gc-array.wast.out --- binaryen-108/test/ctor-eval/gc-array.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc-array.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -(module - (type $array (array (mut i32))) - (type $none_=>_i32 (func (result i32))) - (global $global1 (ref $array) (array.init_static $array - (i32.const 10) - (i32.const 20) - (i32.const 30) - (i32.const 40) - )) - (global $global2 (ref $array) (array.init_static $array - (i32.const 42) - (i32.const 1337) - )) - (export "keepalive" (func $1)) - (func $1 (result i32) - (i32.add - (array.get $array - (global.get $global1) - (i32.const 0) - ) - (array.get $array - (global.get $global2) - (i32.const 0) - ) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/gc.wast binaryen-99/test/ctor-eval/gc.wast --- binaryen-108/test/ctor-eval/gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -(module - (type $struct (struct_subtype (field i32) data)) - - (import "import" "import" (func $import (param anyref))) - - ;; Create a GC object in a global. We can keep the struct.new here even after - ;; evalling (we should not create an extra, unneeded global, and read from - ;; that). - (global $global1 (ref $struct) - (struct.new $struct - (i32.const 1337) - ) - ) - - ;; After evalling we should see this refer to a struct with contents 42, and - ;; not 41, which is overridden, see "test1". We also should not see any code - ;; that creates an object with 41, as that is no longer live. - ;; - ;; Note that we will not simply do a struct.new in this global, as it is - ;; mutable, and we only use immutable globals as defining globals for values, - ;; so a new (immutable) global will appear, and we will read from it. - (global $global2 (mut (ref null $struct)) (ref.null $struct)) - - (func "test1" - ;; Leave the first local as null, which we should handle properly (we will - ;; end up emitting nothing and still using the default null value). - (local $temp1 (ref null $struct)) - (local $temp2 (ref null $struct)) - - (global.set $global2 - (struct.new $struct - (i32.const 41) - ) - ) - (global.set $global2 - (struct.new $struct - (i32.const 42) - ) - ) - - ;; Write a value to this local. A struct with value 99 will be created in a - ;; global, and referred to here. - (local.set $temp2 - (struct.new $struct - (i32.const 99) - ) - ) - - ;; Stop evalling here at the import. - (call $import (local.get $temp1)) - (call $import (local.get $temp2)) - ) - - (func "keepalive" (result i32) - (i32.add - (struct.get $struct 0 - (global.get $global1) - ) - (struct.get $struct 0 - (global.get $global2) - ) - ) - ) -) - diff -Nru binaryen-108/test/ctor-eval/gc.wast.ctors binaryen-99/test/ctor-eval/gc.wast.ctors --- binaryen-108/test/ctor-eval/gc.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/gc.wast.out binaryen-99/test/ctor-eval/gc.wast.out --- binaryen-108/test/ctor-eval/gc.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/gc.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -(module - (type $struct (struct (field i32))) - (type $anyref_=>_none (func (param anyref))) - (type $none_=>_i32 (func (result i32))) - (type $none_=>_none (func)) - (import "import" "import" (func $import (param anyref))) - (global $global1 (ref $struct) (struct.new $struct - (i32.const 1337) - )) - (global $ctor-eval$global (ref $struct) (struct.new $struct - (i32.const 42) - )) - (global $global2 (mut (ref null $struct)) (global.get $ctor-eval$global)) - (global $ctor-eval$global_0 (ref $struct) (struct.new $struct - (i32.const 99) - )) - (export "test1" (func $0_0)) - (export "keepalive" (func $1)) - (func $1 (result i32) - (i32.add - (struct.get $struct 0 - (global.get $global1) - ) - (struct.get $struct 0 - (global.get $global2) - ) - ) - ) - (func $0_0 - (local $0 (ref null $struct)) - (local.set $0 - (global.get $ctor-eval$global_0) - ) - (call $import - (ref.null $struct) - ) - (call $import - (local.get $0) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/global-get-init.wast binaryen-99/test/ctor-eval/global-get-init.wast --- binaryen-108/test/ctor-eval/global-get-init.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/global-get-init.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -(module - (import "import" "global" (global $imported i32)) - (func $test1 (export "test1") - ;; This should be safe to eval in theory, but the imported global stops us, - ;; so this function will not be optimized out. - ;; TODO: perhaps if we never use that global that is ok? - ) -) diff -Nru binaryen-108/test/ctor-eval/global-get-init.wast.ctors binaryen-99/test/ctor-eval/global-get-init.wast.ctors --- binaryen-108/test/ctor-eval/global-get-init.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/global-get-init.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/global-get-init.wast.out binaryen-99/test/ctor-eval/global-get-init.wast.out --- binaryen-108/test/ctor-eval/global-get-init.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/global-get-init.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -(module - (type $none_=>_none (func)) - (export "test1" (func $test1)) - (func $test1 - (nop) - ) -) diff -Nru binaryen-108/test/ctor-eval/globals.wast binaryen-99/test/ctor-eval/globals.wast --- binaryen-108/test/ctor-eval/globals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/globals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -(module - (global $g1 (mut i32) (i32.const 10)) - (global $g2 (mut i32) (i32.const 20)) - (func $test1 (export "test1") - (global.set $g1 (i32.const 30)) - (global.set $g2 (i32.const 40)) - (global.set $g1 (i32.const 50)) ;; this overrides the previous 30 - ) - (func $keepalive (export "keepalive") (result i32) - ;; Keep the globals alive so we can see their values. - (i32.add - (global.get $g1) - (global.get $g2) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/globals.wast.ctors binaryen-99/test/ctor-eval/globals.wast.ctors --- binaryen-108/test/ctor-eval/globals.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/globals.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/globals.wast.out binaryen-99/test/ctor-eval/globals.wast.out --- binaryen-108/test/ctor-eval/globals.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/globals.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (global $g1 (mut i32) (i32.const 50)) - (global $g2 (mut i32) (i32.const 40)) - (export "keepalive" (func $keepalive)) - (func $keepalive (result i32) - (i32.add - (global.get $g1) - (global.get $g2) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/ignore-external-input-gc.wast binaryen-99/test/ctor-eval/ignore-external-input-gc.wast --- binaryen-108/test/ctor-eval/ignore-external-input-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/ignore-external-input-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -(module - (global $global1 (mut i32) (i32.const 10)) - (global $global2 (mut i32) (i32.const 20)) - - (func "test1" (param $any (ref null any)) - ;; This is ok to call: when ignoring external input we assume 0 for the - ;; parameters, and this parameter is nullable. - (drop - (local.get $any) - ) - (global.set $global1 - (i32.const 11) - ) - ) - - (func "test2" (param $any (ref any)) - ;; This is *not* ok to call: when ignoring external input we assume 0 for - ;; the parameters, and this parameter is not nullable. - (drop - (local.get $any) - ) - (global.set $global2 - (i32.const 22) - ) - ) - - (func "keepalive" (result i32) - (i32.add - (global.get $global1) - (global.get $global2) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/ignore-external-input-gc.wast.ctors binaryen-99/test/ctor-eval/ignore-external-input-gc.wast.ctors --- binaryen-108/test/ctor-eval/ignore-external-input-gc.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/ignore-external-input-gc.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1,test2 diff -Nru binaryen-108/test/ctor-eval/ignore-external-input-gc.wast.out binaryen-99/test/ctor-eval/ignore-external-input-gc.wast.out --- binaryen-108/test/ctor-eval/ignore-external-input-gc.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/ignore-external-input-gc.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -(module - (type $ref|any|_=>_none (func (param (ref any)))) - (type $none_=>_i32 (func (result i32))) - (global $global1 (mut i32) (i32.const 11)) - (global $global2 (mut i32) (i32.const 20)) - (export "test2" (func $1)) - (export "keepalive" (func $2)) - (func $1 (param $any (ref any)) - (global.set $global2 - (i32.const 22) - ) - ) - (func $2 (result i32) - (i32.add - (global.get $global1) - (global.get $global2) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/ignore-external-input.wast binaryen-99/test/ctor-eval/ignore-external-input.wast --- binaryen-108/test/ctor-eval/ignore-external-input.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/ignore-external-input.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -(module - (import "wasi_snapshot_preview1" "environ_sizes_get" (func $wasi_environ_sizes_get (param i32 i32) (result i32))) - (import "wasi_snapshot_preview1" "environ_get" (func $wasi_environ_get (param i32 i32) (result i32))) - - (import "wasi_snapshot_preview1" "args_sizes_get" (func $wasi_args_sizes_get (param i32 i32) (result i32))) - (import "wasi_snapshot_preview1" "args_get" (func $wasi_args_get (param i32 i32) (result i32))) - - (import "wasi_snapshot_preview1" "something_else" (func $wasi_something_else (result i32))) - - (memory 256 256) - (data (i32.const 0) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") ;; the final 4 'a's will remain - - (func "test1" - ;; This is ok to call: when ignoring external input we assume there is no - ;; environment to read. - (i32.store - (i32.const 0) ;; the result (0) will be written to address 0 - (call $wasi_environ_sizes_get - (i32.const 4) ;; count (0) will be written to address 4 - (i32.const 0) - ) - ) - (i32.store - (i32.const 8) ;; the result (0) will be written to address 8 - (call $wasi_environ_get - (i32.const 0) - (i32.const 0) - ) - ) - ) - - (func "test2" - ;; This is also ok to call: when ignoring external input we assume there are - ;; not args passed to main. - (i32.store - (i32.const 12) ;; the result (0) will be written to address 12 - (call $wasi_args_sizes_get - (i32.const 16) ;; argc (0) will be written to address 16 - (i32.const 0) - ) - ) - (i32.store - (i32.const 20) ;; the result (0) will be written to address 20 - (call $wasi_args_get - (i32.const 0) - (i32.const 0) - ) - ) - ) - - (func "test2b" (param $x i32) - ;; This is also ok to call: when ignoring external input we assume the - ;; args are zeros. - (i32.store - (i32.const 24) ;; the result (0) will be written to address 24 - (local.get $x) - ) - ) - - (func "test3" - ;; This is *not* ok to call, and we will *not* reach the final store after - ;; this call. This function will not be evalled and will remain in the - ;; output. - (drop - (call $wasi_something_else) - ) - (i32.store - (i32.const 28) - (i32.const 100) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/ignore-external-input.wast.ctors binaryen-99/test/ctor-eval/ignore-external-input.wast.ctors --- binaryen-108/test/ctor-eval/ignore-external-input.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/ignore-external-input.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1,test2,test2b,test3 diff -Nru binaryen-108/test/ctor-eval/ignore-external-input.wast.out binaryen-99/test/ctor-eval/ignore-external-input.wast.out --- binaryen-108/test/ctor-eval/ignore-external-input.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/ignore-external-input.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (type $none_=>_none (func)) - (import "wasi_snapshot_preview1" "something_else" (func $wasi_something_else (result i32))) - (memory $0 256 256) - (data (i32.const 28) "aaaa") - (export "test3" (func $3)) - (func $3 - (drop - (call $wasi_something_else) - ) - (i32.store - (i32.const 28) - (i32.const 100) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/imported2.wast binaryen-99/test/ctor-eval/imported2.wast --- binaryen-108/test/ctor-eval/imported2.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported2.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,26 @@ +(module + (memory 256 256) + (data (i32.const 10) "waka waka waka waka waka") + ;; stack imports are special-cased + (import "env" "STACKTOP" (global $STACKTOP i32)) + (import "env" "STACK_MAX" (global $STACK_MAX i32)) + ;; other imports must not be touched! + (import "env" "tempDoublePtr" (global $tempDoublePtr i32)) + (export "test1" $test1) + (export "test2" $test2) + (export "test3" $test3) + ;; ok to modify a global, if we keep it the same value + (global $mine (mut i32) (i32.const 1)) + (func $test1 + (global.set $mine (i32.const 2)) + (global.set $mine (i32.const 1)) ;; restore! + (i32.store8 (i32.const 12) (i32.const 115)) + ) + (func $test2 + (global.set $mine (i32.const 2)) ;; embadden + (i32.store8 (i32.const 13) (i32.const 115)) + ) + (func $test3 + (i32.store8 (i32.const 14) (i32.const 115)) + ) +) diff -Nru binaryen-108/test/ctor-eval/imported2.wast.ctors binaryen-99/test/ctor-eval/imported2.wast.ctors --- binaryen-108/test/ctor-eval/imported2.wast.ctors 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported2.wast.ctors 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +test1,test2,test3 diff -Nru binaryen-108/test/ctor-eval/imported2.wast.out binaryen-99/test/ctor-eval/imported2.wast.out --- binaryen-108/test/ctor-eval/imported2.wast.out 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported2.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,23 @@ +(module + (type $none_=>_none (func)) + (memory $0 256 256) + (data (i32.const 10) "wasa waka waka waka waka") + (global $mine (mut i32) (i32.const 1)) + (export "test2" (func $test2)) + (export "test3" (func $test3)) + (func $test2 + (global.set $mine + (i32.const 2) + ) + (i32.store8 + (i32.const 13) + (i32.const 115) + ) + ) + (func $test3 + (i32.store8 + (i32.const 14) + (i32.const 115) + ) + ) +) diff -Nru binaryen-108/test/ctor-eval/imported3.wast binaryen-99/test/ctor-eval/imported3.wast --- binaryen-108/test/ctor-eval/imported3.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported3.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,12 @@ +(module + (memory 256 256) + (data (i32.const 10) "waka waka waka waka waka") + ;; imports must not be used + (import "env" "tempDoublePtr" (global $tempDoublePtr i32)) + (export "test1" $test1) + (global $mine (mut i32) (global.get $tempDoublePtr)) ;; BAD, if used + (func $test1 + (drop (global.get $mine)) + (i32.store8 (i32.const 13) (i32.const 115)) ;; we never get here. + ) +) diff -Nru binaryen-108/test/ctor-eval/imported3.wast.ctors binaryen-99/test/ctor-eval/imported3.wast.ctors --- binaryen-108/test/ctor-eval/imported3.wast.ctors 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported3.wast.ctors 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +test1 diff -Nru binaryen-108/test/ctor-eval/imported3.wast.out binaryen-99/test/ctor-eval/imported3.wast.out --- binaryen-108/test/ctor-eval/imported3.wast.out 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported3.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,12 @@ +(module + (type $none_=>_none (func)) + (memory $0 256 256) + (data (i32.const 10) "waka waka waka waka waka") + (export "test1" (func $test1)) + (func $test1 + (i32.store8 + (i32.const 13) + (i32.const 115) + ) + ) +) diff -Nru binaryen-108/test/ctor-eval/imported-global-2.wast binaryen-99/test/ctor-eval/imported-global-2.wast --- binaryen-108/test/ctor-eval/imported-global-2.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-global-2.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -(module - (memory 256 256) - - ;; imports must not be used - (import "env" "imported" (global $imported i32)) - - (func "test1" (result i32) - (local $temp i32) - - ;; this errors, and we never get to evalling the store after it - (local.set $temp - (global.get $imported) - ) - - (i32.store8 - (i32.const 13) - (i32.const 115) - ) - - (local.get $temp) - ) - - (func "keepalive" (result i32) - (drop - (i32.load - (i32.const 13) - ) - ) - (global.get $imported) - ) -) diff -Nru binaryen-108/test/ctor-eval/imported-global-2.wast.ctors binaryen-99/test/ctor-eval/imported-global-2.wast.ctors --- binaryen-108/test/ctor-eval/imported-global-2.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-global-2.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/imported-global-2.wast.out binaryen-99/test/ctor-eval/imported-global-2.wast.out --- binaryen-108/test/ctor-eval/imported-global-2.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-global-2.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (import "env" "imported" (global $imported i32)) - (memory $0 256 256) - (export "test1" (func $0)) - (export "keepalive" (func $1)) - (func $0 (result i32) - (local $temp i32) - (local.set $temp - (global.get $imported) - ) - (i32.store8 - (i32.const 13) - (i32.const 115) - ) - (local.get $temp) - ) - (func $1 (result i32) - (drop - (i32.load - (i32.const 13) - ) - ) - (global.get $imported) - ) -) diff -Nru binaryen-108/test/ctor-eval/imported-global.wast binaryen-99/test/ctor-eval/imported-global.wast --- binaryen-108/test/ctor-eval/imported-global.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-global.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -(module - (memory 256 256) - (data (i32.const 10) "waka waka waka waka waka") - ;; imports must not be used - (import "env" "tempDoublePtr" (global $tempDoublePtr i32)) - (export "test1" $test1) - (global $mine (mut i32) (global.get $tempDoublePtr)) ;; BAD, if used - (func $test1 - (i32.store8 (i32.const 13) (i32.const 115)) ;; we never get here. - ) -) diff -Nru binaryen-108/test/ctor-eval/imported-global.wast.ctors binaryen-99/test/ctor-eval/imported-global.wast.ctors --- binaryen-108/test/ctor-eval/imported-global.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-global.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/imported-global.wast.out binaryen-99/test/ctor-eval/imported-global.wast.out --- binaryen-108/test/ctor-eval/imported-global.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-global.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -(module - (type $none_=>_none (func)) - (memory $0 256 256) - (data (i32.const 10) "waka waka waka waka waka") - (export "test1" (func $test1)) - (func $test1 - (i32.store8 - (i32.const 13) - (i32.const 115) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/imported-min.wast binaryen-99/test/ctor-eval/imported-min.wast --- binaryen-108/test/ctor-eval/imported-min.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-min.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,47 @@ +(module + (memory 256 256) + (data (i32.const 10) "waka waka waka waka waka") + ;; stack imports are special + (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) + (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) + (import "env" "tempDoublePtr" (global $tempDoublePtr i32)) + (global $tempDoublePtrMut (mut i32) (global.get $tempDoublePtr)) + (export "test1" $test1) + (export "test2" $test2) + (export "test3" $test3) + ;; ok to modify a global, if we keep it the same value + (global $mine (mut i32) (i32.const 1)) + ;; stack imports are ok to use. their uses are the same as other + ;; globals - must keep the same value (which means, unwind the stack) + ;; here the global names are "minified" + (global $global0 (mut i32) (global.get $STACKTOP$asm2wasm$import)) + (global $global1 (mut i32) (global.get $STACK_MAX$asm2wasm$import)) + ;; a global initialized by an import, so bad, but ok if not used + (global $do-not-use (mut i32) (global.get $tempDoublePtr)) + (func $test1 + (local $temp i32) + (global.set $mine (i32.const 1)) + (local.set $temp (global.get $global0)) + (global.set $global0 (i32.const 1337)) ;; bad + (global.set $global0 (local.get $temp)) ;; save us + (global.set $global1 (i32.const 913370)) ;; bad + (global.set $global1 (local.get $temp)) ;; save us + ;; use the stack memory + (i32.store (local.get $temp) (i32.const 1337)) + (if + (i32.ne + (i32.load (local.get $temp)) + (i32.const 1337) + ) + (unreachable) ;; they should be equal, never get here + ) + ;; finally, do a valid store + (i32.store8 (i32.const 12) (i32.const 115)) + ) + (func $test2 + (i32.store8 (i32.const 13) (i32.const 115)) + ) + (func $test3 + (i32.store8 (i32.const 14) (i32.const 115)) + ) +) diff -Nru binaryen-108/test/ctor-eval/imported-min.wast.ctors binaryen-99/test/ctor-eval/imported-min.wast.ctors --- binaryen-108/test/ctor-eval/imported-min.wast.ctors 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-min.wast.ctors 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +test1,test2,test3 diff -Nru binaryen-108/test/ctor-eval/imported-min.wast.out binaryen-99/test/ctor-eval/imported-min.wast.out --- binaryen-108/test/ctor-eval/imported-min.wast.out 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported-min.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,2 @@ +(module +) diff -Nru binaryen-108/test/ctor-eval/imported.wast binaryen-99/test/ctor-eval/imported.wast --- binaryen-108/test/ctor-eval/imported.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,45 @@ +(module + (memory 256 256) + (data (i32.const 10) "waka waka waka waka waka") + ;; stack imports are special + (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) + (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) + ;; other imports must not be touched! + (import "env" "tempDoublePtr" (global $tempDoublePtr i32)) + (global $tempDoublePtrMut (mut i32) (global.get $tempDoublePtr)) + (export "test1" $test1) + (export "test2" $test2) + (export "test3" $test3) + ;; ok to modify a global, if we keep it the same value + (global $mine (mut i32) (i32.const 1)) + ;; stack imports are ok to use. their uses are the same as other + ;; globals - must keep the same value (which means, unwind the stack) + (global $STACKTOP (mut i32) (global.get $STACKTOP$asm2wasm$import)) + (global $STACK_MAX (mut i32) (global.get $STACK_MAX$asm2wasm$import)) + ;; a global initialized by an import, so bad, but ok if not used + (global $do-not-use (mut i32) (global.get $tempDoublePtr)) + (func $test1 + (local $temp i32) + (global.set $mine (i32.const 1)) + (local.set $temp (global.get $STACKTOP)) + (global.set $STACKTOP (i32.const 1337)) ;; bad + (global.set $STACKTOP (local.get $temp)) ;; save us + ;; use the stack memory + (i32.store (local.get $temp) (i32.const 1337)) + (if + (i32.ne + (i32.load (local.get $temp)) + (i32.const 1337) + ) + (unreachable) ;; they should be equal, never get here + ) + ;; finally, do a valid store + (i32.store8 (i32.const 12) (i32.const 115)) + ) + (func $test2 + (i32.store8 (i32.const 13) (i32.const 115)) + ) + (func $test3 + (i32.store8 (i32.const 14) (i32.const 115)) + ) +) diff -Nru binaryen-108/test/ctor-eval/imported.wast.ctors binaryen-99/test/ctor-eval/imported.wast.ctors --- binaryen-108/test/ctor-eval/imported.wast.ctors 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported.wast.ctors 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +test1,test2,test3 diff -Nru binaryen-108/test/ctor-eval/imported.wast.out binaryen-99/test/ctor-eval/imported.wast.out --- binaryen-108/test/ctor-eval/imported.wast.out 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/imported.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,2 @@ +(module +) diff -Nru binaryen-108/test/ctor-eval/indirect-call3.wast binaryen-99/test/ctor-eval/indirect-call3.wast --- binaryen-108/test/ctor-eval/indirect-call3.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/indirect-call3.wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,9 +2,10 @@ (type $v (func)) (memory 256 256) (data (i32.const 10) "waka waka waka waka waka") + (import "env" "tableBase" (global $tableBase i32)) (import "env" "_abort" (func $_abort)) (table 2 2 funcref) - (elem (i32.const 0) $_abort $call-indirect) + (elem (global.get $tableBase) $_abort $call-indirect) (export "test1" $test1) (func $test1 (call_indirect (type $v) (i32.const 1)) ;; safe to call diff -Nru binaryen-108/test/ctor-eval/indirect-call3.wast.out binaryen-99/test/ctor-eval/indirect-call3.wast.out --- binaryen-108/test/ctor-eval/indirect-call3.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/indirect-call3.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,6 @@ (module - (type $v (func)) + (type $none_=>_none (func)) + (import "env" "tableBase" (global $tableBase i32)) (import "env" "_abort" (func $_abort)) (memory $0 256 256) (data (i32.const 10) "waka waka xaka waka waka\00\00\00\00\00\00C") diff -Nru binaryen-108/test/ctor-eval/memory-init.wast binaryen-99/test/ctor-eval/memory-init.wast --- binaryen-108/test/ctor-eval/memory-init.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/memory-init.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -(module - (memory $0 1) - (data (i32.const 0) "__________") - (data (i32.const 20) "__________") - (func "test1" - ;; A store that can be evalled. - (i32.store8 - (i32.const 4) - (i32.const 100) - ) - - ;; A memory init cannot be evalled since ctor-eval flattens memory segments - ;; atm. We lose the identity of them as a result as they are all merged - ;; into a single big segment. We could fix that eventually. - (memory.init 1 - (i32.const 0) - (i32.const 0) - (i32.const 1) - ) - ) -) - diff -Nru binaryen-108/test/ctor-eval/memory-init.wast.ctors binaryen-99/test/ctor-eval/memory-init.wast.ctors --- binaryen-108/test/ctor-eval/memory-init.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/memory-init.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/memory-init.wast.out binaryen-99/test/ctor-eval/memory-init.wast.out --- binaryen-108/test/ctor-eval/memory-init.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/memory-init.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -(module - (type $none_=>_none (func)) - (memory $0 1) - (data (i32.const 0) "__________") - (data (i32.const 20) "__________") - (export "test1" (func $0)) - (func $0 - (i32.store8 - (i32.const 4) - (i32.const 100) - ) - (memory.init 1 - (i32.const 0) - (i32.const 0) - (i32.const 1) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/no_partial.wast binaryen-99/test/ctor-eval/no_partial.wast --- binaryen-108/test/ctor-eval/no_partial.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/no_partial.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,10 @@ +(module + (memory 256 256) + (data (i32.const 10) "waka waka waka waka waka") + (export "test1" $test1) + (func $test1 + (i32.store8 (i32.const 12) (i32.const 115)) ;; a safe store, should alter memory + (unreachable) + (i32.store8 (i32.const 13) (i32.const 114)) ;; a safe store, should alter memory, but we trapped already, and so must roll back the first one too + ) +) diff -Nru binaryen-108/test/ctor-eval/no_partial.wast.ctors binaryen-99/test/ctor-eval/no_partial.wast.ctors --- binaryen-108/test/ctor-eval/no_partial.wast.ctors 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/no_partial.wast.ctors 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +test1 diff -Nru binaryen-108/test/ctor-eval/no_partial.wast.out binaryen-99/test/ctor-eval/no_partial.wast.out --- binaryen-108/test/ctor-eval/no_partial.wast.out 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/no_partial.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,13 @@ +(module + (type $none_=>_none (func)) + (memory $0 256 256) + (data (i32.const 10) "waka waka waka waka waka") + (export "test1" (func $test1)) + (func $test1 + (i32.store8 + (i32.const 12) + (i32.const 115) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/ctor-eval/overlapping-segments.wast binaryen-99/test/ctor-eval/overlapping-segments.wast --- binaryen-108/test/ctor-eval/overlapping-segments.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/overlapping-segments.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - - (table $0 46 funcref) - (elem $0 (i32.const 9) $1) - (elem $1 (i32.const 9) $0) - - (export "test1" (func $2)) - - (func $0 (result i32) - (unreachable) - ) - (func $1 (result i32) - (i32.const 65) - ) - (func $2 - (drop - (call_indirect (type $none_=>_i32) - ;; Calling the item at index $9 should call $0, which appears in the - ;; last of the overlapping segments. That function traps, which stops - ;; us from evalling anything here. - (i32.const 9) - ) - ) - ) -) - diff -Nru binaryen-108/test/ctor-eval/overlapping-segments.wast.ctors binaryen-99/test/ctor-eval/overlapping-segments.wast.ctors --- binaryen-108/test/ctor-eval/overlapping-segments.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/overlapping-segments.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/overlapping-segments.wast.out binaryen-99/test/ctor-eval/overlapping-segments.wast.out --- binaryen-108/test/ctor-eval/overlapping-segments.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/overlapping-segments.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (type $none_=>_none (func)) - (table $0 46 funcref) - (elem $0 (i32.const 9) $1) - (elem $1 (i32.const 9) $0) - (export "test1" (func $2)) - (func $0 (result i32) - (unreachable) - ) - (func $1 (result i32) - (i32.const 65) - ) - (func $2 - (drop - (call_indirect $0 (type $none_=>_i32) - (i32.const 9) - ) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/params.wast binaryen-99/test/ctor-eval/params.wast --- binaryen-108/test/ctor-eval/params.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/params.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -(module - (func "test1" (param $x i32) - ;; The presence of params stops us from evalling this function, at least - ;; not with --ignore-external-input (see ignore-external-input.wast) - (nop) - ) -) diff -Nru binaryen-108/test/ctor-eval/params.wast.ctors binaryen-99/test/ctor-eval/params.wast.ctors --- binaryen-108/test/ctor-eval/params.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/params.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/params.wast.out binaryen-99/test/ctor-eval/params.wast.out --- binaryen-108/test/ctor-eval/params.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/params.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -(module - (type $i32_=>_none (func (param i32))) - (export "test1" (func $0)) - (func $0 (param $x i32) - (nop) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial-locals-tee.wast binaryen-99/test/ctor-eval/partial-locals-tee.wast --- binaryen-108/test/ctor-eval/partial-locals-tee.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-locals-tee.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -(module - (import "import" "import" (func $import (param i32 i32))) - - (memory 256 256) - (data (i32.const 10) "_________________") - - (export "test1" $test1) - - (func $test1 - (local $temp i32) - - ;; Increment $temp from 0 to 1, which we can eval. - (local.set $temp - (i32.add - (local.get $temp) - (i32.const 1) - ) - ) - - ;; A safe store that will be evalled and alter memory. - (i32.store8 (i32.const 12) (i32.const 115)) - - ;; A call to an import, which prevents evalling. We will stop here. The - ;; 'tee' instruction should *not* have any effect, that is, we should not - ;; partially eval this line in the block - we should eval none of it. - ;; TODO: We should support such partial line evalling, with more careful - ;; management of locals. - (call $import - (local.get $temp) ;; The value sent here should be '1'. - (local.tee $temp - (i32.const 50) - ) - ) - - ;; A safe store that we never reach - (i32.store8 (i32.const 13) (i32.const 115)) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial-locals-tee.wast.ctors binaryen-99/test/ctor-eval/partial-locals-tee.wast.ctors --- binaryen-108/test/ctor-eval/partial-locals-tee.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-locals-tee.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/partial-locals-tee.wast.out binaryen-99/test/ctor-eval/partial-locals-tee.wast.out --- binaryen-108/test/ctor-eval/partial-locals-tee.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-locals-tee.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -(module - (type $i32_i32_=>_none (func (param i32 i32))) - (type $none_=>_none (func)) - (import "import" "import" (func $import (param i32 i32))) - (memory $0 256 256) - (data (i32.const 10) "__s______________") - (export "test1" (func $test1_0)) - (func $test1_0 - (call $import - (i32.const 1) - (i32.const 50) - ) - (i32.store8 - (i32.const 13) - (i32.const 115) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial-locals.wast binaryen-99/test/ctor-eval/partial-locals.wast --- binaryen-108/test/ctor-eval/partial-locals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-locals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -(module - (import "import" "import" (func $import)) - - (memory 256 256) - (data (i32.const 10) "_________________") - - (export "test1" $test1) - - (global $sp (mut i32) (i32.const 100)) - - (func $test1 - (local $temp-sp i32) - - ;; Save and bump the stack pointer. - (local.set $temp-sp - (global.get $sp) - ) - (global.set $sp - (i32.add - (global.get $sp) - (i32.const 4) - ) - ) - - ;; A safe store, should alter memory - (i32.store8 (i32.const 12) (i32.const 115)) - - ;; A call to an import, which prevents evalling. We will stop here. After - ;; optimization we'll serialize the value of $temp-sp so that when the - ;; code is run later it runs properly. - ;; - ;; (Also, the global $sp will contain 104, the value after the bump.) - (call $import) - - ;; A safe store that we never reach - (i32.store8 (i32.const 13) (i32.const 115)) - - ;; Restore the stack pointer. - (global.set $sp - (local.get $temp-sp) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial-locals.wast.ctors binaryen-99/test/ctor-eval/partial-locals.wast.ctors --- binaryen-108/test/ctor-eval/partial-locals.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-locals.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/partial-locals.wast.out binaryen-99/test/ctor-eval/partial-locals.wast.out --- binaryen-108/test/ctor-eval/partial-locals.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-locals.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -(module - (type $none_=>_none (func)) - (import "import" "import" (func $import)) - (global $sp (mut i32) (i32.const 104)) - (memory $0 256 256) - (data (i32.const 10) "__s______________") - (export "test1" (func $test1_0)) - (func $test1_0 - (local $0 i32) - (local.set $0 - (i32.const 100) - ) - (call $import) - (i32.store8 - (i32.const 13) - (i32.const 115) - ) - (global.set $sp - (local.get $0) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial-return.wast binaryen-99/test/ctor-eval/partial-return.wast --- binaryen-108/test/ctor-eval/partial-return.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-return.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -(module - (import "import" "import" (func $import)) - - (memory 256 256) - (data (i32.const 10) "_________________") - - (export "test1" $test1) - (export "memory" (memory $0)) - - (func $test1 - ;; A safe store, should alter memory - (i32.store8 (i32.const 12) (i32.const 115)) - - ;; Load the value we just saved, and return because of its value. (This way - ;; we could not see the return must execute without ctor-eval. At least, not - ;; without store-load forwarding.) - (if - (i32.load8_u - (i32.const 12) - ) - (return) - ) - - ;; This is unsafe to call, and would stop evalling here. But we exit due to - ;; the return before anyhow, so it doesn't matter. - (call $import) - - ;; A safe store that we never reach because of the return before us. - (i32.store8 (i32.const 13) (i32.const 115)) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial-return.wast.ctors binaryen-99/test/ctor-eval/partial-return.wast.ctors --- binaryen-108/test/ctor-eval/partial-return.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-return.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/partial-return.wast.out binaryen-99/test/ctor-eval/partial-return.wast.out --- binaryen-108/test/ctor-eval/partial-return.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial-return.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -(module - (memory $0 256 256) - (data (i32.const 10) "__s______________") - (export "memory" (memory $0)) -) diff -Nru binaryen-108/test/ctor-eval/partial.wast binaryen-99/test/ctor-eval/partial.wast --- binaryen-108/test/ctor-eval/partial.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -(module - (import "import" "import" (func $import)) - - (memory 256 256) - (data (i32.const 10) "_________________") - - (export "test1" $test1) - - ;; Use the function in an additional export. We should still get the same - ;; results if we call this one, so it should point to identical contents as - ;; earlier - (export "keepalive" $test1) - - (func $test1 - ;; A safe store, should alter memory - (i32.store8 (i32.const 12) (i32.const 115)) - - ;; A call to an import, which prevents evalling. - (call $import) - - ;; Another safe store, but the import call before us will stop our evalling. - ;; As a result we will only partially eval this function, applying only - ;; the first store. - ;; - ;; After optimization, the test1 export will point to a function that does - ;; not have the first store anymore. It will contain just the call to the - ;; import and then this second store. - (i32.store8 (i32.const 13) (i32.const 114)) - ) -) diff -Nru binaryen-108/test/ctor-eval/partial.wast.ctors binaryen-99/test/ctor-eval/partial.wast.ctors --- binaryen-108/test/ctor-eval/partial.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1 diff -Nru binaryen-108/test/ctor-eval/partial.wast.out binaryen-99/test/ctor-eval/partial.wast.out --- binaryen-108/test/ctor-eval/partial.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/partial.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -(module - (type $none_=>_none (func)) - (import "import" "import" (func $import)) - (memory $0 256 256) - (data (i32.const 10) "__s______________") - (export "test1" (func $test1_0)) - (export "keepalive" (func $test1)) - (func $test1 - (i32.store8 - (i32.const 12) - (i32.const 115) - ) - (call $import) - (i32.store8 - (i32.const 13) - (i32.const 114) - ) - ) - (func $test1_0 - (call $import) - (i32.store8 - (i32.const 13) - (i32.const 114) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/results.wast binaryen-99/test/ctor-eval/results.wast --- binaryen-108/test/ctor-eval/results.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/results.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,100 +0,0 @@ -(module - (import "import" "import" (func $import)) - - (global $global1 (mut i32) (i32.const 1)) - (global $global2 (mut i32) (i32.const 2)) - (global $global3 (mut i32) (i32.const 3)) - (global $global4 (mut i32) (i32.const 4)) - (global $global5 (mut i32) (i32.const 5)) - - (func $test1 (export "test1") - ;; This function can be evalled. But in this test we keep this export, - ;; so we should still see an export, but the export should do nothing since - ;; the code has already run. - ;; - ;; In comparison, test3 below, with a result, will still contain a - ;; (constant) result in the remaining export once we can handle results. - - (global.set $global1 - (i32.const 11) - ) - ) - - (func $test2 (export "test2") - ;; As the above function, but the export is *not* kept. - (global.set $global2 - (i32.const 12) - ) - ) - - (func $test3 (export "test3") (result i32) - ;; The global.set can be evalled. We must then keep returning the 42. - (global.set $global3 - (i32.const 13) - ) - (i32.const 42) - ) - - (func $test4 (export "test4") (result i32) - ;; Similar to the above, but not in a toplevel block format that we can - ;; eval one item at a time. We will eval this entire function at once, and - ;; we should succeed. After that we should keep returning the constant 55 - (if (result i32) - (i32.const 1) - (block (result i32) - (global.set $global4 - (i32.const 14) - ) - (i32.const 55) - ) - (i32.const 99) - ) - ) - - (func $test5 (export "test5") (result i32) - ;; Tests partial evalling with a return value at the end. We never reach - ;; that return value, but we should eval the global.set. - (global.set $global5 - (i32.const 15) - ) - - (call $import) - - (i32.const 100) - ) - - (func "keepalive" (result i32) - ;; Keep everything alive to see the changes. - - ;; These should call the original $test1, not the one that is nopped out - ;; after evalling. - (call $test1) - (call $test2) - - (drop - (call $test3) - ) - (drop - (call $test4) - ) - (drop - (call $test5) - ) - - ;; Keeping these alive should show the changes to the globals (that should - ;; contain 11, 12, and 3). - (i32.add - (i32.add - (global.get $global1) - (global.get $global2) - ) - (i32.add - (global.get $global3) - (i32.add - (global.get $global4) - (global.get $global5) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/ctor-eval/results.wast.ctors binaryen-99/test/ctor-eval/results.wast.ctors --- binaryen-108/test/ctor-eval/results.wast.ctors 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/results.wast.ctors 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -test1,test2,test3,test4,test5 diff -Nru binaryen-108/test/ctor-eval/results.wast.out binaryen-99/test/ctor-eval/results.wast.out --- binaryen-108/test/ctor-eval/results.wast.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/ctor-eval/results.wast.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (type $none_=>_none (func)) - (import "import" "import" (func $import)) - (global $global1 (mut i32) (i32.const 11)) - (global $global2 (mut i32) (i32.const 12)) - (global $global3 (mut i32) (i32.const 13)) - (global $global4 (mut i32) (i32.const 14)) - (global $global5 (mut i32) (i32.const 15)) - (export "test1" (func $test1_0)) - (export "test3" (func $test3_0)) - (export "test5" (func $test5_0)) - (export "keepalive" (func $5)) - (func $test1 - (global.set $global1 - (i32.const 11) - ) - ) - (func $test2 - (global.set $global2 - (i32.const 12) - ) - ) - (func $test3 (result i32) - (global.set $global3 - (i32.const 13) - ) - (i32.const 42) - ) - (func $test4 (result i32) - (global.set $global4 - (i32.const 14) - ) - (i32.const 55) - ) - (func $test5 (result i32) - (global.set $global5 - (i32.const 15) - ) - (call $import) - (i32.const 100) - ) - (func $5 (result i32) - (call $test1) - (call $test2) - (drop - (call $test3) - ) - (drop - (call $test4) - ) - (drop - (call $test5) - ) - (i32.add - (i32.add - (global.get $global1) - (global.get $global2) - ) - (i32.add - (global.get $global3) - (i32.add - (global.get $global4) - (global.get $global5) - ) - ) - ) - ) - (func $test1_0 - (nop) - ) - (func $test3_0 (result i32) - (i32.const 42) - ) - (func $test5_0 (result i32) - (call $import) - (i32.const 100) - ) -) diff -Nru binaryen-108/test/ctor-eval/stack-direction.wast binaryen-99/test/ctor-eval/stack-direction.wast --- binaryen-108/test/ctor-eval/stack-direction.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/stack-direction.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,30 @@ +(module + (type $0 (func)) + (import "env" "memory" (memory $1 256 256)) + (import "env" "STACKTOP" (global $gimport$0 i32)) + (global $global$0 (mut i32) (global.get $gimport$0)) + (export "__post_instantiate" (func $0)) + ;; if the stack goes **down**, this may seem to write to memory we care about + (func $0 (; 0 ;) (type $0) + (local $0 i32) + (i32.store offset=12 + (local.tee $0 + (i32.sub + (global.get $global$0) + (i32.const 16) + ) + ) + (i32.const 10) + ) + (i32.store offset=12 + (local.get $0) + (i32.add + (i32.load offset=12 + (local.get $0) + ) + (i32.const 1) + ) + ) + ) +) + diff -Nru binaryen-108/test/ctor-eval/stack-direction.wast.ctors binaryen-99/test/ctor-eval/stack-direction.wast.ctors --- binaryen-108/test/ctor-eval/stack-direction.wast.ctors 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/stack-direction.wast.ctors 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +__post_instantiate diff -Nru binaryen-108/test/ctor-eval/stack-direction.wast.out binaryen-99/test/ctor-eval/stack-direction.wast.out --- binaryen-108/test/ctor-eval/stack-direction.wast.out 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/ctor-eval/stack-direction.wast.out 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,2 @@ +(module +) diff -Nru binaryen-108/test/duplicate_types.wast.fromBinary binaryen-99/test/duplicate_types.wast.fromBinary --- binaryen-108/test/duplicate_types.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/duplicate_types.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (param i32))) + (type $i32_=>_none (func (param i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (func $f0 (param $0 i32) (nop) diff -Nru binaryen-108/test/duplicate_types.wast.from-wast binaryen-99/test/duplicate_types.wast.from-wast --- binaryen-108/test/duplicate_types.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/duplicate_types.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (param i32))) + (type $i32_=>_none (func (param i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (func $f0 (param $0 i32) (nop) diff -Nru binaryen-108/test/events.wast binaryen-99/test/events.wast --- binaryen-108/test/events.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/events.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,16 @@ +;; Test events + +(module + (event (attr 0) (param i32)) + (event $e (attr 0) (param i32 f32)) + (event $empty (attr 0)) + + (event $e-params0 (attr 0) (param i32 f32)) + (event $e-params1 (attr 0) (param i32) (param f32)) + + (event $e-export (export "ex0") (attr 0) (param i32)) + (event $e-import (import "env" "im0") (attr 0) (param i32)) + + (import "env" "im1" (event (attr 0) (param i32 f32))) + (export "ex1" (event $e)) +) diff -Nru binaryen-108/test/events.wast.fromBinary binaryen-99/test/events.wast.fromBinary --- binaryen-108/test/events.wast.fromBinary 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/events.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,15 @@ +(module + (type $i32_f32_=>_none (func (param i32 f32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (import "env" "im0" (event $eimport$0 (attr 0) (param i32))) + (import "env" "im1" (event $eimport$1 (attr 0) (param i32 f32))) + (event $event$0 (attr 0) (param i32)) + (event $event$1 (attr 0) (param i32 f32)) + (event $event$2 (attr 0) (param)) + (event $event$3 (attr 0) (param i32 f32)) + (event $event$4 (attr 0) (param i32 f32)) + (event $event$5 (attr 0) (param i32)) + (export "ex1" (event $event$1)) +) + diff -Nru binaryen-108/test/events.wast.fromBinary.noDebugInfo binaryen-99/test/events.wast.fromBinary.noDebugInfo --- binaryen-108/test/events.wast.fromBinary.noDebugInfo 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/events.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,15 @@ +(module + (type $i32_f32_=>_none (func (param i32 f32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (import "env" "im0" (event $eimport$0 (attr 0) (param i32))) + (import "env" "im1" (event $eimport$1 (attr 0) (param i32 f32))) + (event $event$0 (attr 0) (param i32)) + (event $event$1 (attr 0) (param i32 f32)) + (event $event$2 (attr 0) (param)) + (event $event$3 (attr 0) (param i32 f32)) + (event $event$4 (attr 0) (param i32 f32)) + (event $event$5 (attr 0) (param i32)) + (export "ex1" (event $event$1)) +) + diff -Nru binaryen-108/test/events.wast.from-wast binaryen-99/test/events.wast.from-wast --- binaryen-108/test/events.wast.from-wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/events.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,14 @@ +(module + (type $i32_f32_=>_none (func (param i32 f32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (import "env" "im0" (event $e-import (attr 0) (param i32))) + (import "env" "im1" (event $eimport$1 (attr 0) (param i32 f32))) + (event $2 (attr 0) (param i32)) + (event $e (attr 0) (param i32 f32)) + (event $empty (attr 0) (param)) + (event $e-params0 (attr 0) (param i32 f32)) + (event $e-params1 (attr 0) (param i32 f32)) + (event $e-export (attr 0) (param i32)) + (export "ex1" (event $e)) +) diff -Nru binaryen-108/test/example/c-api-kitchen-sink.c binaryen-99/test/example/c-api-kitchen-sink.c --- binaryen-108/test/example/c-api-kitchen-sink.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/c-api-kitchen-sink.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,73 +12,41 @@ // kitchen sink, tests the full API + // helpers -static const uint8_t v128_bytes[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; +static const uint8_t v128_bytes[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; -BinaryenExpressionRef -makeUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenType inputType) { - if (inputType == BinaryenTypeInt32()) - return BinaryenUnary( - module, op, BinaryenConst(module, BinaryenLiteralInt32(-10))); - if (inputType == BinaryenTypeInt64()) - return BinaryenUnary( - module, op, BinaryenConst(module, BinaryenLiteralInt64(-22))); - if (inputType == BinaryenTypeFloat32()) - return BinaryenUnary( - module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612f))); - if (inputType == BinaryenTypeFloat64()) - return BinaryenUnary( - module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841))); - if (inputType == BinaryenTypeVec128()) - return BinaryenUnary( - module, op, BinaryenConst(module, BinaryenLiteralVec128(v128_bytes))); +BinaryenExpressionRef makeUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenType inputType) { + if (inputType == BinaryenTypeInt32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt32(-10))); + if (inputType == BinaryenTypeInt64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt64(-22))); + if (inputType == BinaryenTypeFloat32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612f))); + if (inputType == BinaryenTypeFloat64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841))); + if (inputType == BinaryenTypeVec128()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralVec128(v128_bytes))); abort(); } -BinaryenExpressionRef -makeBinary(BinaryenModuleRef module, BinaryenOp op, BinaryenType type) { +BinaryenExpressionRef makeBinary(BinaryenModuleRef module, BinaryenOp op, BinaryenType type) { if (type == BinaryenTypeInt32()) { - // use temp vars to ensure optimization doesn't change the order of - // operation in our trace recording - BinaryenExpressionRef temp = - BinaryenConst(module, BinaryenLiteralInt32(-11)); - return BinaryenBinary( - module, op, BinaryenConst(module, BinaryenLiteralInt32(-10)), temp); + // use temp vars to ensure optimization doesn't change the order of operation in our trace recording + BinaryenExpressionRef temp = BinaryenConst(module, BinaryenLiteralInt32(-11)); + return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralInt32(-10)), temp); } if (type == BinaryenTypeInt64()) { - BinaryenExpressionRef temp = - BinaryenConst(module, BinaryenLiteralInt64(-23)); - return BinaryenBinary( - module, op, BinaryenConst(module, BinaryenLiteralInt64(-22)), temp); + BinaryenExpressionRef temp = BinaryenConst(module, BinaryenLiteralInt64(-23)); + return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralInt64(-22)), temp); } if (type == BinaryenTypeFloat32()) { - BinaryenExpressionRef temp = - BinaryenConst(module, BinaryenLiteralFloat32(-62.5f)); - return BinaryenBinary( - module, - op, - BinaryenConst(module, BinaryenLiteralFloat32(-33.612f)), - temp); + BinaryenExpressionRef temp = BinaryenConst(module, BinaryenLiteralFloat32(-62.5f)); + return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612f)), temp); } if (type == BinaryenTypeFloat64()) { - BinaryenExpressionRef temp = - BinaryenConst(module, BinaryenLiteralFloat64(-9007.333)); - return BinaryenBinary( - module, - op, - BinaryenConst(module, BinaryenLiteralFloat64(-9005.841)), - temp); + BinaryenExpressionRef temp = BinaryenConst(module, BinaryenLiteralFloat64(-9007.333)); + return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841)), temp); } if (type == BinaryenTypeVec128()) { - BinaryenExpressionRef temp = - BinaryenConst(module, BinaryenLiteralVec128(v128_bytes)); - return BinaryenBinary( - module, - op, - BinaryenConst(module, BinaryenLiteralVec128(v128_bytes)), - temp); + BinaryenExpressionRef temp = BinaryenConst(module, BinaryenLiteralVec128(v128_bytes)); + return BinaryenBinary(module, op, BinaryenConst(module, BinaryenLiteralVec128(v128_bytes)), temp); } abort(); } @@ -99,8 +67,7 @@ return BinaryenConst(module, BinaryenLiteralFloat64(x)); } -BinaryenExpressionRef makeVec128(BinaryenModuleRef module, - uint8_t const* bytes) { +BinaryenExpressionRef makeVec128(BinaryenModuleRef module, uint8_t const *bytes) { return BinaryenConst(module, BinaryenLiteralVec128(bytes)); } @@ -116,8 +83,7 @@ return BinaryenSIMDExtract(module, op, makeVec128(module, v128_bytes), 0); } -BinaryenExpressionRef -makeSIMDReplace(BinaryenModuleRef module, BinaryenOp op, BinaryenType type) { +BinaryenExpressionRef makeSIMDReplace(BinaryenModuleRef module, BinaryenOp op, BinaryenType type) { BinaryenExpressionRef val; if (type == BinaryenTypeInt32()) { val = makeInt32(module, 42); @@ -134,14 +100,13 @@ if (!val) { abort(); } - return BinaryenSIMDReplace( - module, op, makeVec128(module, v128_bytes), 0, val); + return BinaryenSIMDReplace(module, op, makeVec128(module, v128_bytes), 0, val); } BinaryenExpressionRef makeSIMDShuffle(BinaryenModuleRef module) { BinaryenExpressionRef left = makeVec128(module, v128_bytes); BinaryenExpressionRef right = makeVec128(module, v128_bytes); - return BinaryenSIMDShuffle(module, left, right, (uint8_t[16]){}); + return BinaryenSIMDShuffle(module, left, right, (uint8_t[16]) {}); } BinaryenExpressionRef makeSIMDTernary(BinaryenModuleRef module, BinaryenOp op) { @@ -240,6 +205,12 @@ BinaryenTypeExpand(externref, &valueType); assert(valueType == externref); + BinaryenType exnref = BinaryenTypeExnref(); + printf(" // BinaryenTypeExnref: %d\n", exnref); + assert(BinaryenTypeArity(exnref) == 1); + BinaryenTypeExpand(exnref, &valueType); + assert(valueType == exnref); + BinaryenType anyref = BinaryenTypeAnyref(); printf(" // BinaryenTypeAnyref: %d\n", anyref); assert(BinaryenTypeArity(anyref) == 1); @@ -258,12 +229,6 @@ BinaryenTypeExpand(i31ref, &valueType); assert(valueType == i31ref); - BinaryenType dataref = BinaryenTypeDataref(); - printf(" // BinaryenTypeDataref: %d\n", dataref); - assert(BinaryenTypeArity(dataref) == 1); - BinaryenTypeExpand(dataref, &valueType); - assert(valueType == dataref); - printf(" // BinaryenTypeAuto: %d\n", BinaryenTypeAuto()); BinaryenType pair[] = {i32, i32}; @@ -286,24 +251,16 @@ printf("BinaryenFeatureMVP: %d\n", BinaryenFeatureMVP()); printf("BinaryenFeatureAtomics: %d\n", BinaryenFeatureAtomics()); printf("BinaryenFeatureBulkMemory: %d\n", BinaryenFeatureBulkMemory()); - printf("BinaryenFeatureMutableGlobals: %d\n", - BinaryenFeatureMutableGlobals()); - printf("BinaryenFeatureNontrappingFPToInt: %d\n", - BinaryenFeatureNontrappingFPToInt()); + printf("BinaryenFeatureMutableGlobals: %d\n", BinaryenFeatureMutableGlobals()); + printf("BinaryenFeatureNontrappingFPToInt: %d\n", BinaryenFeatureNontrappingFPToInt()); printf("BinaryenFeatureSignExt: %d\n", BinaryenFeatureSignExt()); printf("BinaryenFeatureSIMD128: %d\n", BinaryenFeatureSIMD128()); - printf("BinaryenFeatureExceptionHandling: %d\n", - BinaryenFeatureExceptionHandling()); + printf("BinaryenFeatureExceptionHandling: %d\n", BinaryenFeatureExceptionHandling()); printf("BinaryenFeatureTailCall: %d\n", BinaryenFeatureTailCall()); - printf("BinaryenFeatureReferenceTypes: %d\n", - BinaryenFeatureReferenceTypes()); + printf("BinaryenFeatureReferenceTypes: %d\n", BinaryenFeatureReferenceTypes()); printf("BinaryenFeatureMultivalue: %d\n", BinaryenFeatureMultivalue()); printf("BinaryenFeatureGC: %d\n", BinaryenFeatureGC()); printf("BinaryenFeatureMemory64: %d\n", BinaryenFeatureMemory64()); - printf("BinaryenFeatureTypedFunctionReferences: %d\n", - BinaryenFeatureTypedFunctionReferences()); - printf("BinaryenFeatureRelaxedSIMD: %d\n", BinaryenFeatureRelaxedSIMD()); - printf("BinaryenFeatureExtendedConst: %d\n", BinaryenFeatureExtendedConst()); printf("BinaryenFeatureAll: %d\n", BinaryenFeatureAll()); } @@ -315,30 +272,20 @@ // Literals and consts - BinaryenExpressionRef - constI32 = BinaryenConst(module, BinaryenLiteralInt32(1)), - constI64 = BinaryenConst(module, BinaryenLiteralInt64(2)), - constF32 = BinaryenConst(module, BinaryenLiteralFloat32(3.14f)), - constF64 = BinaryenConst(module, BinaryenLiteralFloat64(2.1828)), - constF32Bits = - BinaryenConst(module, BinaryenLiteralFloat32Bits(0xffff1234)), - constF64Bits = - BinaryenConst(module, BinaryenLiteralFloat64Bits(0xffff12345678abcdLL)), - constV128 = BinaryenConst(module, BinaryenLiteralVec128(v128_bytes)); - - const char* switchValueNames[] = {"the-value"}; - const char* switchBodyNames[] = {"the-nothing"}; - - BinaryenExpressionRef callOperands2[] = {makeInt32(module, 13), - makeFloat64(module, 3.7)}; - BinaryenExpressionRef callOperands4[] = {makeInt32(module, 13), - makeInt64(module, 37), - makeFloat32(module, 1.3f), - makeFloat64(module, 3.7)}; - BinaryenExpressionRef callOperands4b[] = {makeInt32(module, 13), - makeInt64(module, 37), - makeFloat32(module, 1.3f), - makeFloat64(module, 3.7)}; + BinaryenExpressionRef constI32 = BinaryenConst(module, BinaryenLiteralInt32(1)), + constI64 = BinaryenConst(module, BinaryenLiteralInt64(2)), + constF32 = BinaryenConst(module, BinaryenLiteralFloat32(3.14f)), + constF64 = BinaryenConst(module, BinaryenLiteralFloat64(2.1828)), + constF32Bits = BinaryenConst(module, BinaryenLiteralFloat32Bits(0xffff1234)), + constF64Bits = BinaryenConst(module, BinaryenLiteralFloat64Bits(0xffff12345678abcdLL)), + constV128 = BinaryenConst(module, BinaryenLiteralVec128(v128_bytes)); + + const char* switchValueNames[] = { "the-value" }; + const char* switchBodyNames[] = { "the-nothing" }; + + BinaryenExpressionRef callOperands2[] = { makeInt32(module, 13), makeFloat64(module, 3.7) }; + BinaryenExpressionRef callOperands4[] = { makeInt32(module, 13), makeInt64(module, 37), makeFloat32(module, 1.3f), makeFloat64(module, 3.7) }; + BinaryenExpressionRef callOperands4b[] = { makeInt32(module, 13), makeInt64(module, 37), makeFloat32(module, 1.3f), makeFloat64(module, 3.7) }; BinaryenExpressionRef tupleElements4a[] = {makeInt32(module, 13), makeInt64(module, 37), makeFloat32(module, 1.3f), @@ -354,57 +301,64 @@ BinaryenTypeFloat64()}; BinaryenType iIfF = BinaryenTypeCreate(iIfF_, 4); - BinaryenExpressionRef temp1 = makeInt32(module, 1), - temp2 = makeInt32(module, 2), - temp3 = makeInt32(module, 3), - temp4 = makeInt32(module, 4), - temp5 = makeInt32(module, 5), - temp6 = makeInt32(module, 0), - temp7 = makeInt32(module, 1), - temp8 = makeInt32(module, 0), - temp9 = makeInt32(module, 1), - temp10 = makeInt32(module, 1), - temp11 = makeInt32(module, 3), - temp12 = makeInt32(module, 5), - temp13 = makeInt32(module, 10), - temp14 = makeInt32(module, 11), - temp15 = makeInt32(module, 110), - temp16 = makeInt64(module, 111); - BinaryenExpressionRef externrefExpr = - BinaryenRefNull(module, BinaryenTypeExternref()); - BinaryenExpressionRef funcrefExpr = - BinaryenRefNull(module, BinaryenTypeFuncref()); + BinaryenExpressionRef temp1 = makeInt32(module, 1), temp2 = makeInt32(module, 2), temp3 = makeInt32(module, 3), + temp4 = makeInt32(module, 4), temp5 = makeInt32(module, 5), + temp6 = makeInt32(module, 0), temp7 = makeInt32(module, 1), + temp8 = makeInt32(module, 0), temp9 = makeInt32(module, 1), + temp10 = makeInt32(module, 1), temp11 = makeInt32(module, 3), temp12 = makeInt32(module, 5), + temp13 = makeInt32(module, 10), temp14 = makeInt32(module, 11), + temp15 = makeInt32(module, 110), temp16 = makeInt64(module, 111); + BinaryenExpressionRef externrefExpr = BinaryenRefNull(module, BinaryenTypeExternref()); + BinaryenExpressionRef funcrefExpr = BinaryenRefNull(module, BinaryenTypeFuncref()); funcrefExpr = BinaryenRefFunc(module, "kitchen()sinker", BinaryenTypeFuncref()); - BinaryenExpressionRef i31refExpr = - BinaryenI31New(module, makeInt32(module, 1)); + BinaryenExpressionRef exnrefExpr = BinaryenRefNull(module, BinaryenTypeExnref()); + BinaryenExpressionRef i31refExpr = BinaryenI31New(module, makeInt32(module, 1)); - // Tags - BinaryenAddTag(module, "a-tag", BinaryenTypeInt32(), BinaryenTypeNone()); - - BinaryenAddTable(module, "tab", 0, 100, BinaryenTypeFuncref()); + // Events + BinaryenAddEvent( + module, "a-event", 0, BinaryenTypeInt32(), BinaryenTypeNone()); // Exception handling // (try // (do - // (throw $a-tag (i32.const 0)) + // (throw $a-event (i32.const 0)) // ) - // (catch $a-tag - // (drop (i32 pop)) + // (catch + // ;; We don't support multi-value yet. Use locals instead. + // (local.set 0 (exnref.pop)) + // (drop + // (block $try-block (result i32) + // (rethrow + // (br_on_exn $try-block $a-event (local.get 5)) + // ) + // ) + // ) // ) - // (catch_all) // ) BinaryenExpressionRef tryBody = BinaryenThrow( - module, "a-tag", (BinaryenExpressionRef[]){makeInt32(module, 0)}, 1); - BinaryenExpressionRef catchBody = - BinaryenDrop(module, BinaryenPop(module, BinaryenTypeInt32())); - BinaryenExpressionRef catchAllBody = BinaryenNop(module); - const char* catchTags[] = {"a-tag"}; - BinaryenExpressionRef catchBodies[] = {catchBody, catchAllBody}; - const char* emptyCatchTags[] = {}; - BinaryenExpressionRef emptyCatchBodies[] = {}; - BinaryenExpressionRef nopCatchBody[] = {BinaryenNop(module)}; + module, "a-event", (BinaryenExpressionRef[]){makeInt32(module, 0)}, 1); + BinaryenExpressionRef catchBody = BinaryenBlock( + module, + NULL, + (BinaryenExpressionRef[]){ + BinaryenLocalSet(module, 5, BinaryenPop(module, BinaryenTypeExnref())), + BinaryenDrop( + module, + BinaryenBlock(module, + "try-block", + (BinaryenExpressionRef[]){BinaryenRethrow( + module, + BinaryenBrOnExn( + module, + "try-block", + "a-event", + BinaryenLocalGet(module, 5, BinaryenTypeExnref())))}, + 1, + BinaryenTypeInt32()))}, + 2, + BinaryenTypeNone()); BinaryenType i32 = BinaryenTypeInt32(); BinaryenType i64 = BinaryenTypeInt64(); @@ -465,24 +419,22 @@ makeUnary(module, BinaryenSplatVecF32x4(), f32), makeUnary(module, BinaryenSplatVecF64x2(), f64), makeUnary(module, BinaryenNotVec128(), v128), - makeUnary(module, BinaryenAnyTrueVec128(), v128), - makeUnary(module, BinaryenPopcntVecI8x16(), v128), makeUnary(module, BinaryenAbsVecI8x16(), v128), makeUnary(module, BinaryenNegVecI8x16(), v128), + makeUnary(module, BinaryenAnyTrueVecI8x16(), v128), makeUnary(module, BinaryenAllTrueVecI8x16(), v128), makeUnary(module, BinaryenBitmaskVecI8x16(), v128), makeUnary(module, BinaryenAbsVecI16x8(), v128), makeUnary(module, BinaryenNegVecI16x8(), v128), + makeUnary(module, BinaryenAnyTrueVecI16x8(), v128), makeUnary(module, BinaryenAllTrueVecI16x8(), v128), makeUnary(module, BinaryenBitmaskVecI16x8(), v128), makeUnary(module, BinaryenAbsVecI32x4(), v128), makeUnary(module, BinaryenNegVecI32x4(), v128), + makeUnary(module, BinaryenAnyTrueVecI32x4(), v128), makeUnary(module, BinaryenAllTrueVecI32x4(), v128), makeUnary(module, BinaryenBitmaskVecI32x4(), v128), - makeUnary(module, BinaryenAbsVecI64x2(), v128), makeUnary(module, BinaryenNegVecI64x2(), v128), - makeUnary(module, BinaryenAllTrueVecI64x2(), v128), - makeUnary(module, BinaryenBitmaskVecI64x2(), v128), makeUnary(module, BinaryenAbsVecF32x4(), v128), makeUnary(module, BinaryenNegVecF32x4(), v128), makeUnary(module, BinaryenSqrtVecF32x4(), v128), @@ -491,26 +443,20 @@ makeUnary(module, BinaryenSqrtVecF64x2(), v128), makeUnary(module, BinaryenTruncSatSVecF32x4ToVecI32x4(), v128), makeUnary(module, BinaryenTruncSatUVecF32x4ToVecI32x4(), v128), + makeUnary(module, BinaryenTruncSatSVecF64x2ToVecI64x2(), v128), + makeUnary(module, BinaryenTruncSatUVecF64x2ToVecI64x2(), v128), makeUnary(module, BinaryenConvertSVecI32x4ToVecF32x4(), v128), makeUnary(module, BinaryenConvertUVecI32x4ToVecF32x4(), v128), - makeUnary(module, BinaryenExtendLowSVecI8x16ToVecI16x8(), v128), - makeUnary(module, BinaryenExtendHighSVecI8x16ToVecI16x8(), v128), - makeUnary(module, BinaryenExtendLowUVecI8x16ToVecI16x8(), v128), - makeUnary(module, BinaryenExtendHighUVecI8x16ToVecI16x8(), v128), - makeUnary(module, BinaryenExtendLowSVecI16x8ToVecI32x4(), v128), - makeUnary(module, BinaryenExtendHighSVecI16x8ToVecI32x4(), v128), - makeUnary(module, BinaryenExtendLowUVecI16x8ToVecI32x4(), v128), - makeUnary(module, BinaryenExtendHighUVecI16x8ToVecI32x4(), v128), - makeUnary(module, BinaryenExtendLowSVecI32x4ToVecI64x2(), v128), - makeUnary(module, BinaryenExtendHighSVecI32x4ToVecI64x2(), v128), - makeUnary(module, BinaryenExtendLowUVecI32x4ToVecI64x2(), v128), - makeUnary(module, BinaryenExtendHighUVecI32x4ToVecI64x2(), v128), - makeUnary(module, BinaryenConvertLowSVecI32x4ToVecF64x2(), v128), - makeUnary(module, BinaryenConvertLowUVecI32x4ToVecF64x2(), v128), - makeUnary(module, BinaryenTruncSatZeroSVecF64x2ToVecI32x4(), v128), - makeUnary(module, BinaryenTruncSatZeroUVecF64x2ToVecI32x4(), v128), - makeUnary(module, BinaryenDemoteZeroVecF64x2ToVecF32x4(), v128), - makeUnary(module, BinaryenPromoteLowVecF32x4ToVecF64x2(), v128), + makeUnary(module, BinaryenConvertSVecI64x2ToVecF64x2(), v128), + makeUnary(module, BinaryenConvertUVecI64x2ToVecF64x2(), v128), + makeUnary(module, BinaryenWidenLowSVecI8x16ToVecI16x8(), v128), + makeUnary(module, BinaryenWidenHighSVecI8x16ToVecI16x8(), v128), + makeUnary(module, BinaryenWidenLowUVecI8x16ToVecI16x8(), v128), + makeUnary(module, BinaryenWidenHighUVecI8x16ToVecI16x8(), v128), + makeUnary(module, BinaryenWidenLowSVecI16x8ToVecI32x4(), v128), + makeUnary(module, BinaryenWidenHighSVecI16x8ToVecI32x4(), v128), + makeUnary(module, BinaryenWidenLowUVecI16x8ToVecI32x4(), v128), + makeUnary(module, BinaryenWidenHighUVecI16x8ToVecI32x4(), v128), // Binary makeBinary(module, BinaryenAddInt32(), i32), makeBinary(module, BinaryenSubFloat64(), f64), @@ -574,12 +520,6 @@ makeBinary(module, BinaryenLeUVecI32x4(), v128), makeBinary(module, BinaryenGeSVecI32x4(), v128), makeBinary(module, BinaryenGeUVecI32x4(), v128), - makeBinary(module, BinaryenEqVecI64x2(), v128), - makeBinary(module, BinaryenNeVecI64x2(), v128), - makeBinary(module, BinaryenLtSVecI64x2(), v128), - makeBinary(module, BinaryenGtSVecI64x2(), v128), - makeBinary(module, BinaryenLeSVecI64x2(), v128), - makeBinary(module, BinaryenGeSVecI64x2(), v128), makeBinary(module, BinaryenEqVecF32x4(), v128), makeBinary(module, BinaryenNeVecF32x4(), v128), makeBinary(module, BinaryenLtVecF32x4(), v128), @@ -602,6 +542,7 @@ makeBinary(module, BinaryenSubVecI8x16(), v128), makeBinary(module, BinaryenSubSatSVecI8x16(), v128), makeBinary(module, BinaryenSubSatUVecI8x16(), v128), + makeBinary(module, BinaryenMulVecI8x16(), v128), makeBinary(module, BinaryenMinSVecI8x16(), v128), makeBinary(module, BinaryenMinUVecI8x16(), v128), makeBinary(module, BinaryenMaxSVecI8x16(), v128), @@ -619,21 +560,12 @@ makeBinary(module, BinaryenMaxSVecI16x8(), v128), makeBinary(module, BinaryenMaxUVecI16x8(), v128), makeBinary(module, BinaryenAvgrUVecI16x8(), v128), - makeBinary(module, BinaryenQ15MulrSatSVecI16x8(), v128), - makeBinary(module, BinaryenExtMulLowSVecI16x8(), v128), - makeBinary(module, BinaryenExtMulHighSVecI16x8(), v128), - makeBinary(module, BinaryenExtMulLowUVecI16x8(), v128), - makeBinary(module, BinaryenExtMulHighUVecI16x8(), v128), makeBinary(module, BinaryenAddVecI32x4(), v128), makeBinary(module, BinaryenSubVecI32x4(), v128), makeBinary(module, BinaryenMulVecI32x4(), v128), makeBinary(module, BinaryenAddVecI64x2(), v128), makeBinary(module, BinaryenSubVecI64x2(), v128), makeBinary(module, BinaryenMulVecI64x2(), v128), - makeBinary(module, BinaryenExtMulLowSVecI64x2(), v128), - makeBinary(module, BinaryenExtMulHighSVecI64x2(), v128), - makeBinary(module, BinaryenExtMulLowUVecI64x2(), v128), - makeBinary(module, BinaryenExtMulHighUVecI64x2(), v128), makeBinary(module, BinaryenAddVecF32x4(), v128), makeBinary(module, BinaryenSubVecF32x4(), v128), makeBinary(module, BinaryenMulVecF32x4(), v128), @@ -642,10 +574,6 @@ makeBinary(module, BinaryenMaxSVecI32x4(), v128), makeBinary(module, BinaryenMaxUVecI32x4(), v128), makeBinary(module, BinaryenDotSVecI16x8ToVecI32x4(), v128), - makeBinary(module, BinaryenExtMulLowSVecI32x4(), v128), - makeBinary(module, BinaryenExtMulHighSVecI32x4(), v128), - makeBinary(module, BinaryenExtMulLowUVecI32x4(), v128), - makeBinary(module, BinaryenExtMulHighUVecI32x4(), v128), makeBinary(module, BinaryenDivVecF32x4(), v128), makeBinary(module, BinaryenMinVecF32x4(), v128), makeBinary(module, BinaryenMaxVecF32x4(), v128), @@ -667,15 +595,11 @@ makeUnary(module, BinaryenFloorVecF64x2(), v128), makeUnary(module, BinaryenTruncVecF64x2(), v128), makeUnary(module, BinaryenNearestVecF64x2(), v128), - makeUnary(module, BinaryenExtAddPairwiseSVecI8x16ToI16x8(), v128), - makeUnary(module, BinaryenExtAddPairwiseUVecI8x16ToI16x8(), v128), - makeUnary(module, BinaryenExtAddPairwiseSVecI16x8ToI32x4(), v128), - makeUnary(module, BinaryenExtAddPairwiseUVecI16x8ToI32x4(), v128), makeBinary(module, BinaryenNarrowSVecI16x8ToVecI8x16(), v128), makeBinary(module, BinaryenNarrowUVecI16x8ToVecI8x16(), v128), makeBinary(module, BinaryenNarrowSVecI32x4ToVecI16x8(), v128), makeBinary(module, BinaryenNarrowUVecI32x4ToVecI16x8(), v128), - makeBinary(module, BinaryenSwizzleVecI8x16(), v128), + makeBinary(module, BinaryenSwizzleVec8x16(), v128), // SIMD lane manipulation makeSIMDExtract(module, BinaryenExtractLaneSVecI8x16()), makeSIMDExtract(module, BinaryenExtractLaneUVecI8x16()), @@ -706,90 +630,44 @@ makeSIMDShift(module, BinaryenShrUVecI64x2()), // SIMD load BinaryenSIMDLoad( - module, BinaryenLoad8SplatVec128(), 0, 1, makeInt32(module, 128)), - BinaryenSIMDLoad( - module, BinaryenLoad16SplatVec128(), 16, 1, makeInt32(module, 128)), - BinaryenSIMDLoad( - module, BinaryenLoad32SplatVec128(), 16, 4, makeInt32(module, 128)), - BinaryenSIMDLoad( - module, BinaryenLoad64SplatVec128(), 0, 4, makeInt32(module, 128)), + module, BinaryenLoadSplatVec8x16(), 0, 1, makeInt32(module, 128)), BinaryenSIMDLoad( - module, BinaryenLoad8x8SVec128(), 0, 8, makeInt32(module, 128)), + module, BinaryenLoadSplatVec16x8(), 16, 1, makeInt32(module, 128)), BinaryenSIMDLoad( - module, BinaryenLoad8x8UVec128(), 0, 8, makeInt32(module, 128)), + module, BinaryenLoadSplatVec32x4(), 16, 4, makeInt32(module, 128)), BinaryenSIMDLoad( - module, BinaryenLoad16x4SVec128(), 0, 8, makeInt32(module, 128)), + module, BinaryenLoadSplatVec64x2(), 0, 4, makeInt32(module, 128)), BinaryenSIMDLoad( - module, BinaryenLoad16x4UVec128(), 0, 8, makeInt32(module, 128)), + module, BinaryenLoadExtSVec8x8ToVecI16x8(), 0, 8, makeInt32(module, 128)), BinaryenSIMDLoad( - module, BinaryenLoad32x2SVec128(), 0, 8, makeInt32(module, 128)), - BinaryenSIMDLoad( - module, BinaryenLoad32x2UVec128(), 0, 8, makeInt32(module, 128)), - BinaryenSIMDLoad( - module, BinaryenLoad32ZeroVec128(), 0, 4, makeInt32(module, 128)), - BinaryenSIMDLoad( - module, BinaryenLoad64ZeroVec128(), 0, 8, makeInt32(module, 128)), - // SIMD load/store lane - BinaryenSIMDLoadStoreLane(module, - BinaryenLoad8LaneVec128(), - 0, - 1, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - BinaryenSIMDLoadStoreLane(module, - BinaryenLoad16LaneVec128(), - 0, - 2, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - BinaryenSIMDLoadStoreLane(module, - BinaryenLoad32LaneVec128(), - 0, - 4, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - BinaryenSIMDLoadStoreLane(module, - BinaryenLoad64LaneVec128(), - 0, - 8, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - - BinaryenSIMDLoadStoreLane(module, - BinaryenStore8LaneVec128(), - 0, - 1, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - BinaryenSIMDLoadStoreLane(module, - BinaryenStore16LaneVec128(), - 0, - 2, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - BinaryenSIMDLoadStoreLane(module, - BinaryenStore32LaneVec128(), - 0, - 4, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), - BinaryenSIMDLoadStoreLane(module, - BinaryenStore64LaneVec128(), - 0, - 8, - 0, - makeInt32(module, 128), - makeVec128(module, v128_bytes)), + module, BinaryenLoadExtUVec8x8ToVecI16x8(), 0, 8, makeInt32(module, 128)), + BinaryenSIMDLoad(module, + BinaryenLoadExtSVec16x4ToVecI32x4(), + 0, + 8, + makeInt32(module, 128)), + BinaryenSIMDLoad(module, + BinaryenLoadExtUVec16x4ToVecI32x4(), + 0, + 8, + makeInt32(module, 128)), + BinaryenSIMDLoad(module, + BinaryenLoadExtSVec32x2ToVecI64x2(), + 0, + 8, + makeInt32(module, 128)), + BinaryenSIMDLoad(module, + BinaryenLoadExtUVec32x2ToVecI64x2(), + 0, + 8, + makeInt32(module, 128)), // Other SIMD makeSIMDShuffle(module), makeSIMDTernary(module, BinaryenBitselectVec128()), + makeSIMDTernary(module, BinaryenQFMAVecF32x4()), + makeSIMDTernary(module, BinaryenQFMSVecF32x4()), + makeSIMDTernary(module, BinaryenQFMAVecF64x2()), + makeSIMDTernary(module, BinaryenQFMSVecF64x2()), // Bulk memory makeMemoryInit(module), makeDataDrop(module), @@ -825,7 +703,6 @@ BinaryenUnary(module, BinaryenEqZInt32(), // check the output type of the call node BinaryenCallIndirect(module, - "tab", makeInt32(module, 2449), callOperands4b, 4, @@ -850,15 +727,15 @@ BinaryenReturnCall( module, "kitchen()sinker", callOperands4, 4, BinaryenTypeInt32()), BinaryenReturnCallIndirect(module, - "tab", makeInt32(module, 2449), callOperands4b, 4, iIfF, BinaryenTypeInt32()), // Reference types - BinaryenRefIs(module, BinaryenRefIsNull(), externrefExpr), - BinaryenRefIs(module, BinaryenRefIsNull(), funcrefExpr), + BinaryenRefIsNull(module, externrefExpr), + BinaryenRefIsNull(module, funcrefExpr), + BinaryenRefIsNull(module, exnrefExpr), BinaryenSelect( module, temp10, @@ -869,55 +746,8 @@ BinaryenRefEq(module, BinaryenRefNull(module, BinaryenTypeEqref()), BinaryenRefNull(module, BinaryenTypeEqref())), - BinaryenRefIs(module, - BinaryenRefIsFunc(), - BinaryenRefNull(module, BinaryenTypeAnyref())), - BinaryenRefIs(module, - BinaryenRefIsData(), - BinaryenRefNull(module, BinaryenTypeAnyref())), - BinaryenRefIs(module, - BinaryenRefIsI31(), - BinaryenRefNull(module, BinaryenTypeAnyref())), - BinaryenRefAs(module, - BinaryenRefAsNonNull(), - BinaryenRefNull(module, BinaryenTypeAnyref())), - BinaryenRefAs(module, - BinaryenRefAsFunc(), - BinaryenRefNull(module, BinaryenTypeAnyref())), - BinaryenRefAs(module, - BinaryenRefAsData(), - BinaryenRefNull(module, BinaryenTypeAnyref())), - BinaryenRefAs(module, - BinaryenRefAsI31(), - BinaryenRefNull(module, BinaryenTypeAnyref())), // Exception handling - BinaryenTry(module, NULL, tryBody, catchTags, 1, catchBodies, 2, NULL), - // (try $try_outer - // (do - // (try - // (do - // (throw $a-tag (i32.const 0)) - // ) - // (delegate $try_outer) - // ) - // ) - // (catch_all) - // ) - BinaryenTry(module, - "try_outer", - BinaryenTry(module, - NULL, - tryBody, - emptyCatchTags, - 0, - emptyCatchBodies, - 0, - "try_outer"), - emptyCatchTags, - 0, - nopCatchBody, - 1, - NULL), + BinaryenTry(module, tryBody, catchBody), // Atomics BinaryenAtomicStore( module, @@ -942,6 +772,7 @@ BinaryenPop(module, BinaryenTypeFloat64()), BinaryenPop(module, BinaryenTypeFuncref()), BinaryenPop(module, BinaryenTypeExternref()), + BinaryenPop(module, BinaryenTypeExnref()), BinaryenPop(module, iIfF), // Memory BinaryenMemorySize(module), @@ -955,11 +786,9 @@ BinaryenUnreachable(module), }; - BinaryenExpressionPrint( - valueList[3]); // test printing a standalone expression + BinaryenExpressionPrint(valueList[3]); // test printing a standalone expression - // Make the main body of the function. and one block with a return value, one - // without + // Make the main body of the function. and one block with a return value, one without BinaryenExpressionRef value = BinaryenBlock(module, "the-value", @@ -967,26 +796,20 @@ sizeof(valueList) / sizeof(BinaryenExpressionRef), BinaryenTypeAuto()); BinaryenExpressionRef droppedValue = BinaryenDrop(module, value); - BinaryenExpressionRef nothing = - BinaryenBlock(module, "the-nothing", &droppedValue, 1, -1); - BinaryenExpressionRef bodyList[] = {nothing, makeInt32(module, 42)}; + BinaryenExpressionRef nothing = BinaryenBlock(module, "the-nothing", &droppedValue, 1, -1); + BinaryenExpressionRef bodyList[] = { nothing, makeInt32(module, 42) }; BinaryenExpressionRef body = BinaryenBlock(module, "the-body", bodyList, 2, BinaryenTypeAuto()); // Create the function - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeExternref()}; + BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeExnref()}; BinaryenFunctionRef sinker = BinaryenAddFunction( module, "kitchen()sinker", iIfF, BinaryenTypeInt32(), localTypes, 2, body); // Globals - BinaryenAddGlobal( - module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, 7)); - BinaryenAddGlobal(module, - "a-mutable-global", - BinaryenTypeFloat32(), - 1, - makeFloat32(module, 7.5)); + BinaryenAddGlobal(module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, 7)); + BinaryenAddGlobal(module, "a-mutable-global", BinaryenTypeFloat32(), 1, makeFloat32(module, 7.5)); // Imports @@ -1000,63 +823,16 @@ BinaryenAddFunctionExport(module, "kitchen()sinker", "kitchen_sinker"); // Function table. One per module - const char* funcNames[] = {BinaryenFunctionGetName(sinker)}; - BinaryenAddTable(module, "0", 1, 1, BinaryenTypeFuncref()); - BinaryenAddActiveElementSegment( - module, - "0", - "0", - funcNames, - 1, - BinaryenConst(module, BinaryenLiteralInt32(0))); - BinaryenAddPassiveElementSegment(module, "passive", funcNames, 1); - BinaryenAddPassiveElementSegment(module, "p2", funcNames, 1); - BinaryenRemoveElementSegment(module, "p2"); - - BinaryenExpressionRef funcrefExpr1 = - BinaryenRefFunc(module, "kitchen()sinker", BinaryenTypeFuncref()); - - BinaryenExpressionPrint(BinaryenTableSet( - module, "0", BinaryenConst(module, BinaryenLiteralInt32(0)), funcrefExpr1)); - - BinaryenExpressionRef funcrefExpr2 = - BinaryenTableGet(module, - "0", - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenTypeFuncref()); - - BinaryenExpressionPrint(funcrefExpr2); - - BinaryenExpressionRef tablesize = BinaryenTableSize(module, "0"); - BinaryenExpressionPrint(tablesize); - - const char* table = BinaryenTableSizeGetTable(tablesize); - BinaryenTableSizeSetTable(tablesize, table); - - BinaryenExpressionRef valueExpr = - BinaryenRefNull(module, BinaryenTypeFuncref()); - BinaryenExpressionRef sizeExpr = makeInt32(module, 0); - BinaryenExpressionRef growExpr = - BinaryenTableGrow(module, "0", valueExpr, sizeExpr); - BinaryenExpressionPrint(growExpr); + const char* funcNames[] = { BinaryenFunctionGetName(sinker) }; + BinaryenSetFunctionTable(module, 1, 1, funcNames, 1, BinaryenConst(module, BinaryenLiteralInt32(0))); // Memory. One per module - const char* segments[] = {"hello, world", "I am passive"}; - bool segmentPassive[] = {false, true}; - BinaryenExpressionRef segmentOffsets[] = { - BinaryenConst(module, BinaryenLiteralInt32(10)), NULL}; - BinaryenIndex segmentSizes[] = {12, 12}; - BinaryenSetMemory(module, - 1, - 256, - "mem", - segments, - segmentPassive, - segmentOffsets, - segmentSizes, - 2, - 1); + const char* segments[] = { "hello, world", "I am passive" }; + int8_t segmentPassive[] = { 0, 1 }; + BinaryenExpressionRef segmentOffsets[] = { BinaryenConst(module, BinaryenLiteralInt32(10)), NULL }; + BinaryenIndex segmentSizes[] = { 12, 12 }; + BinaryenSetMemory(module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 1); // Start function. One per module @@ -1076,12 +852,12 @@ BinaryenModuleSetFeatures(module, features); assert(BinaryenModuleGetFeatures(module) == features); - // Print it out - BinaryenModulePrint(module); - // Verify it validates assert(BinaryenModuleValidate(module)); + // Print it out + BinaryenModulePrint(module); + // Clean up the module, which owns all the objects we created above BinaryenModuleDispose(module); } @@ -1089,7 +865,6 @@ void test_unreachable() { BinaryenModuleRef module = BinaryenModuleCreate(); BinaryenExpressionRef body = BinaryenCallIndirect(module, - "invalid-table", BinaryenUnreachable(module), NULL, 0, @@ -1109,13 +884,13 @@ } BinaryenExpressionRef makeCallCheck(BinaryenModuleRef module, int x) { - BinaryenExpressionRef callOperands[] = {makeInt32(module, x)}; + BinaryenExpressionRef callOperands[] = { makeInt32(module, x) }; return BinaryenCall(module, "check", callOperands, 1, BinaryenTypeNone()); } void test_relooper() { BinaryenModuleRef module = BinaryenModuleCreate(); - BinaryenType localTypes[] = {BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32() }; BinaryenAddFunctionImport(module, "check", @@ -1126,8 +901,7 @@ { // trivial: just one block RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block = - RelooperAddBlock(relooper, makeCallCheck(module, 1337)); + RelooperBlockRef block = RelooperAddBlock(relooper, makeCallCheck(module, 1337)); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block, 0); BinaryenFunctionRef sinker = BinaryenAddFunction(module, "just-one-block", @@ -1139,12 +913,9 @@ } { // two blocks RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperAddBranch( - block0, block1, NULL, NULL); // no condition, no code on branch + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperAddBranch(block0, block1, NULL, NULL); // no condition, no code on branch BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0); BinaryenFunctionRef sinker = BinaryenAddFunction(module, "two-blocks", @@ -1156,12 +927,9 @@ } { // two blocks with code between them RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperAddBranch( - block0, block1, NULL, makeDroppedInt32(module, 77)); // code on branch + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperAddBranch(block0, block1, NULL, makeDroppedInt32(module, 77)); // code on branch BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0); BinaryenFunctionRef sinker = BinaryenAddFunction(module, "two-blocks-plus-code", @@ -1173,10 +941,8 @@ } { // two blocks in a loop RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); RelooperAddBranch(block0, block1, NULL, NULL); RelooperAddBranch(block1, block0, NULL, NULL); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0); @@ -1190,10 +956,8 @@ } { // two blocks in a loop with codes RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); RelooperAddBranch(block0, block1, NULL, makeDroppedInt32(module, 33)); RelooperAddBranch(block1, block0, NULL, makeDroppedInt32(module, -66)); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0); @@ -1207,12 +971,9 @@ } { // split RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); RelooperAddBranch(block0, block1, makeInt32(module, 55), NULL); RelooperAddBranch(block0, block2, NULL, NULL); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0); @@ -1226,12 +987,9 @@ } { // split + code RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); BinaryenExpressionRef temp = makeDroppedInt32(module, 10); RelooperAddBranch(block0, block1, makeInt32(module, 55), temp); RelooperAddBranch(block0, block2, NULL, makeDroppedInt32(module, 20)); @@ -1246,12 +1004,9 @@ } { // if RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); RelooperAddBranch(block0, block1, makeInt32(module, 55), NULL); RelooperAddBranch(block0, block2, NULL, NULL); RelooperAddBranch(block1, block2, NULL, NULL); @@ -1266,12 +1021,9 @@ } { // if + code RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); BinaryenExpressionRef temp = makeDroppedInt32(module, -1); RelooperAddBranch(block0, block1, makeInt32(module, 55), temp); RelooperAddBranch(block0, block2, NULL, makeDroppedInt32(module, -2)); @@ -1287,14 +1039,10 @@ } { // if-else RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); - RelooperBlockRef block3 = - RelooperAddBlock(relooper, makeCallCheck(module, 3)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block3 = RelooperAddBlock(relooper, makeCallCheck(module, 3)); RelooperAddBranch(block0, block1, makeInt32(module, 55), NULL); RelooperAddBranch(block0, block2, NULL, NULL); RelooperAddBranch(block1, block3, NULL, NULL); @@ -1310,12 +1058,9 @@ } { // loop+tail RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); RelooperAddBranch(block0, block1, NULL, NULL); RelooperAddBranch(block1, block0, makeInt32(module, 10), NULL); RelooperAddBranch(block1, block2, NULL, NULL); @@ -1330,20 +1075,13 @@ } { // nontrivial loop + phi to head RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); - RelooperBlockRef block3 = - RelooperAddBlock(relooper, makeCallCheck(module, 3)); - RelooperBlockRef block4 = - RelooperAddBlock(relooper, makeCallCheck(module, 4)); - RelooperBlockRef block5 = - RelooperAddBlock(relooper, makeCallCheck(module, 5)); - RelooperBlockRef block6 = - RelooperAddBlock(relooper, makeCallCheck(module, 6)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block3 = RelooperAddBlock(relooper, makeCallCheck(module, 3)); + RelooperBlockRef block4 = RelooperAddBlock(relooper, makeCallCheck(module, 4)); + RelooperBlockRef block5 = RelooperAddBlock(relooper, makeCallCheck(module, 5)); + RelooperBlockRef block6 = RelooperAddBlock(relooper, makeCallCheck(module, 6)); RelooperAddBranch(block0, block1, NULL, makeDroppedInt32(module, 10)); RelooperAddBranch(block1, block2, makeInt32(module, -2), NULL); RelooperAddBranch(block1, block6, NULL, makeDroppedInt32(module, 20)); @@ -1366,24 +1104,17 @@ { // switch RelooperRef relooper = RelooperCreate(module); BinaryenExpressionRef temp = makeInt32(module, -99); - RelooperBlockRef block0 = - RelooperAddBlockWithSwitch(relooper, makeCallCheck(module, 0), temp); - // TODO: this example is not very good, the blocks should end in a |return| - // as otherwise they - // fall through to each other. A relooper block should end in - // something that stops control flow, if it doesn't have branches - // going out - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); - RelooperBlockRef block3 = - RelooperAddBlock(relooper, makeCallCheck(module, 3)); - BinaryenIndex to_block1[] = {2, 5}; + RelooperBlockRef block0 = RelooperAddBlockWithSwitch(relooper, makeCallCheck(module, 0), temp); + // TODO: this example is not very good, the blocks should end in a |return| as otherwise they + // fall through to each other. A relooper block should end in something that stops control + // flow, if it doesn't have branches going out + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block3 = RelooperAddBlock(relooper, makeCallCheck(module, 3)); + BinaryenIndex to_block1[] = { 2, 5 }; RelooperAddBranchForSwitch(block0, block1, to_block1, 2, NULL); - BinaryenIndex to_block2[] = {4}; - RelooperAddBranchForSwitch( - block0, block2, to_block2, 1, makeDroppedInt32(module, 55)); + BinaryenIndex to_block2[] = { 4 }; + RelooperAddBranchForSwitch(block0, block2, to_block2, 1, makeDroppedInt32(module, 55)); RelooperAddBranchForSwitch(block0, block3, NULL, 0, NULL); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 0); BinaryenFunctionRef sinker = BinaryenAddFunction(module, @@ -1396,25 +1127,15 @@ } { // duff's device RelooperRef relooper = RelooperCreate(module); - RelooperBlockRef block0 = - RelooperAddBlock(relooper, makeCallCheck(module, 0)); - RelooperBlockRef block1 = - RelooperAddBlock(relooper, makeCallCheck(module, 1)); - RelooperBlockRef block2 = - RelooperAddBlock(relooper, makeCallCheck(module, 2)); + RelooperBlockRef block0 = RelooperAddBlock(relooper, makeCallCheck(module, 0)); + RelooperBlockRef block1 = RelooperAddBlock(relooper, makeCallCheck(module, 1)); + RelooperBlockRef block2 = RelooperAddBlock(relooper, makeCallCheck(module, 2)); RelooperAddBranch(block0, block1, makeInt32(module, 10), NULL); RelooperAddBranch(block0, block2, NULL, NULL); RelooperAddBranch(block1, block2, NULL, NULL); RelooperAddBranch(block2, block1, NULL, NULL); - BinaryenExpressionRef body = - RelooperRenderAndDispose(relooper, block0, 3); // use $3 as the helper var - BinaryenType localTypes[] = {BinaryenTypeInt32(), - BinaryenTypeInt32(), - BinaryenTypeInt64(), - BinaryenTypeInt32(), - BinaryenTypeFloat32(), - BinaryenTypeFloat64(), - BinaryenTypeInt32()}; + BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block0, 3); // use $3 as the helper var + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32(), BinaryenTypeInt64(), BinaryenTypeInt32(), BinaryenTypeFloat32(), BinaryenTypeFloat64(), BinaryenTypeInt32() }; BinaryenFunctionRef sinker = BinaryenAddFunction(module, "duffs-device", @@ -1427,11 +1148,8 @@ { // return in a block RelooperRef relooper = RelooperCreate(module); - BinaryenExpressionRef listList[] = { - makeCallCheck(module, 42), - BinaryenReturn(module, makeInt32(module, 1337))}; - BinaryenExpressionRef list = - BinaryenBlock(module, "the-list", listList, 2, -1); + BinaryenExpressionRef listList[] = { makeCallCheck(module, 42), BinaryenReturn(module, makeInt32(module, 1337)) }; + BinaryenExpressionRef list = BinaryenBlock(module, "the-list", listList, 2, -1); RelooperBlockRef block = RelooperAddBlock(relooper, list); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, block, 0); BinaryenFunctionRef sinker = BinaryenAddFunction(module, @@ -1468,11 +1186,10 @@ BinaryenType ii = BinaryenTypeCreate(ii_, 2); BinaryenExpressionRef x = BinaryenLocalGet(module, 0, BinaryenTypeInt32()), y = BinaryenLocalGet(module, 1, BinaryenTypeInt32()); - BinaryenExpressionRef add = - BinaryenBinary(module, BinaryenAddInt32(), x, y); + BinaryenExpressionRef add = BinaryenBinary(module, BinaryenAddInt32(), x, y); BinaryenFunctionRef adder = BinaryenAddFunction( module, "adder", ii, BinaryenTypeInt32(), NULL, 0, add); - BinaryenSetDebugInfo(1); // include names section + BinaryenSetDebugInfo(1); // include names section size = BinaryenModuleWrite(module, buffer, 1024); // write out the module BinaryenSetDebugInfo(0); BinaryenModuleDispose(module); @@ -1493,21 +1210,22 @@ BinaryenModuleWriteText(module, buffer, 1024); printf("module s-expr printed (in memory):\n%s\n", buffer); + // writ the s-expr representation to a pointer which is managed by the // caller - char* text = BinaryenModuleAllocateAndWriteText(module); + char *text = BinaryenModuleAllocateAndWriteText(module); printf("module s-expr printed (in memory, caller-owned):\n%s\n", text); free(text); + BinaryenModuleDispose(module); } void test_interpret() { - // create a simple module with a start method that prints a number, and - // interpret it, printing that number. + // create a simple module with a start method that prints a number, and interpret it, printing that number. BinaryenModuleRef module = BinaryenModuleCreate(); - BinaryenType iparams[2] = {BinaryenTypeInt32()}; + BinaryenType iparams[2] = { BinaryenTypeInt32() }; BinaryenAddFunctionImport(module, "print-i32", "spectest", @@ -1515,9 +1233,8 @@ BinaryenTypeInt32(), BinaryenTypeNone()); - BinaryenExpressionRef callOperands[] = {makeInt32(module, 1234)}; - BinaryenExpressionRef call = - BinaryenCall(module, "print-i32", callOperands, 1, BinaryenTypeNone()); + BinaryenExpressionRef callOperands[] = { makeInt32(module, 1234) }; + BinaryenExpressionRef call = BinaryenCall(module, "print-i32", callOperands, 1, BinaryenTypeNone()); BinaryenFunctionRef starter = BinaryenAddFunction( module, "starter", BinaryenTypeNone(), BinaryenTypeNone(), NULL, 0, call); BinaryenSetStart(module, starter); @@ -1533,7 +1250,7 @@ { BinaryenModuleRef module = BinaryenModuleCreate(); - BinaryenType localTypes[] = {BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32() }; BinaryenFunctionRef func = BinaryenAddFunction( module, "func", @@ -1552,18 +1269,18 @@ } void test_color_status() { - int i; + int i; - // save old state - const int old_state = BinaryenAreColorsEnabled(); + // save old state + const int old_state = BinaryenAreColorsEnabled(); - // Check that we can set the state to both {0, 1} - for (i = 0; i <= 1; i++) { - BinaryenSetColorsEnabled(i); - assert(BinaryenAreColorsEnabled() == i); - } + // Check that we can set the state to both {0, 1} + for(i = 0; i <= 1; i++){ + BinaryenSetColorsEnabled(i); + assert(BinaryenAreColorsEnabled() == i); + } - BinaryenSetColorsEnabled(old_state); + BinaryenSetColorsEnabled(old_state); } void test_for_each() { @@ -1593,7 +1310,7 @@ 0, BinaryenNop(module)); { - for (i = 0; i < BinaryenGetNumFunctions(module); i++) { + for (i = 0; i < BinaryenGetNumFunctions(module) ; i++) { assert(BinaryenGetFunctionByIndex(module, i) == fns[i]); } @@ -1602,58 +1319,45 @@ exps[1] = BinaryenAddFunctionExport(module, "fn1", "export1"); exps[2] = BinaryenAddFunctionExport(module, "fn2", "export2"); - for (i = 0; i < BinaryenGetNumExports(module); i++) { + for (i = 0; i < BinaryenGetNumExports(module) ; i++) { assert(BinaryenGetExportByIndex(module, i) == exps[i]); } - const char* segments[] = {"hello, world", "segment data 2"}; - const uint32_t expected_offsets[] = {10, 125}; - bool segmentPassive[] = {false, false}; - BinaryenIndex segmentSizes[] = {12, 14}; + const char* segments[] = { "hello, world", "segment data 2" }; + const uint32_t expected_offsets[] = { 10, 125 }; + int8_t segmentPassive[] = { 0, 0 }; + BinaryenIndex segmentSizes[] = { 12, 14 }; BinaryenExpressionRef segmentOffsets[] = { BinaryenConst(module, BinaryenLiteralInt32(expected_offsets[0])), - BinaryenGlobalGet(module, "a-global", BinaryenTypeInt32())}; - BinaryenSetMemory(module, - 1, - 256, - "mem", - segments, - segmentPassive, - segmentOffsets, - segmentSizes, - 2, - 0); - BinaryenAddGlobal(module, - "a-global", - BinaryenTypeInt32(), - 0, - makeInt32(module, expected_offsets[1])); + BinaryenGlobalGet(module, "a-global", BinaryenTypeInt32()) + }; + BinaryenSetMemory(module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 0); + BinaryenAddGlobal(module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, expected_offsets[1])); - for (i = 0; i < BinaryenGetNumMemorySegments(module); i++) { + for (i = 0; i < BinaryenGetNumMemorySegments(module) ; i++) { char out[15] = {}; - assert(BinaryenGetMemorySegmentByteOffset(module, i) == - expected_offsets[i]); + assert(BinaryenGetMemorySegmentByteOffset(module, i) == expected_offsets[i]); assert(BinaryenGetMemorySegmentByteLength(module, i) == segmentSizes[i]); BinaryenCopyMemorySegmentData(module, i, out); assert(0 == strcmp(segments[i], out)); } } { - const char* funcNames[] = {BinaryenFunctionGetName(fns[0]), - BinaryenFunctionGetName(fns[1]), - BinaryenFunctionGetName(fns[2])}; - BinaryenExpressionRef constExprRef = - BinaryenConst(module, BinaryenLiteralInt32(0)); - BinaryenAddTable(module, "0", 1, 1, BinaryenTypeFuncref()); - BinaryenAddActiveElementSegment( - module, "0", "0", funcNames, 3, constExprRef); - assert(1 == BinaryenGetNumElementSegments(module)); - BinaryenElementSegmentRef segment = - BinaryenGetElementSegmentByIndex(module, 0); - assert(constExprRef == BinaryenElementSegmentGetOffset(segment)); - for (i = 0; i != BinaryenElementSegmentGetLength(segment); ++i) { - const char* str = BinaryenElementSegmentGetData(segment, i); + const char* funcNames[] = { + BinaryenFunctionGetName(fns[0]), + BinaryenFunctionGetName(fns[1]), + BinaryenFunctionGetName(fns[2]) + }; + BinaryenExpressionRef constExprRef = BinaryenConst(module, BinaryenLiteralInt32(0)); + BinaryenSetFunctionTable(module, 1, 1, funcNames, 3, constExprRef); + assert(0 == BinaryenIsFunctionTableImported(module)); + assert(1 == BinaryenGetNumFunctionTableSegments(module)); + assert(constExprRef == BinaryenGetFunctionTableSegmentOffset(module, 0)); + assert(3 == BinaryenGetFunctionTableSegmentLength(module, 0)); + for (i = 0; i != BinaryenGetFunctionTableSegmentLength(module, 0); ++i) + { + const char * str = BinaryenGetFunctionTableSegmentData(module, 0, i); assert(0 == strcmp(funcNames[i], str)); } } diff -Nru binaryen-108/test/example/c-api-kitchen-sink.txt binaryen-99/test/example/c-api-kitchen-sink.txt --- binaryen-108/test/example/c-api-kitchen-sink.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/c-api-kitchen-sink.txt 2021-01-07 20:01:06.000000000 +0000 @@ -7,10 +7,10 @@ // BinaryenTypeVec128: 6 // BinaryenTypeFuncref: 7 // BinaryenTypeExternref: 8 - // BinaryenTypeAnyref: 8 - // BinaryenTypeEqref: 9 - // BinaryenTypeI31ref: 10 - // BinaryenTypeDataref: 11 + // BinaryenTypeExnref: 9 + // BinaryenTypeAnyref: 10 + // BinaryenTypeEqref: 11 + // BinaryenTypeI31ref: 12 // BinaryenTypeAuto: -1 BinaryenFeatureMVP: 0 BinaryenFeatureAtomics: 1 @@ -25,47 +25,30 @@ BinaryenFeatureMultivalue: 512 BinaryenFeatureGC: 1024 BinaryenFeatureMemory64: 2048 -BinaryenFeatureTypedFunctionReferences: 4096 -BinaryenFeatureRelaxedSIMD: 16384 -BinaryenFeatureExtendedConst: 32768 -BinaryenFeatureAll: 57343 +BinaryenFeatureAll: 8191 (f32.neg (f32.const -33.61199951171875) ) -(table.set $0 - (i32.const 0) - (ref.func "$kitchen()sinker") -) -(table.get $0 - (i32.const 0) -) -(table.size $0) -(table.grow $0 - (ref.null func) - (i32.const 0) -) (module (type $i32_i64_f32_f64_=>_i32 (func (param i32 i64 f32 f64) (result i32))) + (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_f64_=>_f32 (func (param i32 f64) (result f32))) - (type $none_=>_none (func)) (import "module" "base" (func $an-imported (param i32 f64) (result f32))) - (global $a-global i32 (i32.const 7)) - (global $a-mutable-global (mut f32) (f32.const 7.5)) (memory $0 (shared 1 256)) (data (i32.const 10) "hello, world") - (data "I am passive") - (table $tab 0 100 funcref) + (data passive "I am passive") (table $0 1 1 funcref) - (elem $0 (table $0) (i32.const 0) func "$kitchen()sinker") - (elem $passive func "$kitchen()sinker") - (tag $a-tag (param i32)) + (elem (i32.const 0) "$kitchen()sinker") + (global $a-global i32 (i32.const 7)) + (global $a-mutable-global (mut f32) (f32.const 7.5)) + (event $a-event (attr 0) (param i32)) (export "kitchen_sinker" (func "$kitchen()sinker")) (export "mem" (memory $0)) (start $starter) (func "$kitchen()sinker" (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32) (local $4 i32) - (local $5 anyref) + (local $5 exnref) (block $the-body (result i32) (block $the-nothing (drop @@ -326,22 +309,17 @@ ) ) (drop - (v128.any_true + (i8x16.abs (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.popcnt + (i8x16.neg (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.abs - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i8x16.neg + (i8x16.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -366,6 +344,11 @@ ) ) (drop + (i16x8.any_true + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + ) + ) + (drop (i16x8.all_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -386,17 +369,17 @@ ) ) (drop - (i32x4.all_true + (i32x4.any_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.bitmask + (i32x4.all_true (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.abs + (i32x4.bitmask (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -406,16 +389,6 @@ ) ) (drop - (i64x2.all_true - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.bitmask - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.abs (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -456,102 +429,72 @@ ) ) (drop - (f32x4.convert_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (f32x4.convert_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_low_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_high_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extend_low_i8x16_u + (i64x2.trunc_sat_f64x2_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.extend_high_i8x16_u + (i64x2.trunc_sat_f64x2_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_low_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extend_high_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extend_low_i16x8_u + (f32x4.convert_i32x4_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.extend_high_i16x8_u + (f32x4.convert_i32x4_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_low_i32x4_s + (f64x2.convert_i64x2_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_high_i32x4_s + (f64x2.convert_i64x2_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_low_i32x4_u + (i16x8.widen_low_i8x16_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i64x2.extend_high_i32x4_u + (i16x8.widen_high_i8x16_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f64x2.convert_low_i32x4_s + (i16x8.widen_low_i8x16_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f64x2.convert_low_i32x4_u + (i16x8.widen_high_i8x16_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.trunc_sat_f64x2_s_zero + (i32x4.widen_low_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i32x4.trunc_sat_f64x2_u_zero + (i32x4.widen_high_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f32x4.demote_f64x2_zero + (i32x4.widen_low_i16x8_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (f64x2.promote_low_f32x4 + (i32x4.widen_high_i16x8_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) @@ -928,42 +871,6 @@ ) ) (drop - (i64x2.eq - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.ne - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.lt_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.gt_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.le_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.ge_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.eq (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1066,13 +973,13 @@ ) ) (drop - (i8x16.add_sat_s + (i8x16.add_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.add_sat_u + (i8x16.add_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1084,13 +991,19 @@ ) ) (drop - (i8x16.sub_sat_s + (i8x16.sub_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i8x16.sub_sat_u + (i8x16.sub_saturate_u + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + ) + ) + (drop + (i8x16.mul (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1132,13 +1045,13 @@ ) ) (drop - (i16x8.add_sat_s + (i16x8.add_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.add_sat_u + (i16x8.add_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1150,13 +1063,13 @@ ) ) (drop - (i16x8.sub_sat_s + (i16x8.sub_saturate_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (i16x8.sub_sat_u + (i16x8.sub_saturate_u (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1198,36 +1111,6 @@ ) ) (drop - (i16x8.q15mulr_sat_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_low_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_high_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_low_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extmul_high_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i32x4.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1264,30 +1147,6 @@ ) ) (drop - (i64x2.extmul_low_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_high_i32x4_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_low_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i64x2.extmul_high_i32x4_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.add (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1336,30 +1195,6 @@ ) ) (drop - (i32x4.extmul_low_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_high_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_low_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extmul_high_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (f32x4.div (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1478,26 +1313,6 @@ ) ) (drop - (i16x8.extadd_pairwise_i8x16_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i16x8.extadd_pairwise_i8x16_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extadd_pairwise_i16x8_s - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop - (i32x4.extadd_pairwise_i16x8_u - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - ) - (drop (i8x16.narrow_i16x8_s (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1522,7 +1337,7 @@ ) ) (drop - (i8x16.swizzle + (v8x16.swizzle (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) @@ -1676,113 +1491,91 @@ ) ) (drop - (v128.load8_splat - (i32.const 128) - ) - ) - (drop - (v128.load16_splat offset=16 align=1 + (v8x16.load_splat (i32.const 128) ) ) (drop - (v128.load32_splat offset=16 + (v16x8.load_splat offset=16 align=1 (i32.const 128) ) ) (drop - (v128.load64_splat align=4 + (v32x4.load_splat offset=16 (i32.const 128) ) ) (drop - (v128.load8x8_s + (v64x2.load_splat align=4 (i32.const 128) ) ) (drop - (v128.load8x8_u + (i16x8.load8x8_s (i32.const 128) ) ) (drop - (v128.load16x4_s + (i16x8.load8x8_u (i32.const 128) ) ) (drop - (v128.load16x4_u + (i32x4.load16x4_s (i32.const 128) ) ) (drop - (v128.load32x2_s + (i32x4.load16x4_u (i32.const 128) ) ) (drop - (v128.load32x2_u + (i64x2.load32x2_s (i32.const 128) ) ) (drop - (v128.load32_zero + (i64x2.load32x2_u (i32.const 128) ) ) (drop - (v128.load64_zero - (i32.const 128) - ) - ) - (drop - (v128.load8_lane 0 - (i32.const 128) + (v8x16.shuffle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load16_lane 0 - (i32.const 128) + (v128.bitselect + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load32_lane 0 - (i32.const 128) + (f32x4.qfma + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.load64_lane 0 - (i32.const 128) + (f32x4.qfms + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) - (v128.store8_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store16_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store32_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) - (v128.store64_lane 0 - (i32.const 128) - (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) - ) (drop - (i8x16.shuffle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + (f64x2.qfma + (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) ) (drop - (v128.bitselect + (f64x2.qfms (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) @@ -1873,7 +1666,7 @@ ) (drop (i32.eqz - (call_indirect $tab (type $i32_i64_f32_f64_=>_i32) + (call_indirect (type $i32_i64_f32_f64_=>_i32) (i32.const 13) (i64.const 37) (f32.const 1.2999999523162842) @@ -1937,7 +1730,7 @@ (f32.const 1.2999999523162842) (f64.const 3.7) ) - (return_call_indirect $tab (type $i32_i64_f32_f64_=>_i32) + (return_call_indirect (type $i32_i64_f32_f64_=>_i32) (i32.const 13) (i64.const 37) (f32.const 1.2999999523162842) @@ -1946,7 +1739,7 @@ ) (drop (ref.is_null - (ref.null any) + (ref.null extern) ) ) (drop @@ -1955,6 +1748,11 @@ ) ) (drop + (ref.is_null + (ref.null exn) + ) + ) + (drop (select (result funcref) (ref.null func) (ref.func "$kitchen()sinker") @@ -1967,70 +1765,26 @@ (ref.null eq) ) ) - (drop - (ref.is_func - (ref.null any) - ) - ) - (drop - (ref.is_data - (ref.null any) - ) - ) - (drop - (ref.is_i31 - (ref.null any) - ) - ) - (drop - (ref.as_non_null - (ref.null any) - ) - ) - (drop - (ref.as_func - (ref.null any) - ) - ) - (drop - (ref.as_data - (ref.null any) - ) - ) - (drop - (ref.as_i31 - (ref.null any) - ) - ) (try (do - (throw $a-tag + (throw $a-event (i32.const 0) ) ) - (catch $a-tag - (drop - (pop i32) + (catch + (local.set $5 + (pop exnref) ) - ) - (catch_all - (nop) - ) - ) - (try $try_outer - (do - (try - (do - (throw $a-tag - (i32.const 0) + (drop + (block $try-block (result i32) + (rethrow + (br_on_exn $try-block $a-event + (local.get $5) + ) ) ) - (delegate $try_outer) ) ) - (catch_all - (nop) - ) ) (i32.atomic.store (i32.const 0) @@ -2086,7 +1840,10 @@ (pop funcref) ) (drop - (pop anyref) + (pop externref) + ) + (drop + (pop exnref) ) (drop (pop i32 i64 f32 f64) @@ -2640,8 +2397,8 @@ ) (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (import "spectest" "print" (func $print-i32 (param i32))) (start $starter) (func $starter @@ -2663,12 +2420,12 @@ validation: 0 (module (type $none_=>_none (func)) - (global $a-global i32 (i32.const 125)) (memory $0 1 256) (data (i32.const 10) "hello, world") (data (global.get $a-global) "segment data 2") (table $0 1 1 funcref) - (elem $0 (i32.const 0) $fn0 $fn1 $fn2) + (elem (i32.const 0) $fn0 $fn1 $fn2) + (global $a-global i32 (i32.const 125)) (export "export0" (func $fn0)) (export "export1" (func $fn1)) (export "export2" (func $fn2)) diff -Nru binaryen-108/test/example/c-api-multiple-tables.c binaryen-99/test/example/c-api-multiple-tables.c --- binaryen-108/test/example/c-api-multiple-tables.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/c-api-multiple-tables.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,111 +0,0 @@ -#include -#include -#include - -// "hello world" type example: create a function that adds two i32s and returns -// the result - -int main() { - BinaryenModuleRef module = BinaryenModuleCreate(); - BinaryenModuleSetFeatures(module, BinaryenFeatureReferenceTypes()); - - // Create a function type for i32 (i32, i32) - BinaryenType ii[2] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; - BinaryenType params = BinaryenTypeCreate(ii, 2); - BinaryenType results = BinaryenTypeInt32(); - - assert(BinaryenGetNumTables(module) == 0); - - { - // Get the 0 and 1 arguments, and add them - BinaryenExpressionRef x = BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - y = BinaryenLocalGet(module, 1, BinaryenTypeInt32()); - BinaryenExpressionRef add = - BinaryenBinary(module, BinaryenAddInt32(), x, y); - - // Create the add function - // Note: no additional local variables - // Note: no basic blocks here, we are an AST. The function body is just an - // expression node. - BinaryenFunctionRef adder = - BinaryenAddFunction(module, "adder", params, results, NULL, 0, add); - - const char* funcNames[] = {"adder"}; - BinaryenAddTable(module, "tab", 1, 1, BinaryenTypeFuncref()); - assert(BinaryenGetTable(module, "tab") != NULL); - BinaryenAddActiveElementSegment( - module, - "tab", - "0", - funcNames, - 1, - BinaryenConst(module, BinaryenLiteralInt32(0))); - - BinaryenAddTable(module, "t2", 1, 1, BinaryenTypeFuncref()); - BinaryenAddActiveElementSegment( - module, - "t2", - "1", - funcNames, - 1, - BinaryenConst(module, BinaryenLiteralInt32(0))); - BinaryenAddPassiveElementSegment(module, "passive", funcNames, 1); - assert(NULL != BinaryenGetElementSegmentByIndex(module, 2)); - assert(1 == BinaryenElementSegmentIsPassive( - BinaryenGetElementSegment(module, "passive"))); - BinaryenTableRef t2 = BinaryenGetTableByIndex(module, 1); - assert(t2 != NULL); - BinaryenElementSegmentRef elem1 = BinaryenGetElementSegment(module, "1"); - assert(elem1 != NULL); - assert(strcmp(BinaryenElementSegmentGetName(elem1), "1") == 0); - assert(strcmp(BinaryenElementSegmentGetTable(elem1), "t2") == 0); - assert(BinaryenElementSegmentGetLength(elem1) == 1); - assert(strcmp(BinaryenElementSegmentGetData(elem1, 0), funcNames[0]) == 0); - - assert(strcmp(BinaryenTableGetName(t2), "t2") == 0); - BinaryenTableSetName(t2, "table2"); - BinaryenModuleUpdateMaps(module); - assert(strcmp(BinaryenTableGetName(t2), "table2") == 0); - BinaryenElementSegmentSetTable(elem1, "table2"); - assert(strcmp(BinaryenElementSegmentGetTable(elem1), "table2") == 0); - assert(BinaryenTableGetInitial(t2) == 1); - BinaryenTableSetInitial(t2, 2); - assert(BinaryenTableGetInitial(t2) == 2); - assert(BinaryenTableHasMax(t2) == 1); - assert(BinaryenTableGetMax(t2) == 1); - BinaryenTableSetMax(t2, 2); - assert(BinaryenTableGetMax(t2) == 2); - assert(strcmp(BinaryenTableImportGetModule(t2), "") == 0); - assert(strcmp(BinaryenTableImportGetBase(t2), "") == 0); - - assert(BinaryenGetNumTables(module) == 2); - } - - { - // Get the 0 and 1 arguments, and add them - BinaryenExpressionRef operands[] = { - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenLocalGet(module, 1, BinaryenTypeInt32())}; - - BinaryenExpressionRef add_indirect = - BinaryenCallIndirect(module, - "tab", - BinaryenConst(module, BinaryenLiteralInt32(0)), - operands, - 2, - params, - results); - BinaryenCallIndirectSetTable(add_indirect, "t2"); - - BinaryenFunctionRef call_adder_indirectly = BinaryenAddFunction( - module, "call_adder_indirect", params, results, NULL, 0, add_indirect); - } - - // Print it out - BinaryenModulePrint(module); - - // Clean up the module, which owns all the objects we created above - BinaryenModuleDispose(module); - - return 0; -} diff -Nru binaryen-108/test/example/c-api-multiple-tables.txt binaryen-99/test/example/c-api-multiple-tables.txt --- binaryen-108/test/example/c-api-multiple-tables.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/c-api-multiple-tables.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -(module - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (table $tab 1 1 funcref) - (table $table2 2 2 funcref) - (elem $0 (table $tab) (i32.const 0) func $adder) - (elem $1 (table $table2) (i32.const 0) func $adder) - (elem $passive func $adder) - (func $adder (param $0 i32) (param $1 i32) (result i32) - (i32.add - (local.get $0) - (local.get $1) - ) - ) - (func $call_adder_indirect (param $0 i32) (param $1 i32) (result i32) - (call_indirect $t2 (type $i32_i32_=>_i32) - (local.get $0) - (local.get $1) - (i32.const 0) - ) - ) -) diff -Nru binaryen-108/test/example/c-api-relooper-unreachable-if.cpp binaryen-99/test/example/c-api-relooper-unreachable-if.cpp --- binaryen-108/test/example/c-api-relooper-unreachable-if.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/c-api-relooper-unreachable-if.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ // beginning a Binaryen API trace -#include "binaryen-c.h" #include -#include #include +#include +#include "binaryen-c.h" int main() { std::map expressions; @@ -15,20 +15,11 @@ expressions[size_t(NULL)] = BinaryenExpressionRef(NULL); BinaryenModuleAutoDrop(the_module); { - const char* segments[] = {0}; - bool segmentPassive[] = {false}; - BinaryenExpressionRef segmentOffsets[] = {0}; - BinaryenIndex segmentSizes[] = {0}; - BinaryenSetMemory(the_module, - 256, - 256, - "memory", - segments, - segmentPassive, - segmentOffsets, - segmentSizes, - 0, - 0); + const char* segments[] = { 0 }; + int8_t segmentPassive[] = { 0 }; + BinaryenExpressionRef segmentOffsets[] = { 0 }; + BinaryenIndex segmentSizes[] = { 0 }; + BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } the_relooper = RelooperCreate(the_module); expressions[1] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); @@ -37,18 +28,15 @@ the_module, 4, 0, 0, expressions[2], expressions[1], BinaryenTypeInt32()); expressions[4] = BinaryenReturn(the_module, expressions[0]); { - BinaryenExpressionRef children[] = {expressions[3], expressions[4]}; - expressions[5] = - BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[3], expressions[4] }; + expressions[5] = BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[5]); expressions[6] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[7] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[6]); + expressions[7] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[6]); expressions[8] = BinaryenLocalSet(the_module, 0, expressions[7]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[8]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); expressions[9] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); { BinaryenType varTypes[] = { @@ -61,8 +49,7 @@ 3, expressions[9]); } - BinaryenAddFunctionExport( - the_module, "tinycore::eh_personality", "tinycore::eh_personality"); + BinaryenAddFunctionExport(the_module, "tinycore::eh_personality", "tinycore::eh_personality"); the_relooper = RelooperCreate(the_module); expressions[10] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[11] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -70,20 +57,16 @@ the_module, 4, 0, 0, expressions[11], expressions[10], BinaryenTypeInt32()); expressions[13] = BinaryenReturn(the_module, expressions[0]); { - BinaryenExpressionRef children[] = {expressions[12], expressions[13]}; - expressions[14] = - BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[12], expressions[13] }; + expressions[14] = BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[14]); expressions[15] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[16] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[15]); + expressions[16] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[15]); expressions[17] = BinaryenLocalSet(the_module, 0, expressions[16]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[17]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); - expressions[18] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + expressions[18] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); { BinaryenType varTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32(), BinaryenTypeInt64()}; @@ -95,34 +78,26 @@ 3, expressions[18]); } - BinaryenAddFunctionExport( - the_module, "tinycore::eh_unwind_resume", "tinycore::eh_unwind_resume"); + BinaryenAddFunctionExport(the_module, "tinycore::eh_unwind_resume", "tinycore::eh_unwind_resume"); the_relooper = RelooperCreate(the_module); { - BinaryenExpressionRef children[] = {0}; - expressions[19] = - BinaryenBlock(the_module, "bb0", children, 0, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { 0 }; + expressions[19] = BinaryenBlock(the_module, "bb0", children, 0, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[19]); { - BinaryenExpressionRef children[] = {0}; - expressions[20] = - BinaryenBlock(the_module, "bb1", children, 0, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { 0 }; + expressions[20] = BinaryenBlock(the_module, "bb1", children, 0, BinaryenTypeAuto()); } relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[20]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[1], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[1], expressions[0], expressions[0]); expressions[21] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[22] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[21]); + expressions[22] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[21]); expressions[23] = BinaryenLocalSet(the_module, 0, expressions[22]); relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[23]); - RelooperAddBranch( - relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]); - expressions[24] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 1); + RelooperAddBranch(relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]); + expressions[24] = RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 1); { BinaryenType varTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32(), BinaryenTypeInt64()}; @@ -134,8 +109,7 @@ 3, expressions[24]); } - BinaryenAddFunctionExport( - the_module, "tinycore::panic_fmt", "tinycore::panic_fmt"); + BinaryenAddFunctionExport(the_module, "tinycore::panic_fmt", "tinycore::panic_fmt"); the_relooper = RelooperCreate(the_module); expressions[25] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[26] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -143,20 +117,16 @@ the_module, 4, 0, 0, expressions[26], expressions[25], BinaryenTypeInt32()); expressions[28] = BinaryenReturn(the_module, expressions[0]); { - BinaryenExpressionRef children[] = {expressions[27], expressions[28]}; - expressions[29] = - BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[27], expressions[28] }; + expressions[29] = BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[29]); expressions[30] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[31] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[30]); + expressions[31] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[30]); expressions[32] = BinaryenLocalSet(the_module, 0, expressions[31]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[32]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); - expressions[33] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + expressions[33] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); { BinaryenType varTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32(), BinaryenTypeInt64()}; @@ -168,9 +138,7 @@ 3, expressions[33]); } - BinaryenAddFunctionExport(the_module, - "tinycore::rust_eh_register_frames", - "tinycore::rust_eh_register_frames"); + BinaryenAddFunctionExport(the_module, "tinycore::rust_eh_register_frames", "tinycore::rust_eh_register_frames"); the_relooper = RelooperCreate(the_module); expressions[34] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[35] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -178,20 +146,16 @@ the_module, 4, 0, 0, expressions[35], expressions[34], BinaryenTypeInt32()); expressions[37] = BinaryenReturn(the_module, expressions[0]); { - BinaryenExpressionRef children[] = {expressions[36], expressions[37]}; - expressions[38] = - BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[36], expressions[37] }; + expressions[38] = BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[38]); expressions[39] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[40] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[39]); + expressions[40] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[39]); expressions[41] = BinaryenLocalSet(the_module, 0, expressions[40]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[41]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); - expressions[42] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + expressions[42] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 1); { BinaryenType varTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32(), BinaryenTypeInt64()}; @@ -203,9 +167,7 @@ 3, expressions[42]); } - BinaryenAddFunctionExport(the_module, - "tinycore::rust_eh_unregister_frames", - "tinycore::rust_eh_unregister_frames"); + BinaryenAddFunctionExport(the_module, "tinycore::rust_eh_unregister_frames", "tinycore::rust_eh_unregister_frames"); the_relooper = RelooperCreate(the_module); expressions[43] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[44] = BinaryenLocalSet(the_module, 1, expressions[43]); @@ -219,15 +181,12 @@ BinaryenTypeNone()); expressions[47] = BinaryenLocalGet(the_module, 2, BinaryenTypeInt32()); { - BinaryenExpressionRef operands[] = {expressions[47]}; - expressions[48] = - BinaryenCall(the_module, "print_i32", operands, 1, BinaryenTypeNone()); + BinaryenExpressionRef operands[] = { expressions[47] }; + expressions[48] = BinaryenCall(the_module, "print_i32", operands, 1, BinaryenTypeNone()); } { - BinaryenExpressionRef children[] = { - expressions[44], expressions[46], expressions[48]}; - expressions[49] = - BinaryenBlock(the_module, "bb0", children, 3, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[44], expressions[46], expressions[48] }; + expressions[49] = BinaryenBlock(the_module, "bb0", children, 3, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[49]); expressions[50] = BinaryenLocalGet(the_module, 3, BinaryenTypeInt32()); @@ -236,22 +195,17 @@ the_module, 4, 0, 0, expressions[51], expressions[50], BinaryenTypeInt32()); expressions[53] = BinaryenReturn(the_module, expressions[0]); { - BinaryenExpressionRef children[] = {expressions[52], expressions[53]}; - expressions[54] = - BinaryenBlock(the_module, "bb1", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[52], expressions[53] }; + expressions[54] = BinaryenBlock(the_module, "bb1", children, 2, BinaryenTypeAuto()); } relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[54]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); expressions[55] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[56] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[55]); + expressions[56] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[55]); expressions[57] = BinaryenLocalSet(the_module, 3, expressions[56]); relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[57]); - RelooperAddBranch( - relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]); - expressions[58] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 4); + RelooperAddBranch(relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]); + expressions[58] = RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 4); { BinaryenType varTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32(), @@ -276,22 +230,18 @@ expressions[64] = BinaryenConst(the_module, BinaryenLiteralInt32(2)); expressions[65] = BinaryenUnary(the_module, 22, expressions[63]); expressions[66] = BinaryenUnary(the_module, 22, expressions[64]); - expressions[67] = - BinaryenBinary(the_module, 25, expressions[65], expressions[66]); + expressions[67] = BinaryenBinary(the_module, 25, expressions[65], expressions[66]); expressions[68] = BinaryenLocalSet(the_module, 8, expressions[67]); expressions[69] = BinaryenLocalGet(the_module, 8, BinaryenTypeInt64()); expressions[70] = BinaryenUnary(the_module, 24, expressions[69]); expressions[71] = BinaryenConst(the_module, BinaryenLiteralInt64(32)); expressions[72] = BinaryenLocalGet(the_module, 8, BinaryenTypeInt64()); - expressions[73] = - BinaryenBinary(the_module, 36, expressions[72], expressions[71]); + expressions[73] = BinaryenBinary(the_module, 36, expressions[72], expressions[71]); expressions[74] = BinaryenUnary(the_module, 24, expressions[73]); expressions[75] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[76] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[75]); + expressions[76] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[75]); expressions[77] = BinaryenConst(the_module, BinaryenLiteralInt32(128)); - expressions[78] = - BinaryenBinary(the_module, 1, expressions[76], expressions[77]); + expressions[78] = BinaryenBinary(the_module, 1, expressions[76], expressions[77]); expressions[79] = BinaryenLocalTee(the_module, 3, expressions[78], BinaryenTypeInt32()); expressions[80] = BinaryenStore( @@ -302,19 +252,12 @@ expressions[83] = BinaryenStore( the_module, 4, 4, 0, expressions[81], expressions[74], BinaryenTypeInt32()); { - BinaryenExpressionRef children[] = {expressions[60], - expressions[62], - expressions[68], - expressions[80], - expressions[82], - expressions[83]}; - expressions[84] = - BinaryenBlock(the_module, "bb0", children, 6, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[60], expressions[62], expressions[68], expressions[80], expressions[82], expressions[83] }; + expressions[84] = BinaryenBlock(the_module, "bb0", children, 6, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[84]); expressions[85] = BinaryenLocalGet(the_module, 3, BinaryenTypeInt32()); - expressions[86] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[85]); + expressions[86] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[85]); expressions[87] = BinaryenLocalSet(the_module, 1, expressions[86]); expressions[88] = BinaryenLocalGet(the_module, 1, BinaryenTypeInt32()); expressions[89] = BinaryenLocalSet(the_module, 4, expressions[88]); @@ -327,33 +270,22 @@ expressions[95] = BinaryenLocalGet(the_module, 5, BinaryenTypeInt32()); expressions[96] = BinaryenReturn(the_module, expressions[95]); { - BinaryenExpressionRef children[] = {expressions[87], - expressions[89], - expressions[91], - expressions[94], - expressions[96]}; - expressions[97] = - BinaryenBlock(the_module, "bb1", children, 5, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[87], expressions[89], expressions[91], expressions[94], expressions[96] }; + expressions[97] = BinaryenBlock(the_module, "bb1", children, 5, BinaryenTypeAuto()); } relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[97]); expressions[98] = BinaryenLocalGet(the_module, 3, BinaryenTypeInt32()); - expressions[99] = - BinaryenLoad(the_module, 4, 0, 8, 0, BinaryenTypeInt32(), expressions[98]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[1], expressions[99], expressions[0]); + expressions[99] = BinaryenLoad(the_module, 4, 0, 8, 0, BinaryenTypeInt32(), expressions[98]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[99], expressions[0]); expressions[100] = BinaryenUnreachable(the_module); relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[100]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[2], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[2], expressions[0], expressions[0]); expressions[101] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[102] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[101]); + expressions[102] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[101]); expressions[103] = BinaryenLocalSet(the_module, 6, expressions[102]); relooperBlocks[3] = RelooperAddBlock(the_relooper, expressions[103]); - RelooperAddBranch( - relooperBlocks[3], relooperBlocks[0], expressions[0], expressions[0]); - expressions[104] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[3], 7); + RelooperAddBranch(relooperBlocks[3], relooperBlocks[0], expressions[0], expressions[0]); + expressions[104] = RelooperRenderAndDispose(the_relooper, relooperBlocks[3], 7); { BinaryenType varTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32(), @@ -377,37 +309,31 @@ expressions[105] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[106] = BinaryenLocalSet(the_module, 2, expressions[105]); { - BinaryenExpressionRef operands[] = {0}; - expressions[107] = - BinaryenCall(the_module, "real_main", operands, 0, BinaryenTypeInt32()); + BinaryenExpressionRef operands[] = { 0 }; + expressions[107] = BinaryenCall(the_module, "real_main", operands, 0, BinaryenTypeInt32()); } expressions[108] = BinaryenLocalSet(the_module, 4, expressions[107]); { - BinaryenExpressionRef children[] = {expressions[106], expressions[108]}; - expressions[109] = - BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[106], expressions[108] }; + expressions[109] = BinaryenBlock(the_module, "bb0", children, 2, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[109]); expressions[110] = BinaryenLocalGet(the_module, 4, BinaryenTypeInt32()); expressions[111] = BinaryenConst(the_module, BinaryenLiteralInt32(3)); expressions[112] = BinaryenUnary(the_module, 22, expressions[110]); expressions[113] = BinaryenUnary(the_module, 22, expressions[111]); - expressions[114] = - BinaryenBinary(the_module, 25, expressions[112], expressions[113]); + expressions[114] = BinaryenBinary(the_module, 25, expressions[112], expressions[113]); expressions[115] = BinaryenLocalSet(the_module, 11, expressions[114]); expressions[116] = BinaryenLocalGet(the_module, 11, BinaryenTypeInt64()); expressions[117] = BinaryenUnary(the_module, 24, expressions[116]); expressions[118] = BinaryenConst(the_module, BinaryenLiteralInt64(32)); expressions[119] = BinaryenLocalGet(the_module, 11, BinaryenTypeInt64()); - expressions[120] = - BinaryenBinary(the_module, 36, expressions[119], expressions[118]); + expressions[120] = BinaryenBinary(the_module, 36, expressions[119], expressions[118]); expressions[121] = BinaryenUnary(the_module, 24, expressions[120]); expressions[122] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[123] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[122]); + expressions[123] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[122]); expressions[124] = BinaryenConst(the_module, BinaryenLiteralInt32(128)); - expressions[125] = - BinaryenBinary(the_module, 1, expressions[123], expressions[124]); + expressions[125] = BinaryenBinary(the_module, 1, expressions[123], expressions[124]); expressions[126] = BinaryenLocalTee(the_module, 5, expressions[125], BinaryenTypeInt32()); expressions[127] = BinaryenStore(the_module, @@ -433,29 +359,23 @@ expressions[121], BinaryenTypeInt32()); { - BinaryenExpressionRef children[] = { - expressions[115], expressions[127], expressions[129], expressions[130]}; - expressions[131] = - BinaryenBlock(the_module, "bb1", children, 4, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[115], expressions[127], expressions[129], expressions[130] }; + expressions[131] = BinaryenBlock(the_module, "bb1", children, 4, BinaryenTypeAuto()); } relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[131]); expressions[132] = BinaryenLocalGet(the_module, 5, BinaryenTypeInt32()); - expressions[133] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[132]); + expressions[133] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[132]); expressions[134] = BinaryenLocalSet(the_module, 3, expressions[133]); expressions[135] = BinaryenLocalGet(the_module, 3, BinaryenTypeInt32()); expressions[136] = BinaryenLocalSet(the_module, 6, expressions[135]); expressions[137] = BinaryenLocalGet(the_module, 6, BinaryenTypeInt32()); { - BinaryenExpressionRef operands[] = {expressions[137]}; - expressions[138] = BinaryenCall( - the_module, "wasm::print_i32", operands, 1, BinaryenTypeNone()); + BinaryenExpressionRef operands[] = { expressions[137] }; + expressions[138] = BinaryenCall(the_module, "wasm::print_i32", operands, 1, BinaryenTypeNone()); } { - BinaryenExpressionRef children[] = { - expressions[134], expressions[136], expressions[138]}; - expressions[139] = - BinaryenBlock(the_module, "bb2", children, 3, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[134], expressions[136], expressions[138] }; + expressions[139] = BinaryenBlock(the_module, "bb2", children, 3, BinaryenTypeAuto()); } relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[139]); expressions[140] = BinaryenLocalGet(the_module, 3, BinaryenTypeInt32()); @@ -474,34 +394,24 @@ expressions[147] = BinaryenLocalGet(the_module, 8, BinaryenTypeInt32()); expressions[148] = BinaryenReturn(the_module, expressions[147]); { - BinaryenExpressionRef children[] = { - expressions[141], expressions[143], expressions[146], expressions[148]}; - expressions[149] = - BinaryenBlock(the_module, "bb3", children, 4, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[141], expressions[143], expressions[146], expressions[148] }; + expressions[149] = BinaryenBlock(the_module, "bb3", children, 4, BinaryenTypeAuto()); } relooperBlocks[3] = RelooperAddBlock(the_relooper, expressions[149]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); expressions[150] = BinaryenLocalGet(the_module, 5, BinaryenTypeInt32()); - expressions[151] = - BinaryenLoad(the_module, 4, 0, 8, 0, BinaryenTypeInt32(), expressions[150]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[2], expressions[151], expressions[0]); + expressions[151] = BinaryenLoad(the_module, 4, 0, 8, 0, BinaryenTypeInt32(), expressions[150]); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[2], expressions[151], expressions[0]); expressions[152] = BinaryenUnreachable(the_module); relooperBlocks[4] = RelooperAddBlock(the_relooper, expressions[152]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[4], expressions[0], expressions[0]); - RelooperAddBranch( - relooperBlocks[2], relooperBlocks[3], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[4], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[2], relooperBlocks[3], expressions[0], expressions[0]); expressions[153] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[154] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[153]); + expressions[154] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[153]); expressions[155] = BinaryenLocalSet(the_module, 9, expressions[154]); relooperBlocks[5] = RelooperAddBlock(the_relooper, expressions[155]); - RelooperAddBranch( - relooperBlocks[5], relooperBlocks[0], expressions[0], expressions[0]); - expressions[156] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[5], 10); + RelooperAddBranch(relooperBlocks[5], relooperBlocks[0], expressions[0], expressions[0]); + expressions[156] = RelooperRenderAndDispose(the_relooper, relooperBlocks[5], 10); { BinaryenType varTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32(), @@ -525,20 +435,11 @@ } BinaryenAddFunctionExport(the_module, "main", "main"); { - const char* segments[] = {0}; - BinaryenExpressionRef segmentOffsets[] = {0}; - bool segmentPassive[] = {false}; - BinaryenIndex segmentSizes[] = {0}; - BinaryenSetMemory(the_module, - 1, - 1, - NULL, - segments, - segmentPassive, - segmentOffsets, - segmentSizes, - 0, - 0); + const char* segments[] = { 0 }; + BinaryenExpressionRef segmentOffsets[] = { 0 }; + int8_t segmentPassive[] = { 0 }; + BinaryenIndex segmentSizes[] = { 0 }; + BinaryenSetMemory(the_module, 1, 1, NULL, segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } expressions[157] = BinaryenConst(the_module, BinaryenLiteralInt32(65535)); expressions[158] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -552,15 +453,14 @@ expressions[160] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); expressions[161] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); { - BinaryenExpressionRef operands[] = {expressions[160], expressions[161]}; + BinaryenExpressionRef operands[] = { expressions[160], expressions[161] }; expressions[162] = BinaryenCall(the_module, "main", operands, 2, BinaryenTypeInt32()); } expressions[163] = BinaryenDrop(the_module, expressions[162]); { - BinaryenExpressionRef children[] = {expressions[159], expressions[163]}; - expressions[164] = - BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[159], expressions[163] }; + expressions[164] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeAuto()); } BinaryenAddFunctionExport(the_module, "__wasm_start", "rust_entry"); { @@ -587,22 +487,18 @@ expressions[174] = BinaryenLocalGet(the_module, 5, BinaryenTypeInt32()); expressions[175] = BinaryenUnary(the_module, 22, expressions[173]); expressions[176] = BinaryenUnary(the_module, 22, expressions[174]); - expressions[177] = - BinaryenBinary(the_module, 25, expressions[175], expressions[176]); + expressions[177] = BinaryenBinary(the_module, 25, expressions[175], expressions[176]); expressions[178] = BinaryenLocalSet(the_module, 10, expressions[177]); expressions[179] = BinaryenLocalGet(the_module, 10, BinaryenTypeInt64()); expressions[180] = BinaryenUnary(the_module, 24, expressions[179]); expressions[181] = BinaryenConst(the_module, BinaryenLiteralInt64(32)); expressions[182] = BinaryenLocalGet(the_module, 10, BinaryenTypeInt64()); - expressions[183] = - BinaryenBinary(the_module, 36, expressions[182], expressions[181]); + expressions[183] = BinaryenBinary(the_module, 36, expressions[182], expressions[181]); expressions[184] = BinaryenUnary(the_module, 24, expressions[183]); expressions[185] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[186] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[185]); + expressions[186] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[185]); expressions[187] = BinaryenConst(the_module, BinaryenLiteralInt32(128)); - expressions[188] = - BinaryenBinary(the_module, 1, expressions[186], expressions[187]); + expressions[188] = BinaryenBinary(the_module, 1, expressions[186], expressions[187]); expressions[189] = BinaryenLocalTee(the_module, 6, expressions[188], BinaryenTypeInt32()); expressions[190] = BinaryenStore(the_module, @@ -628,21 +524,12 @@ expressions[184], BinaryenTypeInt32()); { - BinaryenExpressionRef children[] = {expressions[166], - expressions[168], - expressions[170], - expressions[172], - expressions[178], - expressions[190], - expressions[192], - expressions[193]}; - expressions[194] = - BinaryenBlock(the_module, "bb0", children, 8, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[166], expressions[168], expressions[170], expressions[172], expressions[178], expressions[190], expressions[192], expressions[193] }; + expressions[194] = BinaryenBlock(the_module, "bb0", children, 8, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[194]); expressions[195] = BinaryenLocalGet(the_module, 6, BinaryenTypeInt32()); - expressions[196] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[195]); + expressions[196] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[195]); expressions[197] = BinaryenLocalSet(the_module, 7, expressions[196]); expressions[198] = BinaryenLocalGet(the_module, 8, BinaryenTypeInt32()); expressions[199] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -656,30 +543,22 @@ expressions[201] = BinaryenLocalGet(the_module, 7, BinaryenTypeInt32()); expressions[202] = BinaryenReturn(the_module, expressions[201]); { - BinaryenExpressionRef children[] = { - expressions[197], expressions[200], expressions[202]}; - expressions[203] = - BinaryenBlock(the_module, "bb1", children, 3, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[197], expressions[200], expressions[202] }; + expressions[203] = BinaryenBlock(the_module, "bb1", children, 3, BinaryenTypeAuto()); } relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[203]); expressions[204] = BinaryenLocalGet(the_module, 6, BinaryenTypeInt32()); - expressions[205] = - BinaryenLoad(the_module, 4, 0, 8, 0, BinaryenTypeInt32(), expressions[204]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[1], expressions[205], expressions[0]); + expressions[205] = BinaryenLoad(the_module, 4, 0, 8, 0, BinaryenTypeInt32(), expressions[204]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[205], expressions[0]); expressions[206] = BinaryenUnreachable(the_module); relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[206]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[2], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[2], expressions[0], expressions[0]); expressions[207] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[208] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[207]); + expressions[208] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[207]); expressions[209] = BinaryenLocalSet(the_module, 8, expressions[208]); relooperBlocks[3] = RelooperAddBlock(the_relooper, expressions[209]); - RelooperAddBranch( - relooperBlocks[3], relooperBlocks[0], expressions[0], expressions[0]); - expressions[210] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[3], 9); + RelooperAddBranch(relooperBlocks[3], relooperBlocks[0], expressions[0], expressions[0]); + expressions[210] = RelooperRenderAndDispose(the_relooper, relooperBlocks[3], 9); { BinaryenType varTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32(), @@ -700,9 +579,7 @@ 9, expressions[210]); } - BinaryenAddFunctionExport(the_module, - "_isize_as_tinycore::Add_::add", - "_isize_as_tinycore::Add_::add"); + BinaryenAddFunctionExport(the_module, "_isize_as_tinycore::Add_::add", "_isize_as_tinycore::Add_::add"); the_relooper = RelooperCreate(the_module); expressions[211] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[212] = BinaryenLocalSet(the_module, 1, expressions[211]); @@ -723,24 +600,16 @@ expressions[221] = BinaryenLocalGet(the_module, 3, BinaryenTypeInt32()); expressions[222] = BinaryenReturn(the_module, expressions[221]); { - BinaryenExpressionRef children[] = {expressions[212], - expressions[214], - expressions[217], - expressions[220], - expressions[222]}; - expressions[223] = - BinaryenBlock(the_module, "bb0", children, 5, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[212], expressions[214], expressions[217], expressions[220], expressions[222] }; + expressions[223] = BinaryenBlock(the_module, "bb0", children, 5, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[223]); expressions[224] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[225] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[224]); + expressions[225] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[224]); expressions[226] = BinaryenLocalSet(the_module, 4, expressions[225]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[226]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); - expressions[227] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 5); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + expressions[227] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 5); { BinaryenType varTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32(), @@ -756,8 +625,7 @@ 6, expressions[227]); } - BinaryenAddFunctionExport( - the_module, "_bool_as_tinycore::Not_::not", "_bool_as_tinycore::Not_::not"); + BinaryenAddFunctionExport(the_module, "_bool_as_tinycore::Not_::not", "_bool_as_tinycore::Not_::not"); the_relooper = RelooperCreate(the_module); expressions[228] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); expressions[229] = BinaryenLocalSet(the_module, 2, expressions[228]); @@ -769,8 +637,7 @@ expressions[235] = BinaryenLocalSet(the_module, 5, expressions[234]); expressions[236] = BinaryenLocalGet(the_module, 4, BinaryenTypeInt32()); expressions[237] = BinaryenLocalGet(the_module, 5, BinaryenTypeInt32()); - expressions[238] = - BinaryenBinary(the_module, 15, expressions[236], expressions[237]); + expressions[238] = BinaryenBinary(the_module, 15, expressions[236], expressions[237]); expressions[239] = BinaryenLocalSet(the_module, 6, expressions[238]); expressions[240] = BinaryenLocalGet(the_module, 7, BinaryenTypeInt32()); expressions[241] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -784,26 +651,16 @@ expressions[243] = BinaryenLocalGet(the_module, 6, BinaryenTypeInt32()); expressions[244] = BinaryenReturn(the_module, expressions[243]); { - BinaryenExpressionRef children[] = {expressions[229], - expressions[231], - expressions[233], - expressions[235], - expressions[239], - expressions[242], - expressions[244]}; - expressions[245] = - BinaryenBlock(the_module, "bb0", children, 7, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[229], expressions[231], expressions[233], expressions[235], expressions[239], expressions[242], expressions[244] }; + expressions[245] = BinaryenBlock(the_module, "bb0", children, 7, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[245]); expressions[246] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[247] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[246]); + expressions[247] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[246]); expressions[248] = BinaryenLocalSet(the_module, 7, expressions[247]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[248]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); - expressions[249] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 8); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + expressions[249] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 8); { BinaryenType varTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32(), @@ -823,9 +680,7 @@ 8, expressions[249]); } - BinaryenAddFunctionExport(the_module, - "_i16_as_tinycore::PartialEq_::eq", - "_i16_as_tinycore::PartialEq_::eq"); + BinaryenAddFunctionExport(the_module, "_i16_as_tinycore::PartialEq_::eq", "_i16_as_tinycore::PartialEq_::eq"); the_relooper = RelooperCreate(the_module); expressions[250] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt64()); expressions[251] = BinaryenLocalSet(the_module, 2, expressions[250]); @@ -837,8 +692,7 @@ expressions[257] = BinaryenLocalSet(the_module, 5, expressions[256]); expressions[258] = BinaryenLocalGet(the_module, 4, BinaryenTypeInt64()); expressions[259] = BinaryenLocalGet(the_module, 5, BinaryenTypeInt64()); - expressions[260] = - BinaryenBinary(the_module, 40, expressions[258], expressions[259]); + expressions[260] = BinaryenBinary(the_module, 40, expressions[258], expressions[259]); expressions[261] = BinaryenLocalSet(the_module, 6, expressions[260]); expressions[262] = BinaryenLocalGet(the_module, 7, BinaryenTypeInt64()); expressions[263] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); @@ -852,26 +706,16 @@ expressions[265] = BinaryenLocalGet(the_module, 6, BinaryenTypeInt32()); expressions[266] = BinaryenReturn(the_module, expressions[265]); { - BinaryenExpressionRef children[] = {expressions[251], - expressions[253], - expressions[255], - expressions[257], - expressions[261], - expressions[264], - expressions[266]}; - expressions[267] = - BinaryenBlock(the_module, "bb0", children, 7, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[251], expressions[253], expressions[255], expressions[257], expressions[261], expressions[264], expressions[266] }; + expressions[267] = BinaryenBlock(the_module, "bb0", children, 7, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[267]); expressions[268] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); - expressions[269] = - BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt64(), expressions[268]); + expressions[269] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt64(), expressions[268]); expressions[270] = BinaryenLocalSet(the_module, 7, expressions[269]); relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[270]); - RelooperAddBranch( - relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); - expressions[271] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 8); + RelooperAddBranch(relooperBlocks[1], relooperBlocks[0], expressions[0], expressions[0]); + expressions[271] = RelooperRenderAndDispose(the_relooper, relooperBlocks[1], 8); { BinaryenType varTypes[] = {BinaryenTypeInt64(), BinaryenTypeInt64(), @@ -891,9 +735,7 @@ 8, expressions[271]); } - BinaryenAddFunctionExport(the_module, - "_i64_as_tinycore::PartialEq_::eq", - "_i64_as_tinycore::PartialEq_::eq"); + BinaryenAddFunctionExport(the_module, "_i64_as_tinycore::PartialEq_::eq", "_i64_as_tinycore::PartialEq_::eq"); assert(BinaryenModuleValidate(the_module)); BinaryenModuleDispose(the_module); expressions.clear(); diff -Nru binaryen-108/test/example/c-api-unused-mem.cpp binaryen-99/test/example/c-api-unused-mem.cpp --- binaryen-108/test/example/c-api-unused-mem.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/c-api-unused-mem.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,10 +1,10 @@ // beginning a Binaryen API trace -#include "binaryen-c.h" #include -#include -#include #include +#include +#include +#include "binaryen-c.h" int main() { std::map expressions; @@ -16,26 +16,16 @@ expressions[size_t(NULL)] = BinaryenExpressionRef(NULL); BinaryenModuleAutoDrop(the_module); { - const char* segments[] = {0}; - bool segmentPassive[] = {false}; - BinaryenExpressionRef segmentOffsets[] = {0}; - BinaryenIndex segmentSizes[] = {0}; - BinaryenSetMemory(the_module, - 256, - 256, - "memory", - segments, - segmentPassive, - segmentOffsets, - segmentSizes, - 0, - 0); + const char* segments[] = { 0 }; + int8_t segmentPassive[] = { 0 }; + BinaryenExpressionRef segmentOffsets[] = { 0 }; + BinaryenIndex segmentSizes[] = { 0 }; + BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } the_relooper = RelooperCreate(the_module); { - BinaryenExpressionRef children[] = {0}; - expressions[1] = - BinaryenBlock(the_module, "bb0", children, 0, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { 0 }; + expressions[1] = BinaryenBlock(the_module, "bb0", children, 0, BinaryenTypeAuto()); } relooperBlocks[0] = RelooperAddBlock(the_relooper, expressions[1]); expressions[2] = BinaryenLocalGet(the_module, 0, BinaryenTypeInt32()); @@ -44,22 +34,18 @@ the_module, 4, 0, 0, expressions[3], expressions[2], BinaryenTypeInt32()); expressions[5] = BinaryenReturn(the_module, expressions[0]); { - BinaryenExpressionRef children[] = {expressions[4], expressions[5]}; - expressions[6] = - BinaryenBlock(the_module, "bb1", children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[4], expressions[5] }; + expressions[6] = BinaryenBlock(the_module, "bb1", children, 2, BinaryenTypeAuto()); } relooperBlocks[1] = RelooperAddBlock(the_relooper, expressions[6]); - RelooperAddBranch( - relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); + RelooperAddBranch(relooperBlocks[0], relooperBlocks[1], expressions[0], expressions[0]); expressions[7] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); expressions[8] = BinaryenLoad(the_module, 4, 0, 0, 0, BinaryenTypeInt32(), expressions[7]); expressions[9] = BinaryenLocalSet(the_module, 0, expressions[8]); relooperBlocks[2] = RelooperAddBlock(the_relooper, expressions[9]); - RelooperAddBranch( - relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]); - expressions[10] = - RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 1); + RelooperAddBranch(relooperBlocks[2], relooperBlocks[0], expressions[0], expressions[0]); + expressions[10] = RelooperRenderAndDispose(the_relooper, relooperBlocks[2], 1); { BinaryenType varTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32(), BinaryenTypeInt64()}; @@ -73,34 +59,23 @@ } BinaryenAddFunctionExport(the_module, "main", "main"); { - const char* segments[] = {0}; - bool segmentPassive[] = {false}; - BinaryenExpressionRef segmentOffsets[] = {0}; - BinaryenIndex segmentSizes[] = {0}; - BinaryenSetMemory(the_module, - 1024, - 1024, - NULL, - segments, - segmentPassive, - segmentOffsets, - segmentSizes, - 0, - 0); + const char* segments[] = { 0 }; + int8_t segmentPassive[] = { 0 }; + BinaryenExpressionRef segmentOffsets[] = { 0 }; + BinaryenIndex segmentSizes[] = { 0 }; + BinaryenSetMemory(the_module, 1024, 1024, NULL, segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } expressions[11] = BinaryenConst(the_module, BinaryenLiteralInt32(65535)); expressions[12] = BinaryenConst(the_module, BinaryenLiteralInt32(0)); expressions[13] = BinaryenStore( the_module, 4, 0, 0, expressions[12], expressions[11], BinaryenTypeInt32()); { - BinaryenExpressionRef operands[] = {0}; - expressions[14] = - BinaryenCall(the_module, "main", operands, 0, BinaryenTypeNone()); + BinaryenExpressionRef operands[] = { 0 }; + expressions[14] = BinaryenCall(the_module, "main", operands, 0, BinaryenTypeNone()); } { - BinaryenExpressionRef children[] = {expressions[13], expressions[14]}; - expressions[15] = - BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeAuto()); + BinaryenExpressionRef children[] = { expressions[13], expressions[14] }; + expressions[15] = BinaryenBlock(the_module, NULL, children, 2, BinaryenTypeAuto()); } BinaryenAddFunctionExport(the_module, "__wasm_start", "rust_entry"); { diff -Nru binaryen-108/test/example/cpp-threads.cpp binaryen-99/test/example/cpp-threads.cpp --- binaryen-108/test/example/cpp-threads.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/cpp-threads.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -24,8 +24,7 @@ // Create the add function // Note: no additional local variables - // Note: no basic blocks here, we are an AST. The function body is just an - // expression node. + // Note: no basic blocks here, we are an AST. The function body is just an expression node. BinaryenFunctionRef adder = BinaryenAddFunction(module, "adder", ii, BinaryenTypeInt32(), NULL, 0, ret); diff -Nru binaryen-108/test/example/cpp-unit.cpp binaryen-99/test/example/cpp-unit.cpp --- binaryen-108/test/example/cpp-unit.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/cpp-unit.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -6,21 +6,20 @@ #include #include #include -#include #include using namespace wasm; using namespace Bits; -#define RESET "\x1b[0m" +#define RESET "\x1b[0m" -#define FG_BLACK "\x1b[30m" -#define FG_RED "\x1b[31m" -#define FG_GREEN "\x1b[32m" +#define FG_BLACK "\x1b[30m" +#define FG_RED "\x1b[31m" +#define FG_GREEN "\x1b[32m" #define FG_YELLOW "\x1b[33m" -#define BG_BLACK "\x1b[40m" -#define BG_RED "\x1b[41m" +#define BG_BLACK "\x1b[40m" +#define BG_RED "\x1b[41m" static int failsCount = 0; @@ -28,16 +27,20 @@ void assert_equal_(T a, U b, int line, const char* file) { if (a != b) { std::cerr << '\n' - << BG_RED FG_BLACK << " ASSERTION ERROR " << ++failsCount - << " " << RESET FG_RED << "\n" - << FG_RED << " Actual: " << a << '\n' - << FG_GREEN << " Expected: " << b << "\n\n" - << FG_YELLOW << " Line: " << line << '\n' - << FG_YELLOW << " File: " << file << '\n' - << RESET << std::endl; - - std::cout << "actual: " << a << ", expected: " << b << ", line " << line - << ", file " << file << std::endl; + << BG_RED FG_BLACK << " ASSERTION ERROR " + << ++failsCount << " " + << RESET FG_RED << "\n" + << FG_RED << " Actual: " << a << '\n' + << FG_GREEN << " Expected: " << b << "\n\n" + << FG_YELLOW << " Line: " << line << '\n' + << FG_YELLOW << " File: " << file << '\n' + << RESET << std::endl; + + std::cout << "actual: " << a + << ", expected: " << b + << ", line " << line + << ", file " << file + << std::endl; } } @@ -56,7 +59,7 @@ c0.type = Type::i32; c1.type = Type::i32; - b.type = Type::i32; + b.type = Type::i32; c0.value = Literal(int32_t(0)); assert_equal(getMaxBits(&c0), 0); @@ -124,17 +127,17 @@ c0.value = Literal(int32_t(0)); c1.value = Literal(int32_t(0xF)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(int32_t(1)); - c1.value = Literal(int32_t(2)); + c0.value = Literal(int32_t( 1)); + c1.value = Literal(int32_t( 2)); assert_equal(getMaxBits(&b), 0); c0.value = Literal(int32_t(0xFF)); c1.value = Literal(int32_t(0xFF)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(int32_t(-1)); - c1.value = Literal(int32_t(1)); + c1.value = Literal(int32_t( 1)); assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(-1)); - c1.value = Literal(int32_t(2)); + c1.value = Literal(int32_t( 2)); assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(0x7FFFFFFF)); c1.value = Literal(int32_t(3)); @@ -152,21 +155,22 @@ c1.value = Literal(int32_t(-2)); assert_equal(getMaxBits(&b), 32); + b.op = DivUInt32; c0.value = Literal(uint32_t(0)); c1.value = Literal(uint32_t(0xF)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(uint32_t(1)); - c1.value = Literal(uint32_t(2)); + c0.value = Literal(uint32_t( 1)); + c1.value = Literal(uint32_t( 2)); assert_equal(getMaxBits(&b), 0); c0.value = Literal(uint32_t(0xFF)); c1.value = Literal(uint32_t(0xFF)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint32_t(-1)); - c1.value = Literal(uint32_t(1)); + c1.value = Literal(uint32_t( 1)); assert_equal(getMaxBits(&b), 32); c0.value = Literal(uint32_t(-1)); - c1.value = Literal(uint32_t(2)); + c1.value = Literal(uint32_t( 2)); assert_equal(getMaxBits(&b), 31); c0.value = Literal(uint32_t(0x7FFFFFFF)); c1.value = Literal(uint32_t(3)); @@ -191,11 +195,11 @@ c0.value = Literal(int32_t(0)); c1.value = Literal(int32_t(-1)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(int32_t(1)); - c1.value = Literal(int32_t(2)); + c0.value = Literal(int32_t( 1)); + c1.value = Literal(int32_t( 2)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(int32_t(-1)); - c1.value = Literal(int32_t(2)); + c1.value = Literal(int32_t( 2)); assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(3)); c1.value = Literal(int32_t(-1)); @@ -211,11 +215,11 @@ c0.value = Literal(uint32_t(0)); c1.value = Literal(uint32_t(-1)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(uint32_t(1)); - c1.value = Literal(uint32_t(2)); + c0.value = Literal(uint32_t( 1)); + c1.value = Literal(uint32_t( 2)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint32_t(-1)); - c1.value = Literal(uint32_t(2)); + c1.value = Literal(uint32_t( 2)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint32_t(3)); c1.value = Literal(uint32_t(-1)); @@ -281,7 +285,7 @@ c0.type = Type::i64; c1.type = Type::i64; - b.type = Type::i64; + b.type = Type::i64; c0.value = Literal(int64_t(0)); assert_equal(getMaxBits(&c0), 0); @@ -349,17 +353,17 @@ c0.value = Literal(int64_t(0)); c1.value = Literal(int64_t(0xF)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(int64_t(1)); - c1.value = Literal(int64_t(2)); + c0.value = Literal(int64_t( 1)); + c1.value = Literal(int64_t( 2)); assert_equal(getMaxBits(&b), 0); c0.value = Literal(int64_t(0xFF)); c1.value = Literal(int64_t(0xFF)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(int64_t(-1)); - c1.value = Literal(int64_t(1)); + c1.value = Literal(int64_t( 1)); assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(-1)); - c1.value = Literal(int64_t(2)); + c1.value = Literal(int64_t( 2)); assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(int64_t(3)); @@ -375,17 +379,17 @@ c0.value = Literal(uint64_t(0)); c1.value = Literal(uint64_t(0xF)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(uint64_t(1)); - c1.value = Literal(uint64_t(2)); + c0.value = Literal(uint64_t( 1)); + c1.value = Literal(uint64_t( 2)); assert_equal(getMaxBits(&b), 0); c0.value = Literal(uint64_t(0xFF)); c1.value = Literal(uint64_t(0xFF)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint64_t(-1)); - c1.value = Literal(uint64_t(1)); + c1.value = Literal(uint64_t( 1)); assert_equal(getMaxBits(&b), 64); c0.value = Literal(uint64_t(-1)); - c1.value = Literal(uint64_t(2)); + c1.value = Literal(uint64_t( 2)); assert_equal(getMaxBits(&b), 63); c0.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(uint64_t(3)); @@ -404,11 +408,11 @@ c0.value = Literal(int64_t(0)); c1.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(int64_t(1)); - c1.value = Literal(int64_t(2)); + c0.value = Literal(int64_t( 1)); + c1.value = Literal(int64_t( 2)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(int64_t(-1)); - c1.value = Literal(int64_t(2)); + c1.value = Literal(int64_t( 2)); assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(3)); c1.value = Literal(int64_t(-1)); @@ -424,11 +428,11 @@ c0.value = Literal(uint64_t(0)); c1.value = Literal(uint64_t(-1)); assert_equal(getMaxBits(&b), 0); - c0.value = Literal(uint64_t(1)); - c1.value = Literal(uint64_t(2)); + c0.value = Literal(uint64_t( 1)); + c1.value = Literal(uint64_t( 2)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint64_t(-1)); - c1.value = Literal(uint64_t(2)); + c1.value = Literal(uint64_t( 2)); assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint64_t(3)); c1.value = Literal(uint64_t(-1)); @@ -533,56 +537,6 @@ c0.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&u), 32); - u.type = Type::i32; - c0.type = Type::i32; - - u.op = ExtendS8Int32; - c0.value = Literal(int8_t(0)); - assert_equal(getMaxBits(&u), 0); - c0.value = Literal(int8_t(127)); - assert_equal(getMaxBits(&u), 7); - c0.value = Literal(int8_t(128)); - assert_equal(getMaxBits(&u), 32); - - u.op = ExtendS16Int32; - c0.value = Literal(int16_t(0)); - assert_equal(getMaxBits(&u), 0); - c0.value = Literal(int16_t(0x7FFF)); - assert_equal(getMaxBits(&u), 15); - c0.value = Literal(int16_t(0x8000)); - assert_equal(getMaxBits(&u), 32); - - u.type = Type::i64; - c0.type = Type::i32; - - u.op = ExtendS8Int64; - c0.value = Literal(int8_t(0)); - assert_equal(getMaxBits(&u), 0); - c0.value = Literal(int8_t(127)); - assert_equal(getMaxBits(&u), 7); - c0.value = Literal(int8_t(128)); - assert_equal(getMaxBits(&u), 64); - - u.op = ExtendS16Int64; - c0.value = Literal(int16_t(0)); - assert_equal(getMaxBits(&u), 0); - c0.value = Literal(int16_t(0x7FFF)); - assert_equal(getMaxBits(&u), 15); - c0.value = Literal(int16_t(0x8000)); - assert_equal(getMaxBits(&u), 64); - - u.type = Type::i64; - c0.type = Type::i64; - - u.op = ExtendS32Int64; - c0.value = Literal(int64_t(0)); - assert_equal(getMaxBits(&u), 0); - c0.value = Literal(int64_t(0x7FFFFFFFLL)); - assert_equal(getMaxBits(&u), 31); - c0.value = Literal(int64_t(0xFFFFFFFFLL)); - assert_equal(getMaxBits(&u), 64); - c0.value = Literal(int64_t(-1LL)); - assert_equal(getMaxBits(&u), 64); } void test_cost() { @@ -593,97 +547,19 @@ void test_effects() { PassOptions options; - Module module; - + FeatureSet features; // Unreachables trap. Unreachable unreachable; - assert_equal(EffectAnalyzer(options, module, &unreachable).trap, true); - + assert_equal(EffectAnalyzer(options, features, &unreachable).trap, true); // Nops... do not. Nop nop; - assert_equal(EffectAnalyzer(options, module, &nop).trap, false); - - // ArrayCopy can trap, reads arrays, and writes arrays (but not structs). - { - ArrayCopy arrayCopy(module.allocator); - EffectAnalyzer effects(options, module); - effects.visit(&arrayCopy); - assert_equal(effects.trap, true); - assert_equal(effects.readsArray, true); - assert_equal(effects.writesArray, true); - assert_equal(effects.readsMutableStruct, false); - assert_equal(effects.writesStruct, false); - } -} - -void test_literals() { - // The i31 heap type may or may not be basic, depending on if it is nullable. - // Verify we handle both code paths. - { - Literal x(Type(HeapType::i31, Nullable)); - std::cout << x << '\n'; - } - { - Literal x(Type(HeapType::i31, NonNullable)); - std::cout << x << '\n'; - } -} - -void test_field() { - // Simple types - assert_equal(Field(Type::i32, Immutable).getByteSize(), 4); - assert_equal(Field(Type::i64, Immutable).getByteSize(), 8); - - // Packed types - assert_equal(Field(Field::PackedType::i8, Immutable).getByteSize(), 1); - assert_equal(Field(Field::PackedType::i16, Immutable).getByteSize(), 2); - assert_equal(Field(Field::PackedType::not_packed, Immutable).getByteSize(), - 4); -} - -void test_queue() { - { - UniqueDeferredQueue queue; - queue.push(1); - queue.push(2); - queue.push(3); - queue.push(2); - // first in was 1 - assert_equal(queue.pop(), 1); - // next in was 2, but it was added later, so we defer to then, and get the 3 - assert_equal(queue.pop(), 3); - assert_equal(queue.pop(), 2); - assert_equal(queue.empty(), true); - } - { - UniqueDeferredQueue queue; - queue.push(1); - queue.push(2); - assert_equal(queue.pop(), 1); - // clearing clears the queue - queue.clear(); - assert_equal(queue.empty(), true); - } - { - UniqueNonrepeatingDeferredQueue queue; - queue.push(1); - assert_equal(queue.pop(), 1); - queue.push(1); - // We never repeat values in this queue, so the last push of 1 is ignored. - assert_equal(queue.empty(), true); - // But new values work. - queue.push(2); - assert_equal(queue.pop(), 2); - } + assert_equal(EffectAnalyzer(options, features, &nop).trap, false); } int main() { test_bits(); test_cost(); test_effects(); - test_literals(); - test_field(); - test_queue(); if (failsCount > 0) { abort(); diff -Nru binaryen-108/test/example/cpp-unit.txt binaryen-99/test/example/cpp-unit.txt --- binaryen-108/test/example/cpp-unit.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/cpp-unit.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,3 +1 @@ -i31ref(0) -i31ref(0) Success diff -Nru binaryen-108/test/example/domtree.cpp binaryen-99/test/example/domtree.cpp --- binaryen-108/test/example/domtree.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/domtree.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -#include -#include - -#include -#include - -using namespace wasm; - -struct BasicBlock { - std::vector in; - - void addPred(BasicBlock* pred) { in.push_back(pred); } -}; - -struct CFG : public std::vector> { - BasicBlock* add() { - emplace_back(std::make_unique()); - return back().get(); - } - - void connect(BasicBlock* pred, BasicBlock* succ) { succ->addPred(pred); } -}; - -int main() { - // An empty CFG. - { - CFG cfg; - - DomTree domTree(cfg); - assert(domTree.iDoms.empty()); - } - - // An CFG with just an entry. - { - CFG cfg; - cfg.add(); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 1); - assert(domTree.iDoms[0] == Index(-1)); // the entry has no parent. - } - - // entry -> a. - { - CFG cfg; - auto* entry = cfg.add(); - auto* a = cfg.add(); - cfg.connect(entry, a); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 2); - assert(domTree.iDoms[0] == Index(-1)); - assert(domTree.iDoms[1] == 0); // a is dominated by the entry. - } - - // entry and a non-connected (unreachable) block. - { - CFG cfg; - auto* entry = cfg.add(); - auto* a = cfg.add(); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 2); - assert(domTree.iDoms[0] == Index(-1)); - assert(domTree.iDoms[1] == Index(-1)); // unreachables have no parent. - } - - // entry -> a -> b -> c. - { - CFG cfg; - auto* entry = cfg.add(); - auto* a = cfg.add(); - auto* b = cfg.add(); - auto* c = cfg.add(); - cfg.connect(entry, a); - cfg.connect(a, b); - cfg.connect(b, c); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 4); - assert(domTree.iDoms[0] == Index(-1)); - assert(domTree.iDoms[1] == 0); - assert(domTree.iDoms[2] == 1); - assert(domTree.iDoms[3] == 2); - } - - // An if: - // b - // / \ - // entry -> a d - // \ / - // c - { - CFG cfg; - auto* entry = cfg.add(); - auto* a = cfg.add(); - auto* b = cfg.add(); - auto* c = cfg.add(); - auto* d = cfg.add(); - cfg.connect(entry, a); - cfg.connect(a, b); - cfg.connect(a, c); - cfg.connect(b, d); - cfg.connect(c, d); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 5); - assert(domTree.iDoms[0] == Index(-1)); - assert(domTree.iDoms[1] == 0); // a - assert(domTree.iDoms[2] == 1); // b - assert(domTree.iDoms[3] == 1); // c - assert(domTree.iDoms[4] == 1); // d is also dominated by a. - } - - // A loop: - // - // entry -> a -> b -> c -> d - // ^ | - // | | - // \---------/ - { - CFG cfg; - auto* entry = cfg.add(); - auto* a = cfg.add(); - auto* b = cfg.add(); - auto* c = cfg.add(); - auto* d = cfg.add(); - cfg.connect(entry, a); - cfg.connect(a, b); - cfg.connect(b, c); - cfg.connect(c, d); - cfg.connect(d, b); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 5); - assert(domTree.iDoms[0] == Index(-1)); - assert(domTree.iDoms[1] == 0); // a - assert(domTree.iDoms[2] == 1); // b, the loop entry, is dominated by a - assert(domTree.iDoms[3] == 2); // c, the loop "middle", is dominated by b - assert(domTree.iDoms[4] == 3); // d, the loop "end", is dominated by c - } - - // Subsequent blocks after an unreachable one. - // - // entry a -> b - // - // (a is unreachable, and b is reached by a, but in unreachable code) - { - CFG cfg; - auto* entry = cfg.add(); - auto* a = cfg.add(); - auto* b = cfg.add(); - cfg.connect(a, b); - - DomTree domTree(cfg); - assert(domTree.iDoms.size() == 3); - assert(domTree.iDoms[0] == Index(-1)); - assert(domTree.iDoms[1] == Index(-1)); // a - assert(domTree.iDoms[2] == Index(-1)); // b - } - - std::cout << "success.\n"; -} diff -Nru binaryen-108/test/example/domtree.txt binaryen-99/test/example/domtree.txt --- binaryen-108/test/example/domtree.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/domtree.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -success. diff -Nru binaryen-108/test/example/hash.cpp binaryen-99/test/example/hash.cpp --- binaryen-108/test/example/hash.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/hash.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -11,14 +11,6 @@ #define assertNotEqual(left, right) \ assert(ExpressionAnalyzer::hash(&left) != ExpressionAnalyzer::hash(&right)); -#define assertShallowEqual(left, right) \ - assert(ExpressionAnalyzer::shallowHash(&left) == \ - ExpressionAnalyzer::shallowHash(&right)); - -#define assertShallowNotEqual(left, right) \ - assert(ExpressionAnalyzer::shallowHash(&left) != \ - ExpressionAnalyzer::shallowHash(&right)); - int main() { { Const x, y; @@ -41,7 +33,7 @@ assertNotEqual(x, y); } { - // Nested identical child. + // Nested child. Drop dx, dy; Const x, y; x.set(Literal(int32_t(10))); @@ -51,17 +43,7 @@ assertEqual(dx, dy); } { - // Nested identical child, checked shallowly. - Drop dx, dy; - Const x, y; - x.set(Literal(int32_t(10))); - y.set(Literal(int32_t(10))); - dx.value = &x; - dy.value = &y; - assertShallowEqual(dx, dy); - } - { - // Nested different child. + // Nested child. Drop dx, dy; Const x, y; x.set(Literal(int32_t(10))); @@ -70,17 +52,6 @@ dy.value = &y; assertNotEqual(dx, dy); } - { - // Nested different child, checked shallowly (so we ignore the difference, - // and return equal). - Drop dx, dy; - Const x, y; - x.set(Literal(int32_t(10))); - y.set(Literal(int32_t(11))); - dx.value = &x; - dy.value = &y; - assertShallowEqual(dx, dy); - } MixedArena arena; { // Blocks @@ -167,15 +138,5 @@ y.index = 11; assertNotEqual(x, y); } - { - // It is ok to hash something that refers to an unknown name, like a break - // without the outside context that it branches to. And different names - // should have different hashes. - Break x; - x.name = "foo"; - Break y; - y.name = "bar"; - assertNotEqual(x, y); - } std::cout << "success.\n"; } diff -Nru binaryen-108/test/example/local-graph.cpp binaryen-99/test/example/local-graph.cpp --- binaryen-108/test/example/local-graph.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/local-graph.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -#include - -#include -#include -#include - -using namespace wasm; - -int main() { - Module wasm; - Builder builder(wasm); - - { - Function foo; - foo.type = Signature(Type::none, Type::none); - foo.vars = {Type::i32}; - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(0, Type::i32); - foo.body = builder.makeBlock({ - builder.makeLocalSet(0, builder.makeConst(Literal(int32_t(0)))), - // two equivalent gets, as both are preceded by the same single set - builder.makeDrop(get1), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(graph.equivalent(get1, get2)); - } - - { - Function foo; - foo.type = Signature(Type::none, Type::none); - foo.vars = {Type::i32}; - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(0, Type::i32); - foo.body = builder.makeBlock({ - // two non-equivalent gets, as there is a set in between them - builder.makeDrop(get1), - builder.makeLocalSet(0, builder.makeConst(Literal(int32_t(0)))), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(!graph.equivalent(get1, get2)); - } - - { - Function foo; - foo.type = Signature({Type::i32}, Type::none); - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(0, Type::i32); - foo.body = builder.makeBlock({ - // two equivalent gets of the same parameter - builder.makeDrop(get1), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(graph.equivalent(get1, get2)); - } - - { - Function foo; - foo.type = Signature({Type::i32}, Type::none); - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(0, Type::i32); - foo.body = builder.makeBlock({ - // two non-equivalent gets of the same parameter, as there is a set - builder.makeDrop(get1), - builder.makeLocalSet(0, builder.makeConst(Literal(int32_t(0)))), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(!graph.equivalent(get1, get2)); - } - - { - Function foo; - foo.type = Signature({Type::i32, Type::i32}, Type::none); - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(1, Type::i32); - foo.body = builder.makeBlock({ - // two non-equivalent gets as they are of different parameters - builder.makeDrop(get1), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(!graph.equivalent(get1, get2)); - } - - { - Function foo; - foo.type = Signature(Type::none, Type::none); - foo.vars = {Type::i32, Type::i32}; - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(1, Type::i32); - foo.body = builder.makeBlock({ - // two equivalent gets, even though they have a different index, as both - // use the zero initialized value - builder.makeDrop(get1), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(graph.equivalent(get1, get2)); - } - - { - Function foo; - foo.type = Signature(Type::none, Type::none); - foo.vars = {Type::i32, Type::f64}; - auto* get1 = builder.makeLocalGet(0, Type::i32); - auto* get2 = builder.makeLocalGet(1, Type::f64); - foo.body = builder.makeBlock({ - // two non-equivalent gets as their zero-init value is different - builder.makeDrop(get1), - builder.makeDrop(get2), - }); - LocalGraph graph(&foo); - assert(!graph.equivalent(get1, get2)); - } - - std::cout << "Success." << std::endl; - - return 0; -} diff -Nru binaryen-108/test/example/local-graph.txt binaryen-99/test/example/local-graph.txt --- binaryen-108/test/example/local-graph.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/local-graph.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Success. diff -Nru binaryen-108/test/example/match.cpp binaryen-99/test/example/match.cpp --- binaryen-108/test/example/match.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/match.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -123,11 +123,10 @@ } void test_internal_literal() { - std::cout << "Testing Internal::{Bool,I32,I64,Int,F32,F64,Float}Lit\n"; + std::cout << "Testing Internal::{I32,I64,Int,F32,F64,Float}Lit\n"; Literal i32Zero(int32_t(0)); Literal i32One(int32_t(1)); - Literal i32Two(int32_t(2)); Literal f32Zero(float(0)); Literal f32One(float(1)); Literal i64Zero(int64_t(0)); @@ -135,17 +134,6 @@ Literal f64Zero(double(0)); Literal f64One(double(1)); - auto anyBool = Internal::BoolLit(nullptr, Internal::Any(nullptr)); - assert(anyBool.matches(i32Zero)); - assert(anyBool.matches(i32One)); - assert(!anyBool.matches(i32Two)); - assert(!anyBool.matches(f32Zero)); - assert(!anyBool.matches(f32One)); - assert(!anyBool.matches(i64Zero)); - assert(!anyBool.matches(i64One)); - assert(!anyBool.matches(f64Zero)); - assert(!anyBool.matches(f64One)); - auto anyi32 = Internal::I32Lit(nullptr, Internal::Any(nullptr)); assert(anyi32.matches(i32Zero)); assert(anyi32.matches(i32One)); diff -Nru binaryen-108/test/example/match.txt binaryen-99/test/example/match.txt --- binaryen-108/test/example/match.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/match.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ Testing Internal::Any Testing Internal::Exact -Testing Internal::{Bool,I32,I64,Int,F32,F64,Float}Lit +Testing Internal::{I32,I64,Int,F32,F64,Float}Lit Testing Internal::ConstantMatcher Testing Internal::UnaryMatcher Testing Internal::UnaryOpMatcher diff -Nru binaryen-108/test/example/module-splitting.cpp binaryen-99/test/example/module-splitting.cpp --- binaryen-108/test/example/module-splitting.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/module-splitting.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -50,7 +50,7 @@ ModuleSplitting::Config config; config.primaryFuncs = keptFuncs; config.newExportPrefix = "%"; - auto secondary = splitFunctions(*primary, config).secondary; + auto secondary = splitFunctions(*primary, config); std::cout << "After:\n"; std::cout << *primary.get(); @@ -64,8 +64,6 @@ assert(valid && "secondary invalid!"); } -void test_minimized_exports(); - int main() { // Trivial module do_test({}, "(module)"); @@ -76,7 +74,7 @@ (memory $mem (shared 3 42)) (table $tab 3 42 funcref) (global $glob (mut i32) (i32.const 7)) - (tag $e (param i32)) + (event $e (attr 0) (param i32)) ))"); // Imported global stuff @@ -85,7 +83,7 @@ (import "env" "mem" (memory $mem (shared 3 42))) (import "env" "tab" (table $tab 3 42 funcref)) (import "env" "glob" (global $glob (mut i32))) - (import "env" "e" (tag $e (param i32))) + (import "env" "e" (event $e (attr 0) (param i32))) ))"); // Exported global stuff @@ -94,11 +92,11 @@ (memory $mem (shared 3 42)) (table $tab 3 42 funcref) (global $glob (mut i32) (i32.const 7)) - (tag $e (param i32)) + (event $e (attr 0) (param i32)) (export "mem" (memory $mem)) (export "tab" (table $tab)) (export "glob" (global $glob)) - (export "e" (tag $e)) + (export "e" (event $e)) ))"); // Non-deferred function @@ -128,16 +126,6 @@ ) ))"); - // Non-deferred function in table multiple times - do_test({"foo"}, R"( - (module - (table $table 2 funcref) - (elem (i32.const 0) $foo $foo) - (func $foo (param i32) (result i32) - (local.get 0) - ) - ))"); - // Non-deferred function in table at non-const offset do_test({"foo"}, R"( (module @@ -149,17 +137,6 @@ ) ))"); - // Non-deferred function in table at non-const offset multiple times - do_test({"foo"}, R"( - (module - (import "env" "base" (global $base i32)) - (table $table 2 funcref) - (elem (global.get $base) $foo $foo) - (func $foo (param i32) (result i32) - (local.get 0) - ) - ))"); - // Non-deferred imported function do_test({"foo"}, R"( (module @@ -212,16 +189,6 @@ ) ))"); - // Deferred function in table multiple times - do_test({}, R"( - (module - (table $table 2 funcref) - (elem (i32.const 0) $foo $foo) - (func $foo (param i32) (result i32) - (local.get 0) - ) - ))"); - // Deferred exported function in table at a weird offset do_test({}, R"( (module @@ -245,18 +212,6 @@ ) ))"); - // Deferred exported function in table at a non-const offset multiple times - do_test({}, R"( - (module - (import "env" "base" (global $base i32)) - (table $table 1000 funcref) - (elem (global.get $base) $foo $foo) - (export "foo" (func $foo)) - (func $foo (param i32) (result i32) - (local.get 0) - ) - ))"); - // Deferred exported function in table at an offset from a non-const base do_test({"null"}, R"( (module @@ -439,48 +394,4 @@ (export "foo2" (func $foo)) (func $foo) ))"); - - test_minimized_exports(); -} - -void test_minimized_exports() { - Module primary; - primary.features = FeatureSet::All; - - std::set keep; - Expression* callBody = nullptr; - - Builder builder(primary); - auto funcType = Signature(Type::none, Type::none); - - for (size_t i = 0; i < 10; ++i) { - Name name = std::to_string(i); - primary.addFunction( - Builder::makeFunction(name, funcType, {}, builder.makeNop())); - keep.insert(name); - callBody = - builder.blockify(callBody, builder.makeCall(name, {}, Type::none)); - - if (i == 3) { - primary.addExport( - Builder::makeExport("already_exported", name, ExternalKind::Function)); - } - if (i == 7) { - primary.addExport( - Builder::makeExport("%b", name, ExternalKind::Function)); - } - } - - primary.addFunction(Builder::makeFunction("call", funcType, {}, callBody)); - - ModuleSplitting::Config config; - config.primaryFuncs = std::move(keep); - config.newExportPrefix = "%"; - config.minimizeNewExportNames = true; - - auto secondary = splitFunctions(primary, config).secondary; - std::cout << "Minimized names primary:\n"; - std::cout << primary << "\n"; - std::cout << "Minimized names secondary:\n"; - std::cout << *secondary << "\n"; } diff -Nru binaryen-108/test/example/module-splitting.txt binaryen-99/test/example/module-splitting.txt --- binaryen-108/test/example/module-splitting.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/module-splitting.txt 2021-01-07 20:01:06.000000000 +0000 @@ -13,23 +13,23 @@ Before: (module (type $i32_=>_none (func (param i32))) - (global $glob (mut i32) (i32.const 7)) (memory $mem (shared 3 42)) (table $tab 3 42 funcref) - (tag $e (param i32)) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) ) Keeping: After: (module (type $i32_=>_none (func (param i32))) - (global $glob (mut i32) (i32.const 7)) (memory $mem (shared 3 42)) (table $tab 3 42 funcref) - (tag $e (param i32)) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) (export "%memory" (memory $mem)) (export "%table" (table $tab)) (export "%global" (global $glob)) - (export "%tag" (tag $e)) + (export "%event" (event $e)) ) Secondary: (module @@ -37,7 +37,7 @@ (import "primary" "%memory" (memory $mem (shared 3 42))) (import "primary" "%table" (table $tab 3 42 funcref)) (import "primary" "%global" (global $glob (mut i32))) - (import "primary" "%tag" (tag $e (param i32))) + (import "primary" "%event" (event $e (attr 0) (param i32))) ) @@ -47,7 +47,7 @@ (import "env" "mem" (memory $mem (shared 3 42))) (import "env" "tab" (table $tab 3 42 funcref)) (import "env" "glob" (global $glob (mut i32))) - (import "env" "e" (tag $e (param i32))) + (import "env" "e" (event $e (attr 0) (param i32))) ) Keeping: After: @@ -56,11 +56,11 @@ (import "env" "mem" (memory $mem (shared 3 42))) (import "env" "tab" (table $tab 3 42 funcref)) (import "env" "glob" (global $glob (mut i32))) - (import "env" "e" (tag $e (param i32))) + (import "env" "e" (event $e (attr 0) (param i32))) (export "%memory" (memory $mem)) (export "%table" (table $tab)) (export "%global" (global $glob)) - (export "%tag" (tag $e)) + (export "%event" (event $e)) ) Secondary: (module @@ -68,34 +68,34 @@ (import "primary" "%memory" (memory $mem (shared 3 42))) (import "primary" "%table" (table $tab 3 42 funcref)) (import "primary" "%global" (global $glob (mut i32))) - (import "primary" "%tag" (tag $e (param i32))) + (import "primary" "%event" (event $e (attr 0) (param i32))) ) Before: (module (type $i32_=>_none (func (param i32))) - (global $glob (mut i32) (i32.const 7)) (memory $mem (shared 3 42)) (table $tab 3 42 funcref) - (tag $e (param i32)) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) (export "mem" (memory $mem)) (export "tab" (table $tab)) (export "glob" (global $glob)) - (export "e" (tag $e)) + (export "e" (event $e)) ) Keeping: After: (module (type $i32_=>_none (func (param i32))) - (global $glob (mut i32) (i32.const 7)) (memory $mem (shared 3 42)) (table $tab 3 42 funcref) - (tag $e (param i32)) + (global $glob (mut i32) (i32.const 7)) + (event $e (attr 0) (param i32)) (export "mem" (memory $mem)) (export "tab" (table $tab)) (export "glob" (global $glob)) - (export "e" (tag $e)) + (export "e" (event $e)) ) Secondary: (module @@ -103,7 +103,7 @@ (import "primary" "mem" (memory $mem (shared 3 42))) (import "primary" "tab" (table $tab 3 42 funcref)) (import "primary" "glob" (global $glob (mut i32))) - (import "primary" "e" (tag $e (param i32))) + (import "primary" "e" (event $e (attr 0) (param i32))) ) @@ -178,32 +178,6 @@ Before: (module (type $i32_=>_i32 (func (param i32) (result i32))) - (table $table 2 funcref) - (elem (i32.const 0) $foo $foo) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) -Keeping: foo -After: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (table $table 2 funcref) - (elem (i32.const 0) $foo $foo) - (export "%table" (table $table)) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) -Secondary: -(module - (import "primary" "%table" (table $table 2 funcref)) -) - - -Before: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "base" (global $base i32)) (table $table 1 funcref) (elem (global.get $base) $foo) @@ -234,36 +208,6 @@ Before: (module (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "base" (global $base i32)) - (table $table 2 funcref) - (elem (global.get $base) $foo $foo) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) -Keeping: foo -After: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "base" (global $base i32)) - (table $table 2 funcref) - (elem (global.get $base) $foo $foo) - (export "%table" (table $table)) - (export "%global" (global $base)) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) -Secondary: -(module - (import "primary" "%table" (table $table 2 funcref)) - (import "primary" "%global" (global $base i32)) -) - - -Before: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "foo" (func $foo (param i32) (result i32))) ) Keeping: foo @@ -367,7 +311,7 @@ (export "foo" (func $foo)) (export "%table" (table $0)) (func $foo (param $0 i32) (result i32) - (call_indirect $0 (type $i32_=>_i32) + (call_indirect (type $i32_=>_i32) (local.get $0) (i32.const 0) ) @@ -416,36 +360,6 @@ Before: (module (type $i32_=>_i32 (func (param i32) (result i32))) - (table $table 2 funcref) - (elem (i32.const 0) $foo $foo) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) -Keeping: -After: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) - (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32))) - (table $table 2 funcref) - (elem (i32.const 0) $placeholder_0 $placeholder_1) - (export "%table" (table $table)) -) -Secondary: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "primary" "%table" (table $table 2 funcref)) - (elem (i32.const 0) $foo $foo) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) - - -Before: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) (table $table 1000 funcref) (elem (i32.const 42) $foo) (export "foo" (func $foo)) @@ -463,7 +377,7 @@ (export "foo" (func $foo)) (export "%table" (table $table)) (func $foo (param $0 i32) (result i32) - (call_indirect $table (type $i32_=>_i32) + (call_indirect (type $i32_=>_i32) (local.get $0) (i32.const 42) ) @@ -503,7 +417,7 @@ (export "%table" (table $table)) (export "%global" (global $base)) (func $foo (param $0 i32) (result i32) - (call_indirect $table (type $i32_=>_i32) + (call_indirect (type $i32_=>_i32) (local.get $0) (global.get $base) ) @@ -513,50 +427,8 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (import "primary" "%table" (table $table 1000 funcref)) - (import "primary" "%global" (global $base i32)) (elem (global.get $base) $foo) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) - - -Before: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "base" (global $base i32)) - (table $table 1000 funcref) - (elem (global.get $base) $foo $foo) - (export "foo" (func $foo)) - (func $foo (param $0 i32) (result i32) - (local.get $0) - ) -) -Keeping: -After: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "base" (global $base i32)) - (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) - (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32))) - (table $table 1000 funcref) - (elem (global.get $base) $placeholder_0 $placeholder_1) - (export "foo" (func $foo)) - (export "%table" (table $table)) - (export "%global" (global $base)) - (func $foo (param $0 i32) (result i32) - (call_indirect $table (type $i32_=>_i32) - (local.get $0) - (global.get $base) - ) - ) -) -Secondary: -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "primary" "%table" (table $table 1000 funcref)) (import "primary" "%global" (global $base i32)) - (elem (global.get $base) $foo $foo) (func $foo (param $0 i32) (result i32) (local.get $0) ) @@ -595,7 +467,7 @@ (nop) ) (func $foo (param $0 i32) (result i32) - (call_indirect $table (type $i32_=>_i32) + (call_indirect (type $i32_=>_i32) (local.get $0) (i32.add (global.get $base) @@ -606,12 +478,12 @@ ) Secondary: (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "primary" "%table" (table $table 1000 funcref)) + (elem (global.get $base) $null $foo) (import "primary" "%global" (global $base i32)) (import "primary" "%null" (func $null)) - (elem (global.get $base) $null $foo) (func $foo (param $0 i32) (result i32) (local.get $0) ) @@ -692,7 +564,7 @@ (elem (i32.const 0) $placeholder_0) (export "%table" (table $0)) (func $foo - (call_indirect $0 (type $none_=>_none) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) @@ -759,7 +631,7 @@ (nop) ) (func $bar - (call_indirect $0 (type $none_=>_none) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) @@ -768,8 +640,8 @@ (module (type $none_=>_none (func)) (import "primary" "%table" (table $0 1 funcref)) - (import "primary" "%foo_0" (func $foo)) (elem (i32.const 0) $bar) + (import "primary" "%foo_0" (func $foo)) (func $bar (call $foo) ) @@ -814,8 +686,8 @@ (module (type $none_=>_none (func)) (import "primary" "%table" (table $table 4 funcref)) - (elem $0 (i32.const 0) $foo) - (elem $1 (i32.const 2) $baz) + (elem (i32.const 0) $foo) + (elem (i32.const 2) $baz) (func $baz (nop) ) @@ -867,9 +739,9 @@ (module (type $none_=>_none (func)) (import "primary" "%table" (table $table 4 funcref)) + (elem (global.get $base) $foo $bar $baz) (import "primary" "%global" (global $base i32)) (import "primary" "%bar" (func $bar)) - (elem (global.get $base) $foo $bar $baz) (func $baz (nop) ) @@ -915,8 +787,8 @@ (module (type $none_=>_none (func)) (import "primary" "%table" (table $table 4 funcref)) - (elem $0 (i32.const 0) $foo $bar) - (elem $1 (i32.const 3) $quux) + (elem (i32.const 0) $foo $bar) + (elem (i32.const 3) $quux) (func $bar (nop) ) @@ -969,9 +841,9 @@ (module (type $none_=>_none (func)) (import "primary" "%table" (table $table 4 funcref)) + (elem (global.get $base) $foo $bar $baz $quux) (import "primary" "%global" (global $base i32)) (import "primary" "%baz" (func $baz)) - (elem (global.get $base) $foo $bar $baz $quux) (func $bar (nop) ) @@ -1016,9 +888,9 @@ (module (type $none_=>_none (func)) (import "primary" "%table" (table $table 2 funcref)) + (elem (global.get $base) $foo $bar) (import "primary" "%global" (global $base i32)) (import "primary" "%foo" (func $foo)) - (elem (global.get $base) $foo $bar) (func $bar (call $foo) ) @@ -1051,7 +923,7 @@ (export "%foo" (func $foo)) (export "%table" (table $table)) (func $foo (param $0 i32) (result i32) - (call_indirect $table (type $i32_=>_i32) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 1) ) @@ -1061,8 +933,8 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (import "primary" "%table" (table $table 2 2 funcref)) - (import "primary" "%foo" (func $foo (param i32) (result i32))) (elem (i32.const 1) $bar) + (import "primary" "%foo" (func $foo (param i32) (result i32))) (func $bar (param $0 i32) (result i32) (call $foo (i32.const 1) @@ -1091,7 +963,7 @@ (export "foo2" (func $foo)) (export "%table" (table $0)) (func $foo - (call_indirect $0 (type $none_=>_none) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) @@ -1107,75 +979,3 @@ ) -Minimized names primary: -(module - (type $none_=>_none (func)) - (export "already_exported" (func $3)) - (export "%b" (func $7)) - (export "%a" (func $0)) - (export "%c" (func $1)) - (export "%d" (func $2)) - (export "%e" (func $4)) - (export "%f" (func $5)) - (export "%g" (func $6)) - (export "%h" (func $8)) - (export "%i" (func $9)) - (func $0 - (nop) - ) - (func $1 - (nop) - ) - (func $2 - (nop) - ) - (func $3 - (nop) - ) - (func $4 - (nop) - ) - (func $5 - (nop) - ) - (func $6 - (nop) - ) - (func $7 - (nop) - ) - (func $8 - (nop) - ) - (func $9 - (nop) - ) -) - -Minimized names secondary: -(module - (type $none_=>_none (func)) - (import "primary" "%a" (func $0)) - (import "primary" "%c" (func $1)) - (import "primary" "%d" (func $2)) - (import "primary" "already_exported" (func $3)) - (import "primary" "%e" (func $4)) - (import "primary" "%f" (func $5)) - (import "primary" "%g" (func $6)) - (import "primary" "%b" (func $7)) - (import "primary" "%h" (func $8)) - (import "primary" "%i" (func $9)) - (func $call - (call $0) - (call $1) - (call $2) - (call $3) - (call $4) - (call $5) - (call $6) - (call $7) - (call $8) - (call $9) - ) -) - diff -Nru binaryen-108/test/example/relooper-fuzz1.c binaryen-99/test/example/relooper-fuzz1.c --- binaryen-108/test/example/relooper-fuzz1.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-fuzz1.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenEqInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 30)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeAuto()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeAuto() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,222 +77,219 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b0 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b0 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(2))}; + BinaryenConst(module, BinaryenLiteralInt32(2)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(3))}; + BinaryenConst(module, BinaryenLiteralInt32(3)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(4))}; + BinaryenConst(module, BinaryenLiteralInt32(4)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b5; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(5))}; + BinaryenConst(module, BinaryenLiteralInt32(5)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b5 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b5 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b6; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(6))}; + BinaryenConst(module, BinaryenLiteralInt32(6)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b6 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b6 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b7; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(7))}; + BinaryenConst(module, BinaryenLiteralInt32(7)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b7 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b7 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b8; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(8))}; + BinaryenConst(module, BinaryenLiteralInt32(8)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b8 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); - b8 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b9; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(9))}; + BinaryenConst(module, BinaryenLiteralInt32(9)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - - b9 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b9 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, + BinaryenTypeAuto())); + } - RelooperAddBranch( - b0, - b2, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); - - RelooperAddBranch( - b0, - b7, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenConst(module, BinaryenLiteralInt32(2))), - NULL); + RelooperAddBranch(b0, b2, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); + + RelooperAddBranch(b0, b7, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenConst(module, BinaryenLiteralInt32(2)) + ), NULL); RelooperAddBranch(b0, b3, NULL, NULL); - RelooperAddBranch( - b2, - b3, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(2))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); + RelooperAddBranch(b2, b3, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(2)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); RelooperAddBranch(b2, b9, NULL, NULL); RelooperAddBranch(b3, b3, NULL, NULL); - RelooperAddBranch( - b7, - b2, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(3))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); + RelooperAddBranch(b7, b2, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(3)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); RelooperAddBranch(b7, b9, NULL, NULL); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); - int decisions[] = {67, 131, 49, 36, 112, 161, 62, 166, 16, 88, - 176, 152, 161, 194, 117, 180, 60, 166, 55, 183, - 150, 73, 196, 143, 76, 182, 97, 140, 126, 3}; - int numDecisions = sizeof(decisions) / sizeof(int); + int decisions[] = { 67, 131, 49, 36, 112, 161, 62, 166, 16, 88, 176, 152, 161, 194, 117, 180, 60, 166, 55, 183, 150, 73, 196, 143, 76, 182, 97, 140, 126, 3 }; + int numDecisions = sizeof(decisions)/sizeof(int); // write out all the decisions, then the body of the function BinaryenExpressionRef full[numDecisions + 1]; @@ -330,22 +297,21 @@ { int i; for (i = 0; i < numDecisions; i++) { - full[i] = - BinaryenStore(module, - 4, - 0, - 0, - BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), - BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), - BinaryenTypeInt32()); + full[i] = BinaryenStore(module, + 4, 0, 0, + BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), + BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), + BinaryenTypeInt32() + ); } } full[numDecisions] = body; - BinaryenExpressionRef all = - BinaryenBlock(module, NULL, full, numDecisions + 1, BinaryenTypeAuto()); + BinaryenExpressionRef all = BinaryenBlock(module, NULL, full, + numDecisions + 1, + BinaryenTypeAuto()); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction( module, "main", BinaryenTypeNone(), BinaryenTypeNone(), localTypes, 2, all); BinaryenSetStart(module, theMain); diff -Nru binaryen-108/test/example/relooper-fuzz1.txt binaryen-99/test/example/relooper-fuzz1.txt --- binaryen-108/test/example/relooper-fuzz1.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-fuzz1.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) @@ -268,9 +268,9 @@ ) ) (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-fuzz2.c binaryen-99/test/example/relooper-fuzz2.c --- binaryen-108/test/example/relooper-fuzz2.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-fuzz2.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 27)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,159 +77,168 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b0 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b0 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b2 = RelooperAddBlockWithSwitch( - relooper, + b2 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(2)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(2)) + ) + ); + } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlockWithSwitch( - relooper, + b3 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(4))}; + BinaryenConst(module, BinaryenLiteralInt32(4)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b5; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b5 = RelooperAddBlockWithSwitch( - relooper, + b5 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b6; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(6))}; + BinaryenConst(module, BinaryenLiteralInt32(6)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b6 = RelooperAddBlockWithSwitch( - relooper, + b6 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(3)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(3)) + ) + ); + } RelooperBlockRef b7; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b7 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b7 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b8; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b8 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b8 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperAddBranch( @@ -309,10 +288,7 @@ BinaryenTypeInt32())); { - BinaryenIndex values[] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, - 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, - 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, - 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86}; + BinaryenIndex values[] = { 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86 }; RelooperAddBranchForSwitch( b2, b7, @@ -464,10 +440,7 @@ BinaryenTypeInt32())); { - BinaryenIndex values[] = {0, 3, 6, 9, 12, 15, 18, 21, 24, 27, - 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, - 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, - 90, 93, 96, 99, 102, 105, 108}; + BinaryenIndex values[] = { 0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,90,93,96,99,102,105,108 }; RelooperAddBranchForSwitch( b6, b1, @@ -494,11 +467,7 @@ } { - BinaryenIndex values[] = { - 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, - 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, - 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, - 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160}; + BinaryenIndex values[] = { 1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,127,130,133,136,139,142,145,148,151,154,157,160 }; RelooperAddBranchForSwitch( b6, b7, @@ -626,10 +595,8 @@ BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); - int decisions[] = {5, 111, 119, 17, 179, 41, 32, 3, 171, - 126, 13, 95, 70, 91, 9, 140, 99, 161, - 38, 87, 153, 117, 140, 11, 157, 48, 4}; - int numDecisions = sizeof(decisions) / sizeof(int); + int decisions[] = { 5, 111, 119, 17, 179, 41, 32, 3, 171, 126, 13, 95, 70, 91, 9, 140, 99, 161, 38, 87, 153, 117, 140, 11, 157, 48, 4 }; + int numDecisions = sizeof(decisions)/sizeof(int); // write out all the decisions, then the body of the function BinaryenExpressionRef full[numDecisions + 1]; @@ -637,22 +604,21 @@ { int i; for (i = 0; i < numDecisions; i++) { - full[i] = - BinaryenStore(module, - 4, - 0, - 0, - BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), - BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), - BinaryenTypeInt32()); + full[i] = BinaryenStore(module, + 4, 0, 0, + BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), + BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), + BinaryenTypeInt32() + ); } } full[numDecisions] = body; - BinaryenExpressionRef all = - BinaryenBlock(module, NULL, full, numDecisions + 1, BinaryenTypeNone()); + BinaryenExpressionRef all = BinaryenBlock(module, NULL, full, + numDecisions + 1, + BinaryenTypeNone()); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction( module, "main", BinaryenTypeNone(), BinaryenTypeNone(), localTypes, 2, all); BinaryenSetStart(module, theMain); @@ -669,8 +635,7 @@ BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-fuzz2.txt binaryen-99/test/example/relooper-fuzz2.txt --- binaryen-108/test/example/relooper-fuzz2.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-fuzz2.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-fuzz.c binaryen-99/test/example/relooper-fuzz.c --- binaryen-108/test/example/relooper-fuzz.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-fuzz.c 2021-01-07 20:01:06.000000000 +0000 @@ -14,89 +14,49 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenEqInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 27)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); - - // return the decision. need to subtract 4 that we just added, and add 8 since - // that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeAuto()); + if (1) debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); + else debugger = BinaryenNop(module); + + // return the decision. need to subtract 4 that we just added, and add 8 since that's where we start, so overall offset 4 + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), BinaryenTypeAuto()); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -109,144 +69,106 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(0)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b0 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b0 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b1; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(1)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b2; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(2))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(2)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b3; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(3))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(3)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b4; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(4))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(4)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b5; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(5))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(5)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b5 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b5 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b6; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(6))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(6)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b6 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b6 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b7; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(7))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(7)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b7 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b7 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } RelooperBlockRef b8; { - BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(8))}; + BinaryenExpressionRef args[] = { BinaryenConst(module, BinaryenLiteralInt32(8)) }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; - b8 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32())) + }; + b8 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeAuto())); } - RelooperAddBranch( - b0, - b5, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(2))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); + RelooperAddBranch(b0, b5, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(2)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); RelooperAddBranch(b0, b8, NULL, NULL); @@ -254,61 +176,49 @@ RelooperAddBranch(b2, b5, NULL, NULL); - RelooperAddBranch( - b3, - b5, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(2))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); + RelooperAddBranch(b3, b5, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(2)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); RelooperAddBranch(b3, b8, NULL, NULL); - RelooperAddBranch( - b4, - b4, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(3))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); - - RelooperAddBranch( - b4, - b5, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(3))), - BinaryenConst(module, BinaryenLiteralInt32(1))), - NULL); + RelooperAddBranch(b4, b4, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(3)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); + + RelooperAddBranch(b4, b5, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(3)) + ), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ), NULL); RelooperAddBranch(b4, b2, NULL, NULL); - RelooperAddBranch( - b5, - b4, - BinaryenBinary( - module, - BinaryenEqInt32(), - BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(2))), - BinaryenConst(module, BinaryenLiteralInt32(0))), - NULL); + RelooperAddBranch(b5, b4, BinaryenBinary(module, + BinaryenEqInt32(), + BinaryenBinary(module, + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(2)) + ), + BinaryenConst(module, BinaryenLiteralInt32(0)) + ), NULL); RelooperAddBranch(b5, b5, NULL, NULL); @@ -320,40 +230,33 @@ BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); - int decisions[] = {89, 12, 78, 149, 118, 179, 127, 80, 21, - 34, 119, 98, 38, 29, 36, 147, 13, 55, - 166, 16, 143, 52, 130, 150, 176, 91, 34}; - int numDecisions = sizeof(decisions) / sizeof(int); + int decisions[] = { 89, 12, 78, 149, 118, 179, 127, 80, 21, 34, 119, 98, 38, 29, 36, 147, 13, 55, 166, 16, 143, 52, 130, 150, 176, 91, 34 }; + int numDecisions = sizeof(decisions)/sizeof(int); - BinaryenExpressionRef full[numDecisions + 1]; // write out all the decisions, - // then the body of the function + BinaryenExpressionRef full[numDecisions + 1]; // write out all the decisions, then the body of the function { int i; for (i = 0; i < numDecisions; i++) { - full[i] = - BinaryenStore(module, - 4, - 0, - 0, - BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), - BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), - BinaryenTypeInt32()); + full[i] = BinaryenStore(module, + 4, 0, 0, + BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), + BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), + BinaryenTypeInt32() + ); } } full[numDecisions] = body; - BinaryenExpressionRef all = - BinaryenBlock(module, NULL, full, numDecisions + 1, BinaryenTypeAuto()); + BinaryenExpressionRef all = BinaryenBlock(module, NULL, full, numDecisions + 1, BinaryenTypeAuto()); - BinaryenType localTypes[] = {BinaryenTypeInt32(), - BinaryenTypeInt32()}; // state, free-for-label + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; // state, free-for-label BinaryenFunctionRef theMain = BinaryenAddFunction( module, "main", BinaryenTypeNone(), BinaryenTypeNone(), localTypes, 2, all); BinaryenSetStart(module, theMain); // import - BinaryenType iparams[] = {BinaryenTypeInt32()}; + BinaryenType iparams[] = { BinaryenTypeInt32() }; BinaryenAddFunctionImport(module, "print", "spectest", diff -Nru binaryen-108/test/example/relooper-fuzz.txt binaryen-99/test/example/relooper-fuzz.txt --- binaryen-108/test/example/relooper-fuzz.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-fuzz.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) @@ -292,9 +292,9 @@ ) ) (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-merge1.c binaryen-99/test/example/relooper-merge1.c --- binaryen-108/test/example/relooper-merge1.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge1.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,99 +77,100 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b0 = RelooperAddBlockWithSwitch( - relooper, + b0 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } // Separate branch for each. // In this testcase, target blocks have identical contents (print 1), // and branches have no phi codes, and no loops. { - BinaryenIndex indexes[] = {1, 4, 9}; + BinaryenIndex indexes[] = { 1, 4, 9 }; RelooperAddBranchForSwitch(b0, b1, indexes, 3, NULL); } { - BinaryenIndex indexes[] = {3, 6}; + BinaryenIndex indexes[] = { 3, 6 }; RelooperAddBranchForSwitch(b0, b2, indexes, 2, NULL); } { - BinaryenIndex indexes[] = {5, 25, 125}; + BinaryenIndex indexes[] = { 5, 25, 125 }; RelooperAddBranchForSwitch(b0, b3, indexes, 3, NULL); } RelooperAddBranchForSwitch(b0, b4, NULL, 0, NULL); @@ -207,7 +178,7 @@ BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", BinaryenTypeNone(), @@ -226,11 +197,10 @@ BinaryenTypeNone()); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-merge1.txt binaryen-99/test/example/relooper-merge1.txt --- binaryen-108/test/example/relooper-merge1.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge1.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-merge2.c binaryen-99/test/example/relooper-merge2.c --- binaryen-108/test/example/relooper-merge2.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge2.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,122 +77,120 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b0 = RelooperAddBlockWithSwitch( - relooper, + b0 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } // Separate branch for each. // In this testcase, target blocks have identical contents (print 1), // and branches have identical phis. { - BinaryenIndex indexes[] = {1, 4, 9}; - RelooperAddBranchForSwitch( - b0, - b1, - indexes, - 3, - BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(4)))); - } - { - BinaryenIndex indexes[] = {3, 6}; - RelooperAddBranchForSwitch( - b0, - b2, - indexes, - 2, - BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(4)))); - } - { - BinaryenIndex indexes[] = {5, 25, 125}; - RelooperAddBranchForSwitch( - b0, - b3, - indexes, - 3, - BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(4)))); + BinaryenIndex indexes[] = { 1, 4, 9 }; + RelooperAddBranchForSwitch(b0, b1, indexes, 3, + BinaryenDrop(module, + BinaryenConst(module, BinaryenLiteralInt32(4)) + ) + ); + } + { + BinaryenIndex indexes[] = { 3, 6 }; + RelooperAddBranchForSwitch(b0, b2, indexes, 2, + BinaryenDrop(module, + BinaryenConst(module, BinaryenLiteralInt32(4)) + ) + ); + } + { + BinaryenIndex indexes[] = { 5, 25, 125 }; + RelooperAddBranchForSwitch(b0, b3, indexes, 3, + BinaryenDrop(module, + BinaryenConst(module, BinaryenLiteralInt32(4)) + ) + ); } RelooperAddBranchForSwitch(b0, b4, NULL, 0, NULL); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", BinaryenTypeNone(), @@ -244,8 +212,7 @@ BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-merge2.txt binaryen-99/test/example/relooper-merge2.txt --- binaryen-108/test/example/relooper-merge2.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge2.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-merge3.c binaryen-99/test/example/relooper-merge3.c --- binaryen-108/test/example/relooper-merge3.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge3.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,98 +77,99 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b0 = RelooperAddBlockWithSwitch( - relooper, + b0 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(2))}; + BinaryenConst(module, BinaryenLiteralInt32(2)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(3))}; + BinaryenConst(module, BinaryenLiteralInt32(3)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } // Separate branch for each. // In this testcase, two blocks out of 4 can be merged. { - BinaryenIndex indexes[] = {1, 4, 9}; + BinaryenIndex indexes[] = { 1, 4, 9 }; RelooperAddBranchForSwitch(b0, b1, indexes, 3, NULL); } { - BinaryenIndex indexes[] = {3, 6}; + BinaryenIndex indexes[] = { 3, 6 }; RelooperAddBranchForSwitch(b0, b2, indexes, 2, NULL); } { - BinaryenIndex indexes[] = {5}; + BinaryenIndex indexes[] = { 5 }; RelooperAddBranchForSwitch(b0, b3, indexes, 1, NULL); } RelooperAddBranchForSwitch(b0, b4, NULL, 0, NULL); @@ -206,7 +177,7 @@ BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", BinaryenTypeNone(), @@ -228,8 +199,7 @@ BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-merge3.txt binaryen-99/test/example/relooper-merge3.txt --- binaryen-108/test/example/relooper-merge3.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge3.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-merge4.c binaryen-99/test/example/relooper-merge4.c --- binaryen-108/test/example/relooper-merge4.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge4.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,98 +77,99 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b0 = RelooperAddBlockWithSwitch( - relooper, + b0 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(2))}; + BinaryenConst(module, BinaryenLiteralInt32(2)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(3))}; + BinaryenConst(module, BinaryenLiteralInt32(3)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } // Separate branch for each. // In this testcase, two blocks out of 4 can be merged. { - BinaryenIndex indexes[] = {1, 4, 9}; + BinaryenIndex indexes[] = { 1, 4, 9 }; RelooperAddBranchForSwitch(b0, b4, indexes, 3, NULL); } { - BinaryenIndex indexes[] = {3, 6}; + BinaryenIndex indexes[] = { 3, 6 }; RelooperAddBranchForSwitch(b0, b2, indexes, 2, NULL); } { - BinaryenIndex indexes[] = {5}; + BinaryenIndex indexes[] = { 5 }; RelooperAddBranchForSwitch(b0, b3, indexes, 1, NULL); } RelooperAddBranchForSwitch(b0, b1, NULL, 0, NULL); @@ -206,7 +177,7 @@ BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", BinaryenTypeNone(), @@ -228,8 +199,7 @@ BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-merge4.txt binaryen-99/test/example/relooper-merge4.txt --- binaryen-108/test/example/relooper-merge4.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge4.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-merge5.c binaryen-99/test/example/relooper-merge5.c --- binaryen-108/test/example/relooper-merge5.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge5.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,106 +77,107 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b0 = RelooperAddBlockWithSwitch( - relooper, + b0 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(2))}; + BinaryenConst(module, BinaryenLiteralInt32(2)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(3))}; + BinaryenConst(module, BinaryenLiteralInt32(3)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } // Separate branch for each. // In this testcase, two blocks out of 4 can be merged. RelooperAddBranchForSwitch(b0, b1, NULL, 0, NULL); { - BinaryenIndex indexes[] = {1, 4, 9}; + BinaryenIndex indexes[] = { 1, 4, 9 }; RelooperAddBranchForSwitch(b0, b4, indexes, 3, NULL); } { - BinaryenIndex indexes[] = {3, 6}; + BinaryenIndex indexes[] = { 3, 6 }; RelooperAddBranchForSwitch(b0, b2, indexes, 2, NULL); } { - BinaryenIndex indexes[] = {5}; + BinaryenIndex indexes[] = { 5 }; RelooperAddBranchForSwitch(b0, b3, indexes, 1, NULL); } BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", BinaryenTypeNone(), @@ -228,8 +199,7 @@ BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-merge5.txt binaryen-99/test/example/relooper-merge5.txt --- binaryen-108/test/example/relooper-merge5.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge5.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/relooper-merge6.c binaryen-99/test/example/relooper-merge6.c --- binaryen-108/test/example/relooper-merge6.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge6.c 2021-01-07 20:01:06.000000000 +0000 @@ -12,89 +12,59 @@ // check() // if the end, halt - BinaryenExpressionRef halter = BinaryenIf( - module, - BinaryenBinary( - module, + BinaryenExpressionRef halter = BinaryenIf(module, + BinaryenBinary(module, BinaryenGeUInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * 12)) // jumps of 4 bytes - ), + ), BinaryenUnreachable(module), - NULL); + NULL + ); // increment index - BinaryenExpressionRef incer = BinaryenStore( - module, - 4, - 0, - 0, + BinaryenExpressionRef incer = BinaryenStore(module, + 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, - BinaryenAddInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), - BinaryenTypeInt32()); + BinaryenConst(module, BinaryenLiteralInt32(4)) + ), + BinaryenTypeInt32() + ); // optionally, print the return value - BinaryenExpressionRef args[] = {BinaryenBinary( - module, - BinaryenSubInt32(), - BinaryenConst(module, BinaryenLiteralInt32(0)), - BinaryenLoad( - module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), + BinaryenExpressionRef args[] = { + BinaryenBinary(module, + BinaryenSubInt32(), + BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))))}; + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ) + ) + }; BinaryenExpressionRef debugger; - if (1) - debugger = BinaryenCall(module, "print", args, 1, BinaryenTypeNone()); - else - debugger = BinaryenNop(module); + if (1) debugger = BinaryenCall(module, "print", args, 1, + BinaryenTypeNone()); + else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 - BinaryenExpressionRef returner = - BinaryenLoad(module, - 4, - 0, - 4, - 0, - BinaryenTypeInt32(), - BinaryenLoad(module, - 4, - 0, - 0, - 0, - BinaryenTypeInt32(), - BinaryenConst(module, BinaryenLiteralInt32(4)))); - BinaryenExpressionRef checkBodyList[] = {halter, incer, debugger, returner}; - BinaryenExpressionRef checkBody = - BinaryenBlock(module, - NULL, - checkBodyList, - sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), - BinaryenTypeInt32()); + BinaryenExpressionRef returner = BinaryenLoad(module, + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))) + ); + BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, + returner }; + BinaryenExpressionRef checkBody = BinaryenBlock(module, + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() + ); BinaryenAddFunction(module, "check", BinaryenTypeNone(), @@ -107,109 +77,98 @@ RelooperRef relooper = RelooperCreate(module); + RelooperBlockRef b0; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(0))}; + BinaryenConst(module, BinaryenLiteralInt32(0)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b0 = RelooperAddBlockWithSwitch( - relooper, + b0 = RelooperAddBlockWithSwitch(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, - BinaryenRemUInt32(), - BinaryenLocalGet(module, 0, BinaryenTypeInt32()), - BinaryenConst(module, BinaryenLiteralInt32(1)))); + BinaryenRemUInt32(), + BinaryenLocalGet(module, 0, BinaryenTypeInt32()), + BinaryenConst(module, BinaryenLiteralInt32(1)) + ) + ); + } RelooperBlockRef b1; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b1 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b1 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b2; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; + + b2 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); - b2 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b3; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b3 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b3 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } RelooperBlockRef b4; { BinaryenExpressionRef args[] = { - BinaryenConst(module, BinaryenLiteralInt32(1))}; + BinaryenConst(module, BinaryenLiteralInt32(1)) + }; BinaryenExpressionRef list[] = { BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), - BinaryenLocalSet( - module, - 0, - BinaryenCall(module, "check", NULL, 0, BinaryenTypeInt32()))}; + BinaryenLocalSet(module, 0, BinaryenCall(module, "check", NULL, 0, + BinaryenTypeInt32())) + }; - b4 = RelooperAddBlock( - relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); + b4 = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); } // Separate branch for each. // In this testcase, we can merge multiple consecutive blocks with phis. - RelooperAddBranch( - b0, - b1, - NULL, - BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(10)))); - RelooperAddBranch( - b1, - b2, - NULL, - BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(11)))); + RelooperAddBranch(b0, b1, NULL, BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(10)))); + RelooperAddBranch(b1, b2, NULL, BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(11)))); RelooperAddBranch(b2, b3, NULL, NULL); - RelooperAddBranch( - b3, - b4, - NULL, - BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(12)))); + RelooperAddBranch(b3, b4, NULL, BinaryenDrop(module, BinaryenConst(module, BinaryenLiteralInt32(12)))); BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); // locals: state, free-for-label - BinaryenType localTypes[] = {BinaryenTypeInt32(), BinaryenTypeInt32()}; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", BinaryenTypeNone(), @@ -231,8 +190,7 @@ BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, NULL, 0, 0); // optionally, optimize - if (0) - BinaryenModuleOptimize(module); + if (0) BinaryenModuleOptimize(module); assert(BinaryenModuleValidate(module)); diff -Nru binaryen-108/test/example/relooper-merge6.txt binaryen-99/test/example/relooper-merge6.txt --- binaryen-108/test/example/relooper-merge6.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/relooper-merge6.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "spectest" "print" (func $print (param i32))) (memory $0 1 1) (export "mem" (memory $0)) diff -Nru binaryen-108/test/example/small_set.cpp binaryen-99/test/example/small_set.cpp --- binaryen-108/test/example/small_set.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/small_set.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -#include -#include -#include -#include - -#include "support/small_set.h" - -using namespace wasm; - -template -void assertContents(T& t, const std::vector& expectedContents) { - assert(t.size() == expectedContents.size()); - for (auto item : expectedContents) { - assert(t.count(item) == 1); - } - // Also test this using an iterator and a const iterator to also get - // coverage there. - for (auto& item : t) { - assert(std::find(expectedContents.begin(), expectedContents.end(), item) != - expectedContents.end()); - } - for (const auto& item : t) { - assert(std::find(expectedContents.begin(), expectedContents.end(), item) != - expectedContents.end()); - } -} - -template void testAPI() { - { - T t; - - // build up with no duplicates - assert(t.empty()); - assert(t.size() == 0); - t.insert(1); - assertContents(t, {1}); - assert(!t.empty()); - assert(t.size() == 1); - t.insert(2); - assertContents(t, {1, 2}); - assert(!t.empty()); - assert(t.size() == 2); - t.insert(3); - assertContents(t, {1, 2, 3}); - assert(!t.empty()); - - // unwind - assert(t.size() == 3); - t.erase(3); - assertContents(t, {1, 2}); - assert(t.size() == 2); - t.erase(2); - assertContents(t, {1}); - assert(t.size() == 1); - t.erase(1); - assertContents(t, {}); - assert(t.size() == 0); - assert(t.empty()); - } - { - T t; - - // build up with duplicates - t.insert(1); - t.insert(2); - t.insert(2); - t.insert(3); - assertContents(t, {1, 2, 3}); - assert(t.size() == 3); - - // unwind by erasing (in the opposite direction from before) - assert(t.count(1) == 1); - assert(t.count(2) == 1); - assert(t.count(3) == 1); - assert(t.count(1337) == 0); - - t.erase(1); - assert(t.count(1) == 0); - - assert(t.size() == 2); - - assert(t.count(2) == 1); - t.erase(2); - assert(t.count(2) == 0); - - assert(t.size() == 1); - - assert(t.count(3) == 1); - t.erase(3); - - assert(t.count(1) == 0); - assert(t.count(2) == 0); - assert(t.count(3) == 0); - assert(t.count(1337) == 0); - - assert(t.size() == 0); - } - { - T t; - - // build up - t.insert(1); - t.insert(2); - t.insert(3); - - // unwind by clearing - t.clear(); - assert(t.size() == 0); - assert(t.empty()); - } - { - T t, u; - // comparisons - assert(t == u); - t.insert(1); - assert(t != u); - u.insert(1); - assert(t == u); - u.erase(1); - assert(t != u); - u.insert(2); - assert(t != u); - } - { - T t, u; - // comparisons should ignore the order of insertion - t.insert(1); - t.insert(2); - u.insert(2); - u.insert(1); - assert(t == u); - } - { - T t, u; - // comparisons should ignore the mode: in a SmallSet<1>, a set of size 1 - // can be either fixed - if we just grew it to size 1 - or flexible - if we - // grew it enough to be flexible, then shrank it back (as it only becomes - // fixed at size 0). - t.insert(1); - - u.insert(1); - u.insert(2); - - // one extra item in u - assert(t != u); - assert(u != t); - - // remove the extra item - u.erase(2); - - assert(t == u); - assert(u == t); - } - { - T t, u; - // as above, but for size 2, and don't erase the last item added - t.insert(1); - t.insert(2); - - u.insert(3); - u.insert(2); - u.insert(1); - - // one extra item in u - assert(t != u); - assert(u != t); - - // remove the extra item - u.erase(3); - - assert(t == u); - assert(u == t); - } -} - -template void testInternals() { - { - T s; - // Start out using fixed storage. - assert(s.TEST_ONLY_NEVER_USE_usingFixed()); - // Adding one item still keeps us using fixed storage, as that is the exact - // amount we have in fact. - s.insert(0); - assert(s.TEST_ONLY_NEVER_USE_usingFixed()); - // Adding one more item forces us to use flexible storage. - s.insert(1); - assert(!s.TEST_ONLY_NEVER_USE_usingFixed()); - // Removing an item returns us to size 1, *but we keep using flexible - // storage*. We do not ping-pong between flexible and fixed; once flexible, - // we stay that way. - s.erase(0); - assert(!s.TEST_ONLY_NEVER_USE_usingFixed()); - // However, removing all items does return us to using fixed storage, should - // we ever insert again. - s.erase(1); - assert(s.empty()); - assert(s.TEST_ONLY_NEVER_USE_usingFixed()); - // And once more we can add an additional item while remaining fixed. - s.insert(10); - assert(s.TEST_ONLY_NEVER_USE_usingFixed()); - } -} - -int main() { - testAPI>(); - testAPI>(); - testAPI>(); - testAPI>(); - testAPI>(); - - testAPI>(); - testAPI>(); - testAPI>(); - testAPI>(); - testAPI>(); - - testInternals>(); - testInternals>(); - - std::cout << "ok.\n"; -} diff -Nru binaryen-108/test/example/small_set.txt binaryen-99/test/example/small_set.txt --- binaryen-108/test/example/small_set.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/small_set.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -ok. diff -Nru binaryen-108/test/example/small_vector.cpp binaryen-99/test/example/small_vector.cpp --- binaryen-108/test/example/small_vector.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/small_vector.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,11 +1,12 @@ -#include #include +#include #include "support/small_vector.h" using namespace wasm; -template void test(size_t N) { +template +void test() { { T t; // build up @@ -55,23 +56,13 @@ u.push_back(2); assert(t != u); } - { - // Test reserve/capacity. - T t; - - // Capacity begins at the size of the fixed storage. - assert(t.capacity() == N); - - // Reserving more increases the capacity (but how much is impl-defined). - t.reserve(t.capacity() + 100); - assert(t.capacity() >= N + 100); - } } int main() { - test>(0); - test>(1); - test>(2); - test>(10); + test>(); + test>(); + test>(); + test>(); std::cout << "ok.\n"; } + diff -Nru binaryen-108/test/example/sparse_square_matrix.cpp binaryen-99/test/example/sparse_square_matrix.cpp --- binaryen-108/test/example/sparse_square_matrix.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/sparse_square_matrix.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -#include - -#include "support/sparse_square_matrix.h" - -int main() { - sparse_square_matrix m; - - // New matrix should initialize to 0x0 size. - assert(m.width() == 0); - - // Recreating should resize the matrix. - m.recreate(100); - assert(m.width() == 100); - - // Small matrices should use dense storage. - assert(m.usingDenseStorage()); - - // Setting and getting element values in dense storage should work. - for (int y = 0; y < 100; ++y) - for (int x = 0; x < 100; ++x) - m.set(y, x, y * 100 + x); - for (int y = 0; y < 100; ++y) - for (int x = 0; x < 100; ++x) - assert(m.get(y, x) == y * 100 + x); - - // Recreating should clear the matrix elements to zero, - // even if recreating to same size as before. - assert(m.width() == 100); - m.recreate(100); - for (int y = 0; y < 100; ++y) - for (int x = 0; x < 100; ++x) - assert(m.get(y, x) == 0); - - // Large matrices should use sparse storage. - m.recreate(m.DenseLimit); - assert(!m.usingDenseStorage()); - - // Setting and getting element values in sparse storage should work. - for (int y = 0; y < m.DenseLimit; y += 128) - for (int x = 0; x < m.DenseLimit; x += 128) - m.set(y, x, y * m.DenseLimit + x); - for (int y = 0; y < m.DenseLimit; y += 128) - for (int x = 0; x < m.DenseLimit; x += 128) - assert(m.get(y, x) == y * m.DenseLimit + x); - - // Recreating matrix in sparse mode should reset values in sparse - // storage to zero. - m.recreate(m.DenseLimit + 1); - for (int y = 0; y < m.width(); y += 128) - for (int x = 0; x < m.width(); x += 128) - assert(m.get(y, x) == 0); - - std::cout << "ok.\n"; -} diff -Nru binaryen-108/test/example/sparse_square_matrix.txt binaryen-99/test/example/sparse_square_matrix.txt --- binaryen-108/test/example/sparse_square_matrix.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/sparse_square_matrix.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -ok. diff -Nru binaryen-108/test/example/stack-utils.cpp binaryen-99/test/example/stack-utils.cpp --- binaryen-108/test/example/stack-utils.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/stack-utils.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -35,38 +35,37 @@ // Typed block auto* block = builder.makeBlock({builder.makeUnreachable()}, Type::f32); assert(StackSignature(block) == - (StackSignature{Type::none, Type::f32, StackSignature::Fixed})); + (StackSignature{Type::none, Type::f32, false})); // Unreachable block auto* unreachable = builder.makeBlock({builder.makeUnreachable()}, Type::unreachable); assert(StackSignature(unreachable) == - (StackSignature{Type::none, Type::none, StackSignature::Polymorphic})); + (StackSignature{Type::none, Type::none, true})); { // Typed loop auto* loop = builder.makeLoop("loop", unreachable, Type::f32); assert(StackSignature(loop) == - (StackSignature{Type::none, Type::f32, StackSignature::Fixed})); + (StackSignature{Type::none, Type::f32, false})); } { // Unreachable loop auto* loop = builder.makeLoop("loop", unreachable, Type::unreachable); - assert( - StackSignature(loop) == - (StackSignature{Type::none, Type::none, StackSignature::Polymorphic})); + assert(StackSignature(loop) == + (StackSignature{Type::none, Type::none, true})); } { // If (no else) auto* if_ = builder.makeIf( builder.makePop(Type::i32), unreachable, nullptr, Type::none); assert(StackSignature(if_) == - (StackSignature{Type::i32, Type::none, StackSignature::Fixed})); + (StackSignature{Type::i32, Type::none, false})); } { // If (with else) auto* if_ = builder.makeIf(builder.makePop(Type::i32), block, block, Type::f32); assert(StackSignature(if_) == - (StackSignature{Type::i32, Type::f32, StackSignature::Fixed})); + (StackSignature{Type::i32, Type::f32, false})); } { // Call @@ -74,9 +73,9 @@ builder.makeCall("foo", {builder.makePop(Type::i32), builder.makePop(Type::f32)}, {Type::i64, Type::f64}); - assert(StackSignature(call) == (StackSignature{{Type::i32, Type::f32}, - {Type::i64, Type::f64}, - StackSignature::Fixed})); + assert( + StackSignature(call) == + (StackSignature{{Type::i32, Type::f32}, {Type::i64, Type::f64}, false})); } { // Return Call @@ -84,24 +83,21 @@ builder.makeCall("bar", {builder.makePop(Type::i32), builder.makePop(Type::f32)}, Type::unreachable, - StackSignature::Polymorphic); + true); assert(StackSignature(call) == - (StackSignature{ - {Type::i32, Type::f32}, Type::none, StackSignature::Polymorphic})); + (StackSignature{{Type::i32, Type::f32}, Type::none, true})); } { // Return auto* ret = builder.makeReturn(builder.makePop(Type::i32)); - assert( - StackSignature(ret) == - (StackSignature{Type::i32, Type::none, StackSignature::Polymorphic})); + assert(StackSignature(ret) == + (StackSignature{Type::i32, Type::none, true})); } { // Multivalue return auto* ret = builder.makeReturn(builder.makePop({Type::i32, Type::f32})); assert(StackSignature(ret) == - (StackSignature{ - {Type::i32, Type::f32}, Type::none, StackSignature::Polymorphic})); + (StackSignature{{Type::i32, Type::f32}, Type::none, true})); } } @@ -109,360 +105,195 @@ std::cout << ";; Test stack signature composition\n"; // No unreachables { - StackSignature a{Type::none, {Type::f32, Type::i32}, StackSignature::Fixed}; - StackSignature b{{Type::f32, Type::i32}, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, {Type::f32, Type::i32}, false}; + StackSignature b{{Type::f32, Type::i32}, Type::none, false}; assert(a.composes(b)); - assert(a + b == - (StackSignature{Type::none, Type::none, StackSignature::Fixed})); + assert(a + b == (StackSignature{Type::none, Type::none, false})); } { - StackSignature a{Type::none, Type::i32, StackSignature::Fixed}; - StackSignature b{{Type::f32, Type::i32}, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, Type::i32, false}; + StackSignature b{{Type::f32, Type::i32}, Type::none, false}; assert(a.composes(b)); - assert(a + b == - StackSignature(Type::f32, Type::none, StackSignature::Fixed)); + assert(a + b == StackSignature(Type::f32, Type::none, false)); } { - StackSignature a{Type::none, {Type::f32, Type::i32}, StackSignature::Fixed}; - StackSignature b{Type::i32, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, {Type::f32, Type::i32}, false}; + StackSignature b{Type::i32, Type::none, false}; assert(a.composes(b)); - assert(a + b == - (StackSignature{Type::none, Type::f32, StackSignature::Fixed})); + assert(a + b == (StackSignature{Type::none, Type::f32, false})); } { - StackSignature a{Type::none, Type::f32, StackSignature::Fixed}; - StackSignature b{{Type::f32, Type::i32}, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, Type::f32, false}; + StackSignature b{{Type::f32, Type::i32}, Type::none, false}; assert(!a.composes(b)); } { - StackSignature a{Type::none, {Type::f32, Type::i32}, StackSignature::Fixed}; - StackSignature b{Type::f32, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, {Type::f32, Type::i32}, false}; + StackSignature b{Type::f32, Type::none, false}; assert(!a.composes(b)); } // First unreachable { - StackSignature a{ - Type::none, {Type::f32, Type::i32}, StackSignature::Polymorphic}; - StackSignature b{{Type::f32, Type::i32}, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, {Type::f32, Type::i32}, true}; + StackSignature b{{Type::f32, Type::i32}, Type::none, false}; assert(a.composes(b)); - assert(a + b == (StackSignature{ - Type::none, Type::none, StackSignature::Polymorphic})); + assert(a + b == (StackSignature{Type::none, Type::none, true})); } { - StackSignature a{Type::none, Type::i32, StackSignature::Polymorphic}; - StackSignature b{{Type::f32, Type::i32}, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, Type::i32, true}; + StackSignature b{{Type::f32, Type::i32}, Type::none, false}; assert(a.composes(b)); - assert(a + b == - StackSignature(Type::none, Type::none, StackSignature::Polymorphic)); + assert(a + b == StackSignature(Type::none, Type::none, true)); } { - StackSignature a{ - Type::none, {Type::f32, Type::i32}, StackSignature::Polymorphic}; - StackSignature b{Type::i32, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, {Type::f32, Type::i32}, true}; + StackSignature b{Type::i32, Type::none, false}; assert(a.composes(b)); - assert(a + b == (StackSignature{ - Type::none, Type::f32, StackSignature::Polymorphic})); + assert(a + b == (StackSignature{Type::none, Type::f32, true})); } { - StackSignature a{Type::none, Type::f32, StackSignature::Polymorphic}; - StackSignature b{{Type::f32, Type::i32}, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, Type::f32, true}; + StackSignature b{{Type::f32, Type::i32}, Type::none, false}; assert(!a.composes(b)); } { - StackSignature a{ - Type::none, {Type::f32, Type::i32}, StackSignature::Polymorphic}; - StackSignature b{Type::f32, Type::none, StackSignature::Fixed}; + StackSignature a{Type::none, {Type::f32, Type::i32}, true}; + StackSignature b{Type::f32, Type::none, false}; assert(!a.composes(b)); } // Second unreachable { - StackSignature a{Type::none, {Type::f32, Type::i32}, StackSignature::Fixed}; - StackSignature b{ - {Type::f32, Type::i32}, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, {Type::f32, Type::i32}, false}; + StackSignature b{{Type::f32, Type::i32}, Type::none, true}; assert(a.composes(b)); - assert(a + b == (StackSignature{ - Type::none, Type::none, StackSignature::Polymorphic})); + assert(a + b == (StackSignature{Type::none, Type::none, true})); } { - StackSignature a{Type::none, Type::i32, StackSignature::Fixed}; - StackSignature b{ - {Type::f32, Type::i32}, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, Type::i32, false}; + StackSignature b{{Type::f32, Type::i32}, Type::none, true}; assert(a.composes(b)); - assert(a + b == - StackSignature(Type::f32, Type::none, StackSignature::Polymorphic)); + assert(a + b == StackSignature(Type::f32, Type::none, true)); } { - StackSignature a{Type::none, {Type::f32, Type::i32}, StackSignature::Fixed}; - StackSignature b{Type::i32, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, {Type::f32, Type::i32}, false}; + StackSignature b{Type::i32, Type::none, true}; assert(a.composes(b)); - assert(a + b == (StackSignature{ - Type::none, Type::none, StackSignature::Polymorphic})); + assert(a + b == (StackSignature{Type::none, Type::none, true})); } { - StackSignature a{Type::none, Type::f32, StackSignature::Fixed}; - StackSignature b{ - {Type::f32, Type::i32}, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, Type::f32, false}; + StackSignature b{{Type::f32, Type::i32}, Type::none, true}; assert(!a.composes(b)); } { - StackSignature a{Type::none, {Type::f32, Type::i32}, StackSignature::Fixed}; - StackSignature b{Type::f32, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, {Type::f32, Type::i32}, false}; + StackSignature b{Type::f32, Type::none, true}; assert(!a.composes(b)); } // Both unreachable { - StackSignature a{ - Type::none, {Type::f32, Type::i32}, StackSignature::Polymorphic}; - StackSignature b{ - {Type::f32, Type::i32}, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, {Type::f32, Type::i32}, true}; + StackSignature b{{Type::f32, Type::i32}, Type::none, true}; assert(a.composes(b)); - assert(a + b == (StackSignature{ - Type::none, Type::none, StackSignature::Polymorphic})); + assert(a + b == (StackSignature{Type::none, Type::none, true})); } { - StackSignature a{Type::none, Type::i32, StackSignature::Polymorphic}; - StackSignature b{ - {Type::f32, Type::i32}, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, Type::i32, true}; + StackSignature b{{Type::f32, Type::i32}, Type::none, true}; assert(a.composes(b)); - assert(a + b == - StackSignature(Type::none, Type::none, StackSignature::Polymorphic)); + assert(a + b == StackSignature(Type::none, Type::none, true)); } { - StackSignature a{ - Type::none, {Type::f32, Type::i32}, StackSignature::Polymorphic}; - StackSignature b{Type::i32, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, {Type::f32, Type::i32}, true}; + StackSignature b{Type::i32, Type::none, true}; assert(a.composes(b)); - assert(a + b == (StackSignature{ - Type::none, Type::none, StackSignature::Polymorphic})); + assert(a + b == (StackSignature{Type::none, Type::none, true})); } { - StackSignature a{Type::none, Type::f32, StackSignature::Polymorphic}; - StackSignature b{ - {Type::f32, Type::i32}, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, Type::f32, true}; + StackSignature b{{Type::f32, Type::i32}, Type::none, true}; assert(!a.composes(b)); } { - StackSignature a{ - Type::none, {Type::f32, Type::i32}, StackSignature::Polymorphic}; - StackSignature b{Type::f32, Type::none, StackSignature::Polymorphic}; + StackSignature a{Type::none, {Type::f32, Type::i32}, true}; + StackSignature b{Type::f32, Type::none, true}; assert(!a.composes(b)); } } -void test_signature_subtype() { - std::cout << ";; Test stack signature subtyping\n"; - // Differences in unreachability only - { - StackSignature a(Type::none, Type::none, StackSignature::Polymorphic); - StackSignature b(Type::none, Type::none, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - assert(!StackSignature::isSubType(b, a)); - } - // Covariance of results - { - StackSignature a(Type::none, Type::funcref, StackSignature::Fixed); - StackSignature b(Type::none, Type::anyref, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - assert(!StackSignature::isSubType(b, a)); - } - // Contravariance of params - { - StackSignature a(Type::anyref, Type::none, StackSignature::Fixed); - StackSignature b(Type::funcref, Type::none, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - assert(!StackSignature::isSubType(b, a)); - } - // First not unreachable - { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b(Type::i32, Type::f32, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - } +void test_signature_satisfaction() { + std::cout << ";; Test stack signature satisfaction\n"; + // No unreachable { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b( - {Type::i64, Type::i32}, {Type::i64, Type::f32}, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); + StackSignature a{Type::i32, Type::f32, false}; + Signature b(Type::i32, Type::f32); + assert(a.satisfies(b)); } { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b({Type::i64, Type::i32}, - {Type::i64, Type::i64, Type::f32}, - StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); + StackSignature a{Type::i32, Type::f32, false}; + Signature b({Type::i64, Type::i32}, {Type::i64, Type::f32}); + assert(a.satisfies(b)); } { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b( - {Type::i64, Type::i32}, {Type::f64, Type::f32}, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b(Type::none, Type::f32, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b(Type::i32, Type::none, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Fixed); - StackSignature b(Type::f32, Type::i32, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } - // First unreachable - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b(Type::i32, Type::f32, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b( - {Type::i64, Type::i32}, {Type::i64, Type::f32}, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b({Type::i64, Type::i32}, - {Type::i64, Type::i64, Type::f32}, - StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b( - {Type::i64, Type::i32}, {Type::f64, Type::f32}, StackSignature::Fixed); - assert(StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b(Type::none, Type::f32, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b(Type::i32, Type::none, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } - { - StackSignature a(Type::i32, Type::f32, StackSignature::Polymorphic); - StackSignature b(Type::f32, Type::i32, StackSignature::Fixed); - assert(!StackSignature::isSubType(a, b)); - } -} - -void test_signature_lub() { - std::cout << ";; Test stack signature lub\n"; - { - StackSignature a{Type::none, Type::none, StackSignature::Fixed}; - StackSignature b{Type::none, Type::none, StackSignature::Fixed}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::none, Type::none, StackSignature::Fixed})); - } - { - StackSignature a{Type::none, Type::none, StackSignature::Polymorphic}; - StackSignature b{Type::none, Type::none, StackSignature::Fixed}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::none, Type::none, StackSignature::Fixed})); - } - { - StackSignature a{Type::none, Type::none, StackSignature::Fixed}; - StackSignature b{Type::none, Type::none, StackSignature::Polymorphic}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::none, Type::none, StackSignature::Fixed})); - } - { - StackSignature a{Type::i32, Type::none, StackSignature::Polymorphic}; - StackSignature b{Type::none, Type::i32, StackSignature::Polymorphic}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::i32, Type::i32, StackSignature::Polymorphic})); - } - { - StackSignature a{Type::none, Type::i32, StackSignature::Polymorphic}; - StackSignature b{Type::i32, Type::none, StackSignature::Polymorphic}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::i32, Type::i32, StackSignature::Polymorphic})); - } - { - StackSignature a{Type::none, Type::anyref, StackSignature::Polymorphic}; - StackSignature b{Type::none, Type::funcref, StackSignature::Polymorphic}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert( - StackSignature::getLeastUpperBound(a, b) == - (StackSignature{Type::none, Type::anyref, StackSignature::Polymorphic})); + StackSignature a{Type::i32, Type::f32, false}; + Signature b({Type::i64, Type::i32}, {Type::i64, Type::i64, Type::f32}); + assert(!a.satisfies(b)); } { - StackSignature a{Type::anyref, Type::none, StackSignature::Polymorphic}; - StackSignature b{Type::funcref, Type::none, StackSignature::Polymorphic}; - // assert(StackSignature::haveLeastUpperBound(a, b)); - // assert(StackSignature::getLeastUpperBound(a, b) == - // (StackSignature{Type::funcref, Type::none, - // StackSignature::Polymorphic})); + StackSignature a{Type::i32, Type::f32, false}; + Signature b({Type::i64, Type::i32}, {Type::f64, Type::f32}); + assert(!a.satisfies(b)); } { - StackSignature a{ - {Type::i32, Type::funcref}, Type::funcref, StackSignature::Polymorphic}; - StackSignature b{ - Type::funcref, {Type::f32, Type::anyref}, StackSignature::Polymorphic}; - assert(StackSignature::haveLeastUpperBound(a, b)); - assert(StackSignature::getLeastUpperBound(a, b) == - (StackSignature{{Type::i32, Type::funcref}, - {Type::f32, Type::anyref}, - StackSignature::Polymorphic})); + StackSignature a{Type::i32, Type::f32, false}; + Signature b(Type::none, Type::f32); + assert(!a.satisfies(b)); } - // No LUB { - StackSignature a(Type::none, Type::i32, StackSignature::Fixed); - StackSignature b(Type::none, Type::f32, StackSignature::Fixed); - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, false}; + Signature b(Type::i32, Type::none); + assert(!a.satisfies(b)); } { - StackSignature a(Type::none, Type::i32, StackSignature::Polymorphic); - StackSignature b(Type::none, Type::f32, StackSignature::Polymorphic); - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, false}; + Signature b(Type::f32, Type::i32); + assert(!a.satisfies(b)); } + // With unreachable { - StackSignature a(Type::i32, Type::none, StackSignature::Fixed); - StackSignature b(Type::f32, Type::none, StackSignature::Fixed); - // assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b(Type::i32, Type::f32); + assert(a.satisfies(b)); } { - StackSignature a(Type::i32, Type::none, StackSignature::Polymorphic); - StackSignature b(Type::f32, Type::none, StackSignature::Polymorphic); - // assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b({Type::i64, Type::i32}, {Type::i64, Type::f32}); + assert(a.satisfies(b)); } { - StackSignature a(Type::none, Type::none, StackSignature::Fixed); - StackSignature b(Type::none, Type::i32, StackSignature::Polymorphic); - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b({Type::i64, Type::i32}, {Type::i64, Type::i64, Type::f32}); + assert(a.satisfies(b)); } { - StackSignature a(Type::none, Type::none, StackSignature::Fixed); - StackSignature b(Type::i32, Type::none, StackSignature::Polymorphic); - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b({Type::i64, Type::i32}, {Type::f64, Type::f32}); + assert(a.satisfies(b)); } { - StackSignature a{Type::none, Type::i32, StackSignature::Fixed}; - StackSignature b{Type::i32, Type::none, StackSignature::Fixed}; - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b(Type::none, Type::f32); + assert(!a.satisfies(b)); } { - StackSignature a{Type::none, Type::i32, StackSignature::Polymorphic}; - StackSignature b{Type::i32, Type::none, StackSignature::Fixed}; - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b(Type::i32, Type::none); + assert(!a.satisfies(b)); } { - StackSignature a{Type::none, Type::i32, StackSignature::Fixed}; - StackSignature b{Type::i32, Type::none, StackSignature::Polymorphic}; - assert(!StackSignature::haveLeastUpperBound(a, b)); + StackSignature a{Type::i32, Type::f32, true}; + Signature b(Type::f32, Type::i32); + assert(!a.satisfies(b)); } } @@ -595,7 +426,7 @@ assert(flow.getSignature(ret) == (StackSignature{{Type::i32, Type::i64, Type::f32}, {Type::i64, Type::f64, Type::i32}, - StackSignature::Polymorphic})); + true})); assert(flow.getSignature(quux) == StackSignature(quux)); } } @@ -604,7 +435,6 @@ test_remove_nops(); test_stack_signatures(); test_signature_composition(); - test_signature_subtype(); - test_signature_lub(); + test_signature_satisfaction(); test_stack_flow(); } diff -Nru binaryen-108/test/example/stack-utils.txt binaryen-99/test/example/stack-utils.txt --- binaryen-108/test/example/stack-utils.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/stack-utils.txt 2021-01-07 20:01:06.000000000 +0000 @@ -13,6 +13,5 @@ ) ;; Test stack signatures ;; Test stack signature composition -;; Test stack signature subtyping -;; Test stack signature lub +;; Test stack signature satisfaction ;; Test stack flow diff -Nru binaryen-108/test/example/type-builder.cpp binaryen-99/test/example/type-builder.cpp --- binaryen-108/test/example/type-builder.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/type-builder.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,38 +1,95 @@ #include #include -#include "wasm-type-printing.h" #include "wasm-type.h" using namespace wasm; +// Construct Signature, Struct, and Array heap types using undefined types. +void test_builder() { + std::cout << ";; Test TypeBuilder\n"; + + // (type $sig (func (param (ref $struct)) (result (ref $array) i32))) + // (type $struct (struct (field (ref null $array) (mut rtt 0 $array)))) + // (type $array (array (mut externref))) + + TypeBuilder builder(3); + + Type refSig = builder.getTempRefType(0, NonNullable); + Type refStruct = builder.getTempRefType(1, NonNullable); + Type refArray = builder.getTempRefType(2, NonNullable); + Type refNullArray = builder.getTempRefType(2, Nullable); + Type rttArray = builder.getTempRttType(2, 0); + Type refNullExt(HeapType::ext, Nullable); + + Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32})); + Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)}); + Array array(Field(refNullExt, Mutable)); + + std::cout << "Before setting heap types:\n"; + std::cout << "(ref $sig) => " << refSig << "\n"; + std::cout << "(ref $struct) => " << refStruct << "\n"; + std::cout << "(ref $array) => " << refArray << "\n"; + std::cout << "(ref null $array) => " << refNullArray << "\n"; + std::cout << "(rtt 0 $array) => " << rttArray << "\n\n"; + + builder.setHeapType(0, sig); + builder.setHeapType(1, struct_); + builder.setHeapType(2, array); + + std::cout << "After setting heap types:\n"; + std::cout << "(ref $sig) => " << refSig << "\n"; + std::cout << "(ref $struct) => " << refStruct << "\n"; + std::cout << "(ref $array) => " << refArray << "\n"; + std::cout << "(ref null $array) => " << refNullArray << "\n"; + std::cout << "(rtt 0 $array) => " << rttArray << "\n\n"; + + std::vector built = builder.build(); + + Type newRefSig = Type(built[0], NonNullable); + Type newRefStruct = Type(built[1], NonNullable); + Type newRefArray = Type(built[2], NonNullable); + Type newRefNullArray = Type(built[2], Nullable); + Type newRttArray = Type(Rtt(0, built[2])); + + assert(refSig != newRefSig); + assert(refStruct != newRefStruct); + assert(refArray != newRefArray); + assert(refNullArray != newRefNullArray); + assert(rttArray != newRttArray); + + std::cout << "After building types:\n"; + std::cout << "(ref $sig) => " << newRefSig << "\n"; + std::cout << "(ref $struct) => " << newRefStruct << "\n"; + std::cout << "(ref $array) => " << newRefArray << "\n"; + std::cout << "(ref null $array) => " << newRefNullArray << "\n"; + std::cout << "(rtt 0 $array) => " << newRttArray << "\n\n"; +} + // Check that the builder works when there are duplicate definitions void test_canonicalization() { std::cout << ";; Test canonicalization\n"; - // (type $struct (struct (field (ref null $sig) (ref null $sig)))) + // (type $struct (struct (field (ref null $sig)))) // (type $sig (func)) HeapType sig = Signature(Type::none, Type::none); - HeapType struct_ = Struct({Field(Type(sig, Nullable), Immutable), - Field(Type(sig, Nullable), Immutable)}); + HeapType struct_ = Struct({Field(Type(sig, Nullable), Immutable)}); TypeBuilder builder(4); - Type tempSigRef1 = builder.getTempRefType(builder[2], Nullable); - Type tempSigRef2 = builder.getTempRefType(builder[3], Nullable); + Type tempSigRef1 = builder.getTempRefType(2, Nullable); + Type tempSigRef2 = builder.getTempRefType(3, Nullable); assert(tempSigRef1 != tempSigRef2); assert(tempSigRef1 != Type(sig, Nullable)); assert(tempSigRef2 != Type(sig, Nullable)); - builder[0] = - Struct({Field(tempSigRef1, Immutable), Field(tempSigRef1, Immutable)}); - builder[1] = - Struct({Field(tempSigRef2, Immutable), Field(tempSigRef2, Immutable)}); - builder[2] = Signature(Type::none, Type::none); - builder[3] = Signature(Type::none, Type::none); + builder.setHeapType(0, Struct({Field(tempSigRef1, Immutable)})); + builder.setHeapType(1, Struct({Field(tempSigRef2, Immutable)})); + builder.setHeapType(2, Signature(Type::none, Type::none)); + builder.setHeapType(3, Signature(Type::none, Type::none)); - std::vector built = *builder.build(); + std::vector built = builder.build(); assert(built[0] == struct_); assert(built[1] == struct_); @@ -40,407 +97,46 @@ assert(built[3] == sig); } -// Check that defined basic HeapTypes are handled correctly. -void test_basic() { - std::cout << ";; Test basic\n"; - - TypeBuilder builder(6); - - Type anyref = builder.getTempRefType(builder[4], Nullable); - Type i31ref = builder.getTempRefType(builder[5], NonNullable); - - builder[0] = Signature(Type::anyref, Type::i31ref); - builder[1] = Signature(anyref, Type::i31ref); - builder[2] = Signature(Type::anyref, i31ref); - builder[3] = Signature(anyref, i31ref); - builder[4] = HeapType::any; - builder[5] = HeapType::i31; - - std::vector built = *builder.build(); - - assert(built[0] == Signature(Type::anyref, Type::i31ref)); - assert(built[1] == built[0]); - assert(built[2] == built[1]); - assert(built[3] == built[2]); - assert(built[4] == HeapType::any); - assert(built[5] == HeapType::i31); -} - void test_recursive() { std::cout << ";; Test recursive types\n"; { // Trivial recursion - std::vector built; - { - TypeBuilder builder(1); - Type temp = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n\n"; - assert(built[0] == built[0].getSignature().results.getHeapType()); - assert(Type(built[0], Nullable) == built[0].getSignature().results); + TypeBuilder builder(1); + Type temp = builder.getTempRefType(0, Nullable); + builder.setHeapType(0, Signature(Type::none, temp)); + // std::vector built = builder.build(); } { // Mutual recursion - std::vector built; - { - TypeBuilder builder(2); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] == built[1]); - } - - { - // A longer chain of recursion - std::vector built; - { - TypeBuilder builder(5); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type temp4 = builder.getTempRefType(builder[4], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp2); - builder[2] = Signature(Type::none, temp3); - builder[3] = Signature(Type::none, temp4); - builder[4] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n"; - std::cout << print(built[2]) << "\n"; - std::cout << print(built[3]) << "\n"; - std::cout << print(built[4]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[2]); - assert(built[2].getSignature().results.getHeapType() == built[3]); - assert(built[3].getSignature().results.getHeapType() == built[4]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[0] == built[1]); - assert(built[1] == built[2]); - assert(built[2] == built[3]); - assert(built[3] == built[4]); - } - - { - // Check canonicalization for non-recursive parents and children of - // recursive HeapTypes. - std::vector built; - { - TypeBuilder builder(6); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type tuple0_2 = builder.getTempTupleType({temp0, temp2}); - Type tuple1_3 = builder.getTempTupleType({temp1, temp3}); - builder[0] = Signature(Type::none, tuple0_2); - builder[1] = Signature(Type::none, tuple1_3); - builder[2] = Signature(); - builder[3] = Signature(); - builder[4] = Signature(Type::none, temp0); - builder[5] = Signature(Type::none, temp1); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n"; - std::cout << print(built[2]) << "\n"; - std::cout << print(built[3]) << "\n"; - std::cout << print(built[4]) << "\n"; - std::cout << print(built[5]) << "\n\n"; - assert(built[0] == built[1]); - assert(built[2] == built[3]); - assert(built[4] == built[5]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[5].getSignature().results.getHeapType() == built[1]); - assert(built[0].getSignature().results == - Type({Type(built[0], Nullable), Type(built[2], Nullable)})); - assert(built[1].getSignature().results == - Type({Type(built[1], Nullable), Type(built[3], Nullable)})); - } - - { - // Folded and unfolded - std::vector built; - { - TypeBuilder builder(2); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp0); - builder[1] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[0]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] == built[1]); - } - - { - // Including a basic heap type - std::vector built; - { - TypeBuilder builder(3); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type anyref = builder.getTempRefType(builder[2], Nullable); - builder[0] = Signature(anyref, temp0); - builder[1] = Signature(anyref, temp0); - builder[2] = HeapType::any; - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[0]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0].getSignature().params == Type::anyref); - assert(built[1].getSignature().params == Type::anyref); - assert(built[0] == built[1]); - assert(built[2] == HeapType::any); - } -} - -void test_lub() { - std::cout << ";; Test LUBs\n"; - - auto LUB = [&](Type a, Type b) { - Type lubAB = Type::getLeastUpperBound(a, b); - Type lubBA = Type::getLeastUpperBound(b, a); - assert(lubAB == lubBA); - if (lubAB == Type::none) { - assert(!Type::hasLeastUpperBound(a, b)); - assert(!Type::hasLeastUpperBound(b, a)); - } else { - assert(Type::hasLeastUpperBound(a, b)); - assert(Type::hasLeastUpperBound(b, a)); - assert(Type::isSubType(a, lubAB)); - assert(Type::isSubType(b, lubAB)); - } - return lubAB; - }; - - { - // Basic Types - for (auto other : {Type::funcref, - Type::anyref, - Type::eqref, - Type::i31ref, - Type::dataref}) { - assert(LUB(Type::anyref, other) == Type::anyref); - } - assert(LUB(Type::eqref, Type::funcref) == Type::anyref); - assert(LUB(Type::i31ref, Type::dataref) == Type(HeapType::eq, NonNullable)); - } - - { - // Nullable and non-nullable references - Type nullable(HeapType::any, Nullable); - Type nonNullable(HeapType::any, NonNullable); - assert(LUB(nullable, nullable) == nullable); - assert(LUB(nullable, nonNullable) == nullable); - assert(LUB(nonNullable, nonNullable) == nonNullable); - } - - { - // Funcref with specific signature - assert(LUB(Type::funcref, Type(Signature(), Nullable)) == Type::funcref); - } - - { - // Incompatible signatures - Type a(Signature(Type::none, Type::anyref), Nullable); - Type b(Signature(Type::anyref, Type::none), Nullable); - assert(LUB(a, b) == Type::funcref); - } - - { - // Signatures incompatible in tuple size - Type a(Signature(Type::none, {Type::anyref, Type::anyref}), Nullable); - Type b(Signature(Type::none, {Type::anyref, Type::anyref, Type::anyref}), - Nullable); - assert(LUB(a, b) == Type::funcref); - } - - // { - // // Covariance of function results - // Type a(Signature(Type::none, {Type::eqref, Type::funcref}), Nullable); - // Type b(Signature(Type::none, {Type::funcref, Type::eqref}), Nullable); - // assert(LUB(a, b) == Type(Signature(Type::none, {Type::anyref, - // Type::anyref}), Nullable)); - // } - - // TODO: Test contravariance in function parameters once that is supported. - - // { - // // Nested signatures - // Type baseA(Signature(Type::none, Type::eqref), Nullable); - // Type baseB(Signature(Type::none, Type::funcref), Nullable); - // Type a(Signature(Type::none, baseA), Nullable); - // Type b(Signature(Type::none, baseB), Nullable); - // Type baseLub(Signature(Type::none, Type::anyref), Nullable); - // Type lub(Signature(Type::none, baseLub), Nullable); - // assert(LUB(a, b) == lub); - // } - - // TODO: Test recursive signatures once signature subtyping is supported. - - { - // Mutable fields are invariant - Type a(Array(Field(Type::eqref, Mutable)), Nullable); - Type b(Array(Field(Type::funcref, Mutable)), Nullable); - assert(LUB(a, b) == Type(HeapType::data, Nullable)); - } - - { - // Immutable fields are covariant - Type a(Array(Field(Type::eqref, Immutable)), Nullable); - Type b(Array(Field(Type::funcref, Immutable)), Nullable); - Type lub(Array(Field(Type::anyref, Immutable)), Nullable); - assert(LUB(a, b) == lub); - } - - { - // Depth subtyping - Type a(Struct({Field(Type::eqref, Immutable)}), Nullable); - Type b(Struct({Field(Type::funcref, Immutable)}), Nullable); - Type lub(Struct({Field(Type::anyref, Immutable)}), Nullable); - assert(LUB(a, b) == lub); - } - - { - // Width subtyping - Type a(Struct({Field(Type::i32, Immutable)}), Nullable); - Type b(Struct({Field(Type::i32, Immutable), Field(Type::i32, Immutable)}), - Nullable); - assert(LUB(a, b) == a); - } - - { - // Width subtyping with different suffixes - Type a(Struct({Field(Type::i32, Immutable), Field(Type::i64, Immutable)}), - Nullable); - Type b(Struct({Field(Type::i32, Immutable), Field(Type::f32, Immutable)}), - Nullable); - Type lub(Struct({Field(Type::i32, Immutable)}), Nullable); - assert(LUB(a, b) == lub); - } - - { - // Width and depth subtyping with different suffixes - Type a(Struct({Field(Type::eqref, Immutable), Field(Type::i64, Immutable)}), - Nullable); - Type b( - Struct({Field(Type::funcref, Immutable), Field(Type::f32, Immutable)}), - Nullable); - Type lub(Struct({Field(Type::anyref, Immutable)}), Nullable); - assert(LUB(a, b) == lub); - } - - { - // No common prefix - Type a( - Struct({Field(Type::i32, Immutable), Field(Type::anyref, Immutable)}), - Nullable); - Type b( - Struct({Field(Type::f32, Immutable), Field(Type::anyref, Immutable)}), - Nullable); - Type lub(Struct(), Nullable); - assert(LUB(a, b) == lub); - } - - { - // Nested structs - Type innerA(Struct({Field(Type::eqref, Immutable)}), Nullable); - Type innerB(Struct({Field(Type::funcref, Immutable)}), Nullable); - Type innerLub(Struct({Field(Type::anyref, Immutable)}), Nullable); - Type a(Struct({Field(innerA, Immutable)}), Nullable); - Type b(Struct({Field(innerB, Immutable)}), Nullable); - Type lub(Struct({Field(innerLub, Immutable)}), Nullable); - assert(LUB(a, b) == lub); - } - - { - // Recursive structs TypeBuilder builder(2); - Type tempA = builder.getTempRefType(builder[0], Nullable); - Type tempB = builder.getTempRefType(builder[1], Nullable); - builder[0] = - Struct({Field(tempB, Immutable), Field(Type::eqref, Immutable)}); - builder[1] = - Struct({Field(tempA, Immutable), Field(Type::funcref, Immutable)}); - auto built = *builder.build(); - Type a(built[0], Nullable); - Type b(built[1], Nullable); - - TypeBuilder lubBuilder(1); - Type tempLub = builder.getTempRefType(lubBuilder[0], Nullable); - lubBuilder[0] = - Struct({Field(tempLub, Immutable), Field(Type::anyref, Immutable)}); - built = *lubBuilder.build(); - Type lub(built[0], Nullable); - - assert(LUB(a, b) == lub); + Type temp0 = builder.getTempRefType(0, Nullable); + Type temp1 = builder.getTempRefType(1, Nullable); + builder.setHeapType(0, Signature(Type::none, temp1)); + builder.setHeapType(1, Signature(Type::none, temp0)); + // std::vector built = builder.build(); } { - // Incompatible Rtts - Type a{Rtt(HeapType::eq)}; - Type b{Rtt(HeapType::func)}; - assert(LUB(a, b) == Type::none); - } - - { - // Rtts with matching depth - Type a(Rtt(42, HeapType::any)); - assert(LUB(a, a) == a); - } - - { - // Rtts with mismatched depth - Type a(Rtt(42, HeapType::any)); - Type b(Rtt(50, HeapType::any)); - Type lub{Rtt(HeapType::any)}; - assert(LUB(a, b) == lub); - } - - { - // Rtts with and without depth - Type a(Rtt(42, HeapType::any)); - Type b{Rtt(HeapType::any)}; - assert(LUB(a, b) == b); - } - - { - // Rtts without depth - Type a{Rtt(HeapType::any)}; - assert(LUB(a, a) == a); + // A longer chain of recursion + TypeBuilder builder(5); + Type temp0 = builder.getTempRefType(0, Nullable); + Type temp1 = builder.getTempRefType(1, Nullable); + Type temp2 = builder.getTempRefType(2, Nullable); + Type temp3 = builder.getTempRefType(3, Nullable); + Type temp4 = builder.getTempRefType(4, Nullable); + builder.setHeapType(0, Signature(Type::none, temp1)); + builder.setHeapType(1, Signature(Type::none, temp2)); + builder.setHeapType(2, Signature(Type::none, temp3)); + builder.setHeapType(3, Signature(Type::none, temp4)); + builder.setHeapType(4, Signature(Type::none, temp0)); + // std::vector built = builder.build(); } } int main() { - // Run the tests twice to ensure things still work when the global stores are - // already populated. - for (size_t i = 0; i < 2; ++i) { - test_canonicalization(); - test_basic(); - test_recursive(); - test_lub(); - } + test_builder(); + test_canonicalization(); + test_recursive(); } diff -Nru binaryen-108/test/example/type-builder-nominal.cpp binaryen-99/test/example/type-builder-nominal.cpp --- binaryen-108/test/example/type-builder-nominal.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/type-builder-nominal.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,473 +0,0 @@ -#include -#include - -#include "wasm-type-printing.h" -#include "wasm-type.h" - -using namespace wasm; - -// Construct Signature, Struct, and Array heap types using undefined types. -void test_builder() { - std::cout << ";; Test TypeBuilder\n"; - - // (type $sig (func (param (ref $struct)) (result (ref $array) i32))) - // (type $struct (struct (field (ref null $array) (mut rtt 0 $array)))) - // (type $array (array (mut anyref))) - - TypeBuilder builder; - assert(builder.size() == 0); - builder.grow(3); - assert(builder.size() == 3); - - Type refSig = builder.getTempRefType(builder[0], NonNullable); - Type refStruct = builder.getTempRefType(builder[1], NonNullable); - Type refArray = builder.getTempRefType(builder[2], NonNullable); - Type refNullArray = builder.getTempRefType(builder[2], Nullable); - Type rttArray = builder.getTempRttType(Rtt(0, builder[2])); - Type refNullAny(HeapType::any, Nullable); - - Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32})); - Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)}); - Array array(Field(refNullAny, Mutable)); - - { - IndexedTypeNameGenerator print(builder); - std::cout << "Before setting heap types:\n"; - std::cout << "$sig => " << print(builder[0]) << "\n"; - std::cout << "$struct => " << print(builder[1]) << "\n"; - std::cout << "$array => " << print(builder[2]) << "\n"; - std::cout << "(ref $sig) => " << print(refSig) << "\n"; - std::cout << "(ref $struct) => " << print(refStruct) << "\n"; - std::cout << "(ref $array) => " << print(refArray) << "\n"; - std::cout << "(ref null $array) => " << print(refNullArray) << "\n"; - std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n"; - } - - builder[0] = sig; - builder[1] = struct_; - builder[2] = array; - - { - IndexedTypeNameGenerator print(builder); - std::cout << "After setting heap types:\n"; - std::cout << "$sig => " << print(builder[0]) << "\n"; - std::cout << "$struct => " << print(builder[1]) << "\n"; - std::cout << "$array => " << print(builder[2]) << "\n"; - std::cout << "(ref $sig) => " << print(refSig) << "\n"; - std::cout << "(ref $struct) => " << print(refStruct) << "\n"; - std::cout << "(ref $array) => " << print(refArray) << "\n"; - std::cout << "(ref null $array) => " << print(refNullArray) << "\n"; - std::cout << "(rtt 0 $array) => " << print(rttArray) << "\n\n"; - } - - std::vector built = *builder.build(); - - Type newRefSig = Type(built[0], NonNullable); - Type newRefStruct = Type(built[1], NonNullable); - Type newRefArray = Type(built[2], NonNullable); - Type newRefNullArray = Type(built[2], Nullable); - Type newRttArray = Type(Rtt(0, built[2])); - - { - IndexedTypeNameGenerator print(built); - std::cout << "After building types:\n"; - std::cout << "$sig => " << print(built[0]) << "\n"; - std::cout << "$struct => " << print(built[1]) << "\n"; - std::cout << "$array => " << print(built[2]) << "\n"; - std::cout << "(ref $sig) => " << print(newRefSig) << "\n"; - std::cout << "(ref $struct) => " << print(newRefStruct) << "\n"; - std::cout << "(ref $array) => " << print(newRefArray) << "\n"; - std::cout << "(ref null $array) => " << print(newRefNullArray) << "\n"; - std::cout << "(rtt 0 $array) => " << print(newRttArray) << "\n\n"; - } -} - -// Check that the builder works when there are duplicate definitions -void test_canonicalization() { - std::cout << ";; Test canonicalization\n"; - - // (type $struct (struct (field (ref null $sig) (ref null $sig)))) - // (type $sig (func)) - HeapType sig = Signature(Type::none, Type::none); - HeapType struct_ = Struct({Field(Type(sig, Nullable), Immutable), - Field(Type(sig, Nullable), Immutable)}); - - TypeBuilder builder(4); - - Type tempSigRef1 = builder.getTempRefType(builder[2], Nullable); - Type tempSigRef2 = builder.getTempRefType(builder[3], Nullable); - - assert(tempSigRef1 != tempSigRef2); - assert(tempSigRef1 != Type(sig, Nullable)); - assert(tempSigRef2 != Type(sig, Nullable)); - - builder[0] = - Struct({Field(tempSigRef1, Immutable), Field(tempSigRef1, Immutable)}); - builder[1] = - Struct({Field(tempSigRef2, Immutable), Field(tempSigRef2, Immutable)}); - builder[2] = Signature(Type::none, Type::none); - builder[3] = Signature(Type::none, Type::none); - - std::vector built = *builder.build(); - - assert(built[0] != struct_); - assert(built[1] != struct_); - assert(built[0] != built[1]); - assert(built[2] != sig); - assert(built[3] != sig); - assert(built[2] != built[3]); -} - -// Check that defined basic HeapTypes are handled correctly. -void test_basic() { - std::cout << ";; Test basic\n"; - - TypeBuilder builder(6); - - Type anyref = builder.getTempRefType(builder[4], Nullable); - Type i31ref = builder.getTempRefType(builder[5], NonNullable); - - builder[0] = Signature(Type::anyref, Type::i31ref); - builder[1] = Signature(anyref, Type::i31ref); - builder[2] = Signature(Type::anyref, i31ref); - builder[3] = Signature(anyref, i31ref); - builder[4] = HeapType::any; - builder[5] = HeapType::i31; - - std::vector built = *builder.build(); - - assert(built[0].getSignature() == Signature(Type::anyref, Type::i31ref)); - assert(built[1].getSignature() == built[0].getSignature()); - assert(built[2].getSignature() == built[1].getSignature()); - assert(built[3].getSignature() == built[2].getSignature()); - assert(built[4] == HeapType::any); - assert(built[5] == HeapType::i31); -} - -// Check that signatures created with TypeBuilders are properly recorded as -// canonical. -void test_signatures(bool warm) { - std::cout << ";; Test canonical signatures\n"; - - TypeBuilder builder(2); - Type tempRef = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::i31ref, Type::anyref); - builder[1] = Signature(tempRef, tempRef); - std::vector built = *builder.build(); - - HeapType small = Signature(Type::i31ref, Type::anyref); - HeapType big = - Signature(Type(Signature(Type::i31ref, Type::anyref), Nullable), - Type(Signature(Type::i31ref, Type::anyref), Nullable)); - if (warm) { - assert(built[0] != small); - assert(built[1] != big); - } else { - assert(built[0] == small); - assert(built[1] == big); - } -} - -void test_recursive() { - std::cout << ";; Test recursive types\n"; - - { - // Trivial recursion - std::vector built; - { - TypeBuilder builder(1); - Type temp = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n\n"; - assert(built[0] == built[0].getSignature().results.getHeapType()); - assert(Type(built[0], Nullable) == built[0].getSignature().results); - } - - { - // Mutual recursion - std::vector built; - { - TypeBuilder builder(2); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - } - - { - // A longer chain of recursion - std::vector built; - { - TypeBuilder builder(5); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type temp4 = builder.getTempRefType(builder[4], Nullable); - builder[0] = Signature(Type::none, temp1); - builder[1] = Signature(Type::none, temp2); - builder[2] = Signature(Type::none, temp3); - builder[3] = Signature(Type::none, temp4); - builder[4] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n"; - std::cout << print(built[2]) << "\n"; - std::cout << print(built[3]) << "\n"; - std::cout << print(built[4]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[1]); - assert(built[1].getSignature().results.getHeapType() == built[2]); - assert(built[2].getSignature().results.getHeapType() == built[3]); - assert(built[3].getSignature().results.getHeapType() == built[4]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - assert(built[0] != built[2]); - assert(built[0] != built[3]); - assert(built[0] != built[4]); - assert(built[1] != built[2]); - assert(built[1] != built[3]); - assert(built[1] != built[4]); - assert(built[2] != built[3]); - assert(built[2] != built[4]); - assert(built[3] != built[4]); - } - - { - // Check canonicalization for non-recursive parents and children of - // recursive HeapTypes. - std::vector built; - { - TypeBuilder builder(6); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - Type temp1 = builder.getTempRefType(builder[1], Nullable); - Type temp2 = builder.getTempRefType(builder[2], Nullable); - Type temp3 = builder.getTempRefType(builder[3], Nullable); - Type tuple0_2 = builder.getTempTupleType({temp0, temp2}); - Type tuple1_3 = builder.getTempTupleType({temp1, temp3}); - builder[0] = Signature(Type::none, tuple0_2); - builder[1] = Signature(Type::none, tuple1_3); - builder[2] = Signature(); - builder[3] = Signature(); - builder[4] = Signature(Type::none, temp0); - builder[5] = Signature(Type::none, temp1); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n"; - std::cout << print(built[2]) << "\n"; - std::cout << print(built[3]) << "\n"; - std::cout << print(built[4]) << "\n"; - std::cout << print(built[5]) << "\n\n"; - assert(built[0] != built[1]); - assert(built[2] != built[3]); - assert(built[4] != built[5]); - assert(built[4].getSignature().results.getHeapType() == built[0]); - assert(built[5].getSignature().results.getHeapType() == built[1]); - assert(built[0].getSignature().results == - Type({Type(built[0], Nullable), Type(built[2], Nullable)})); - assert(built[1].getSignature().results == - Type({Type(built[1], Nullable), Type(built[3], Nullable)})); - } - - { - // Folded and unfolded - std::vector built; - { - TypeBuilder builder(2); - Type temp0 = builder.getTempRefType(builder[0], Nullable); - builder[0] = Signature(Type::none, temp0); - builder[1] = Signature(Type::none, temp0); - built = *builder.build(); - } - IndexedTypeNameGenerator print(built); - std::cout << print(built[0]) << "\n"; - std::cout << print(built[1]) << "\n\n"; - assert(built[0].getSignature().results.getHeapType() == built[0]); - assert(built[1].getSignature().results.getHeapType() == built[0]); - assert(built[0] != built[1]); - } -} - -void test_subtypes() { - std::cout << ";; Test subtyping\n"; - - auto LUB = [&](HeapType a, HeapType b) { - Type refA = Type(a, Nullable); - Type refB = Type(b, Nullable); - Type lubAB = Type::getLeastUpperBound(refA, refB); - Type lubBA = Type::getLeastUpperBound(refB, refA); - assert(lubAB == lubBA); - assert(lubAB != Type::none); - HeapType lub = lubAB.getHeapType(); - assert(Type::hasLeastUpperBound(refA, refB)); - assert(Type::hasLeastUpperBound(refB, refA)); - assert(Type::isSubType(refA, lubAB)); - assert(Type::isSubType(refB, lubAB)); - assert(HeapType::isSubType(a, lub)); - assert(HeapType::isSubType(b, lub)); - assert(lub == a || !HeapType::isSubType(lub, a)); - assert(lub == b || !HeapType::isSubType(lub, b)); - return lub; - }; - - { - // Basic Types - for (auto other : {HeapType::func, - HeapType::any, - HeapType::eq, - HeapType::i31, - HeapType::data}) { - assert(LUB(HeapType::any, other) == HeapType::any); - } - assert(LUB(HeapType::eq, HeapType::func) == HeapType::any); - assert(LUB(HeapType::i31, HeapType::data) == HeapType::eq); - } - - { - // Identity - std::vector built; - { - TypeBuilder builder(3); - builder[0] = Signature(Type::none, Type::none); - builder[1] = Struct{}; - builder[2] = Array(Field(Type::i32, Mutable)); - built = *builder.build(); - } - assert(LUB(built[0], built[0]) == built[0]); - assert(LUB(built[1], built[1]) == built[1]); - assert(LUB(built[2], built[2]) == built[2]); - } - - { - // No subtype declarations mean no subtypes - std::vector built; - { - TypeBuilder builder(5); - Type structRef0 = builder.getTempRefType(builder[0], Nullable); - Type structRef1 = builder.getTempRefType(builder[1], Nullable); - builder[0] = Struct{}; - builder[1] = Struct{}; - builder[2] = Signature(Type::none, Type::anyref); - builder[3] = Signature(Type::none, structRef0); - builder[4] = Signature(Type::none, structRef1); - built = *builder.build(); - } - assert(LUB(built[0], built[1]) == HeapType::data); - assert(LUB(built[2], built[3]) == HeapType::func); - assert(LUB(built[2], built[4]) == HeapType::func); - } - - { - // Subtype declarations, but still no subtypes - std::vector built; - { - TypeBuilder builder(3); - builder[0].subTypeOf(builder[1]); - builder[0] = Struct{}; - builder[1] = Struct{}; - builder[2] = Struct{}; - built = *builder.build(); - } - assert(LUB(built[0], built[2]) == HeapType::data); - } - - { - // Subtyping of identical types - std::vector built; - { - TypeBuilder builder(6); - builder[0].subTypeOf(builder[1]); - builder[2].subTypeOf(builder[3]); - builder[4].subTypeOf(builder[5]); - builder[0] = - Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)}); - builder[1] = - Struct({Field(Type::i32, Mutable), Field(Type::anyref, Mutable)}); - builder[2] = Signature(Type::i32, Type::anyref); - builder[3] = Signature(Type::i32, Type::anyref); - builder[4] = Array(Field(Type::i32, Mutable)); - builder[5] = Array(Field(Type::i32, Mutable)); - built = *builder.build(); - } - assert(LUB(built[0], built[1]) == built[1]); - assert(LUB(built[2], built[3]) == built[3]); - assert(LUB(built[4], built[5]) == built[5]); - } - - { - // Width subtyping - std::vector built; - { - TypeBuilder builder(2); - builder[0] = Struct({Field(Type::i32, Immutable)}); - builder[1] = - Struct({Field(Type::i32, Immutable), Field(Type::i32, Immutable)}); - builder[1].subTypeOf(builder[0]); - built = *builder.build(); - } - assert(LUB(built[1], built[0]) == built[0]); - } - - { - // Depth subtyping - std::vector built; - { - TypeBuilder builder(2); - builder[0] = Struct({Field(Type::anyref, Immutable)}); - builder[1] = Struct({Field(Type::funcref, Immutable)}); - builder[1].subTypeOf(builder[0]); - built = *builder.build(); - } - assert(LUB(built[1], built[0]) == built[0]); - } - - { - // Mutually recursive subtyping - std::vector built; - { - TypeBuilder builder(4); - Type a = builder.getTempRefType(builder[0], Nullable); - Type b = builder.getTempRefType(builder[1], Nullable); - Type c = builder.getTempRefType(builder[2], Nullable); - Type d = builder.getTempRefType(builder[3], Nullable); - builder[1].subTypeOf(builder[0]); - builder[3].subTypeOf(builder[2]); - builder[0] = Struct({Field(c, Immutable)}); - builder[1] = Struct({Field(d, Immutable)}); - builder[2] = Struct({Field(a, Immutable)}); - builder[3] = Struct({Field(b, Immutable)}); - built = *builder.build(); - } - assert(LUB(built[0], built[1]) == built[0]); - assert(LUB(built[2], built[3]) == built[2]); - } -} - -int main() { - wasm::setTypeSystem(TypeSystem::Nominal); - - // Run the tests twice to ensure things still work when the global stores are - // already populated. - for (size_t i = 0; i < 2; ++i) { - test_builder(); - test_canonicalization(); - test_basic(); - test_signatures(i == 1); - test_recursive(); - test_subtypes(); - } -} diff -Nru binaryen-108/test/example/type-builder-nominal.txt binaryen-99/test/example/type-builder-nominal.txt --- binaryen-108/test/example/type-builder-nominal.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/type-builder-nominal.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -;; Test TypeBuilder -Before setting heap types: -$sig => (; temp ;) (func_subtype func) -$struct => (; temp ;) (func_subtype func) -$array => (; temp ;) (func_subtype func) -(ref $sig) => (; temp ;) (ref $0) -(ref $struct) => (; temp ;) (ref $1) -(ref $array) => (; temp ;) (ref $2) -(ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - -After setting heap types: -$sig => (; temp ;) (func_subtype (param (; temp ;) (ref $1)) (result (; temp ;) (ref $2) i32) func) -$struct => (; temp ;) (struct_subtype (field (; temp ;) (ref null $2) (mut (; temp ;) (rtt 0 $2))) data) -$array => (; temp ;) (array_subtype (mut anyref) data) -(ref $sig) => (; temp ;) (ref $0) -(ref $struct) => (; temp ;) (ref $1) -(ref $array) => (; temp ;) (ref $2) -(ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - -After building types: -$sig => (func_subtype (param (ref $1)) (result (ref $2) i32) func) -$struct => (struct_subtype (field (ref null $2) (mut (rtt 0 $2))) data) -$array => (array_subtype (mut anyref) data) -(ref $sig) => (ref $0) -(ref $struct) => (ref $1) -(ref $array) => (ref $2) -(ref null $array) => (ref null $2) -(rtt 0 $array) => (rtt 0 $2) - -;; Test canonicalization -;; Test basic -;; Test canonical signatures -;; Test recursive types -(func_subtype (result (ref null $0)) func) - -(func_subtype (result (ref null $1)) func) -(func_subtype (result (ref null $0)) func) - -(func_subtype (result (ref null $1)) func) -(func_subtype (result (ref null $2)) func) -(func_subtype (result (ref null $3)) func) -(func_subtype (result (ref null $4)) func) -(func_subtype (result (ref null $0)) func) - -(func_subtype (result (ref null $0) (ref null $2)) func) -(func_subtype (result (ref null $1) (ref null $3)) func) -(func_subtype func) -(func_subtype func) -(func_subtype (result (ref null $0)) func) -(func_subtype (result (ref null $1)) func) - -(func_subtype (result (ref null $0)) func) -(func_subtype (result (ref null $0)) func) - -;; Test subtyping -;; Test TypeBuilder -Before setting heap types: -$sig => (; temp ;) (func_subtype func) -$struct => (; temp ;) (func_subtype func) -$array => (; temp ;) (func_subtype func) -(ref $sig) => (; temp ;) (ref $0) -(ref $struct) => (; temp ;) (ref $1) -(ref $array) => (; temp ;) (ref $2) -(ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - -After setting heap types: -$sig => (; temp ;) (func_subtype (param (; temp ;) (ref $1)) (result (; temp ;) (ref $2) i32) func) -$struct => (; temp ;) (struct_subtype (field (; temp ;) (ref null $2) (mut (; temp ;) (rtt 0 $2))) data) -$array => (; temp ;) (array_subtype (mut anyref) data) -(ref $sig) => (; temp ;) (ref $0) -(ref $struct) => (; temp ;) (ref $1) -(ref $array) => (; temp ;) (ref $2) -(ref null $array) => (; temp ;) (ref null $2) -(rtt 0 $array) => (; temp ;) (rtt 0 $2) - -After building types: -$sig => (func_subtype (param (ref $1)) (result (ref $2) i32) func) -$struct => (struct_subtype (field (ref null $2) (mut (rtt 0 $2))) data) -$array => (array_subtype (mut anyref) data) -(ref $sig) => (ref $0) -(ref $struct) => (ref $1) -(ref $array) => (ref $2) -(ref null $array) => (ref null $2) -(rtt 0 $array) => (rtt 0 $2) - -;; Test canonicalization -;; Test basic -;; Test canonical signatures -;; Test recursive types -(func_subtype (result (ref null $0)) func) - -(func_subtype (result (ref null $1)) func) -(func_subtype (result (ref null $0)) func) - -(func_subtype (result (ref null $1)) func) -(func_subtype (result (ref null $2)) func) -(func_subtype (result (ref null $3)) func) -(func_subtype (result (ref null $4)) func) -(func_subtype (result (ref null $0)) func) - -(func_subtype (result (ref null $0) (ref null $2)) func) -(func_subtype (result (ref null $1) (ref null $3)) func) -(func_subtype func) -(func_subtype func) -(func_subtype (result (ref null $0)) func) -(func_subtype (result (ref null $1)) func) - -(func_subtype (result (ref null $0)) func) -(func_subtype (result (ref null $0)) func) - -;; Test subtyping diff -Nru binaryen-108/test/example/type-builder.txt binaryen-99/test/example/type-builder.txt --- binaryen-108/test/example/type-builder.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/type-builder.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,56 +1,24 @@ -;; Test canonicalization -;; Test basic -;; Test recursive types -(func (result (ref null $0))) - -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (result (ref null $0))) -(func (result (ref null $0))) -(func (result (ref null $0))) -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (result (ref null $0) (ref null $2))) -(func (result (ref null $0) (ref null $2))) -(func) -(func) -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (param anyref) (result (ref null $0))) -(func (param anyref) (result (ref null $0))) +;; Test TypeBuilder +Before setting heap types: +(ref $sig) => (ref (func)) +(ref $struct) => (ref (func)) +(ref $array) => (ref (func)) +(ref null $array) => (ref null (func)) +(rtt 0 $array) => (rtt 0 (func)) + +After setting heap types: +(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32))) +(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref))))))) +(ref $array) => (ref (array (mut externref))) +(ref null $array) => (ref null (array (mut externref))) +(rtt 0 $array) => (rtt 0 (array (mut externref))) + +After building types: +(ref $sig) => (ref (func (param (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref)))))))) (result (ref (array (mut externref))) i32))) +(ref $struct) => (ref (struct (field (ref null (array (mut externref))) (mut (rtt 0 (array (mut externref))))))) +(ref $array) => (ref (array (mut externref))) +(ref null $array) => (ref null (array (mut externref))) +(rtt 0 $array) => (rtt 0 (array (mut externref))) -;; Test LUBs ;; Test canonicalization -;; Test basic ;; Test recursive types -(func (result (ref null $0))) - -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (result (ref null $0))) -(func (result (ref null $0))) -(func (result (ref null $0))) -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (result (ref null $0) (ref null $2))) -(func (result (ref null $0) (ref null $2))) -(func) -(func) -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (result (ref null $0))) -(func (result (ref null $0))) - -(func (param anyref) (result (ref null $0))) -(func (param anyref) (result (ref null $0))) - -;; Test LUBs diff -Nru binaryen-108/test/example/typeinfo.cpp binaryen-99/test/example/typeinfo.cpp --- binaryen-108/test/example/typeinfo.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/typeinfo.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -15,6 +15,24 @@ assert(Type(func, NonNullable).getID() == Type(sameFunc, NonNullable).getID()); + HeapType extern_(HeapType::ext); + assert(Type(extern_, Nullable).getID() == Type::externref); + assert(Type(extern_, NonNullable).getID() == + Type(extern_, NonNullable).getID()); + assert(Type(extern_, NonNullable).getID() != + Type(extern_, Nullable).getID()); + HeapType sameExtern(HeapType::ext); + assert(Type(extern_, NonNullable).getID() == + Type(sameExtern, NonNullable).getID()); + + HeapType exn(HeapType::exn); + assert(Type(exn, Nullable).getID() == Type::exnref); + assert(Type(exn, NonNullable).getID() == Type(exn, NonNullable).getID()); + assert(Type(exn, NonNullable).getID() != Type(exn, Nullable).getID()); + HeapType sameExn(HeapType::exn); + assert(Type(exn, NonNullable).getID() == + Type(sameExn, NonNullable).getID()); + HeapType any(HeapType::any); assert(Type(any, Nullable).getID() == Type::anyref); assert(Type(any, NonNullable).getID() == Type(any, NonNullable).getID()); @@ -54,13 +72,13 @@ Type(otherSignature, NonNullable).getID()); } { - Struct struct_{}; + Struct struct_({}); assert(Type(struct_, NonNullable).getID() == Type(struct_, NonNullable).getID()); assert(Type(struct_, NonNullable).getID() != Type(struct_, Nullable).getID()); - Struct sameStruct{}; + Struct sameStruct({}); assert(Type(struct_, NonNullable).getID() == Type(sameStruct, NonNullable).getID()); @@ -92,7 +110,7 @@ Tuple sameTuple({Type::i32, Type::f64}); assert(Type(tuple).getID() == Type(sameTuple).getID()); - Tuple otherTuple({Type::f64, Type::anyref}); + Tuple otherTuple({Type::f64, Type::externref}); assert(Type(tuple).getID() != Type(otherTuple).getID()); } { @@ -111,10 +129,10 @@ assert(rtt != otherHeapTypeRtt); assert(Type(rtt).getID() != Type(otherHeapTypeRtt).getID()); - Rtt structRtt(0, Struct{}); + Rtt structRtt(0, Struct({})); assert(Type(structRtt).getID() == Type(structRtt).getID()); - Rtt sameStructRtt(0, Struct{}); + Rtt sameStructRtt(0, Struct({})); assert(structRtt == sameStructRtt); assert(Type(structRtt).getID() == Type(sameStructRtt).getID()); @@ -130,6 +148,9 @@ std::cout << HeapType(HeapType::func) << "\n"; std::cout << Type(HeapType::func, Nullable) << "\n"; std::cout << Type(HeapType::func, NonNullable) << "\n"; + std::cout << HeapType(HeapType::ext) << "\n"; + std::cout << Type(HeapType::ext, Nullable) << "\n"; + std::cout << Type(HeapType::ext, NonNullable) << "\n"; std::cout << HeapType(HeapType::any) << "\n"; std::cout << Type(HeapType::any, Nullable) << "\n"; std::cout << Type(HeapType::any, NonNullable) << "\n"; @@ -139,8 +160,11 @@ std::cout << HeapType(HeapType::i31) << "\n"; std::cout << Type(HeapType::i31, Nullable) << "\n"; std::cout << Type(HeapType::i31, NonNullable) << "\n"; - std::cout << Signature(Type::none, Type::none) << "\n"; - std::cout << HeapType(Struct{}) << "\n"; + std::cout << HeapType(HeapType::exn) << "\n"; + std::cout << Type(HeapType::exn, Nullable) << "\n"; + std::cout << Type(HeapType::exn, NonNullable) << "\n"; + std::cout << HeapType(Signature(Type::none, Type::none)) << "\n"; + std::cout << HeapType(Struct({})) << "\n"; std::cout << HeapType(Array({Type::i32, Immutable})) << "\n"; } { @@ -156,7 +180,7 @@ } { std::cout << "\n;; Struct\n"; - Struct emptyStruct{}; + Struct emptyStruct({}); std::cout << emptyStruct << "\n"; std::cout << Type(emptyStruct, NonNullable) << "\n"; std::cout << Type(emptyStruct, Nullable) << "\n"; @@ -165,7 +189,7 @@ {Type::i64, Immutable}, {Type::f32, Mutable}, {Type::f64, Mutable}, - {Type::anyref, Immutable}, + {Type::externref, Immutable}, }); std::cout << struct_ << "\n"; std::cout << Type(struct_, NonNullable) << "\n"; @@ -177,20 +201,20 @@ std::cout << array << "\n"; std::cout << Type(array, NonNullable) << "\n"; std::cout << Type(array, Nullable) << "\n"; - Array arrayMut({Type::anyref, Mutable}); + Array arrayMut({Type::externref, Mutable}); std::cout << arrayMut << "\n"; std::cout << Type(arrayMut, NonNullable) << "\n"; std::cout << Type(arrayMut, Nullable) << "\n"; } { std::cout << "\n;; Tuple\n"; - Tuple emptyTuple{}; + Tuple emptyTuple({}); std::cout << emptyTuple << "\n"; std::cout << Type(emptyTuple) << "\n"; Tuple tuple({ Type::i32, Type::f64, - Type::anyref, + Type::externref, }); std::cout << tuple << "\n"; std::cout << Type(tuple) << "\n"; @@ -199,16 +223,20 @@ std::cout << "\n;; Rtt\n"; std::cout << Rtt(0, HeapType::func) << "\n"; std::cout << Type(Rtt(0, HeapType::func)) << "\n"; + std::cout << Rtt(1, HeapType::ext) << "\n"; + std::cout << Type(Rtt(1, HeapType::ext)) << "\n"; std::cout << Rtt(2, HeapType::any) << "\n"; std::cout << Type(Rtt(2, HeapType::any)) << "\n"; std::cout << Rtt(3, HeapType::eq) << "\n"; std::cout << Type(Rtt(3, HeapType::eq)) << "\n"; std::cout << Rtt(4, HeapType::i31) << "\n"; std::cout << Type(Rtt(4, HeapType::i31)) << "\n"; + std::cout << Rtt(5, HeapType::exn) << "\n"; + std::cout << Type(Rtt(5, HeapType::exn)) << "\n"; Rtt signatureRtt(6, Signature(Type::none, Type::none)); std::cout << signatureRtt << "\n"; std::cout << Type(signatureRtt) << "\n"; - Rtt structRtt(7, Struct{}); + Rtt structRtt(7, Struct({})); std::cout << structRtt << "\n"; std::cout << Type(structRtt) << "\n"; Rtt arrayRtt(8, Array({Type::i32, Immutable})); @@ -217,18 +245,18 @@ } { std::cout << "\n;; Signature of references (param/result)\n"; - Signature signature(Type(Struct{}, Nullable), + Signature signature(Type(Struct({}), Nullable), Type(Array({Type::i32, Mutable}), NonNullable)); std::cout << signature << "\n"; } { std::cout << "\n;; Signature of references (params/results)\n"; Signature signature(Type({ - Type(Struct{}, Nullable), + Type(Struct({}), Nullable), Type(Array({Type::i32, Mutable}), NonNullable), }), Type({ - Type(Struct{}, NonNullable), + Type(Struct({}), NonNullable), Type(Array({Type::i32, Immutable}), Nullable), })); std::cout << signature << "\n"; @@ -245,10 +273,10 @@ std::cout << Type(structOfSignature, NonNullable) << "\n"; std::cout << Type(structOfSignature, Nullable) << "\n"; Struct structOfStruct({ - {Type(Struct{}, NonNullable), Immutable}, - {Type(Struct{}, NonNullable), Mutable}, - {Type(Struct{}, Nullable), Immutable}, - {Type(Struct{}, Nullable), Mutable}, + {Type(Struct({}), NonNullable), Immutable}, + {Type(Struct({}), NonNullable), Mutable}, + {Type(Struct({}), Nullable), Immutable}, + {Type(Struct({}), Nullable), Mutable}, }); std::cout << structOfStruct << "\n"; std::cout << Type(structOfStruct, NonNullable) << "\n"; @@ -265,7 +293,7 @@ Struct structOfEverything({ {Type::i32, Mutable}, {Type(Signature(Type::none, Type::none), Nullable), Mutable}, - {Type(Struct{}, Nullable), Mutable}, + {Type(Struct({}), Nullable), Mutable}, {Type(Array({Type::i32, Mutable}), Nullable), Mutable}, }); std::cout << structOfEverything << "\n"; @@ -279,7 +307,7 @@ std::cout << arrayOfSignature << "\n"; std::cout << Type(arrayOfSignature, NonNullable) << "\n"; std::cout << Type(arrayOfSignature, Nullable) << "\n"; - Array arrayOfStruct({Type(Struct{}, Nullable), Mutable}); + Array arrayOfStruct({Type(Struct({}), Nullable), Mutable}); std::cout << arrayOfStruct << "\n"; std::cout << Type(arrayOfStruct, NonNullable) << "\n"; std::cout << Type(arrayOfStruct, Nullable) << "\n"; @@ -294,14 +322,15 @@ Tuple tuple({ Type(Signature(Type::none, Type::none), NonNullable), Type(Signature(Type::none, Type::none), Nullable), - Type(Struct{}, NonNullable), - Type(Struct{}, Nullable), + Type(Struct({}), NonNullable), + Type(Struct({}), Nullable), Type(Array({Type::i32, Immutable}), NonNullable), Type(Array({Type::i32, Immutable}), Nullable), }); std::cout << tuple << "\n"; std::cout << Type(tuple) << "\n"; } + // TODO: Think about recursive types. Currently impossible to construct. { std::cout << "\n;; Recursive (not really)\n"; Signature signatureSignature(Type::none, Type::none); diff -Nru binaryen-108/test/example/typeinfo.txt binaryen-99/test/example/typeinfo.txt --- binaryen-108/test/example/typeinfo.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/example/typeinfo.txt 2021-01-07 20:01:06.000000000 +0000 @@ -2,6 +2,9 @@ func funcref (ref func) +extern +externref +(ref extern) any anyref (ref any) @@ -11,93 +14,100 @@ i31 (ref null i31) i31ref +exn +exnref +(ref exn) (func) (struct) (array i32) ;; Signature (func) -(ref $func.0) -(ref null $func.0) +(ref (func)) +(ref null (func)) (func (param i32) (result f64)) -(ref $func.0) -(ref null $func.0) +(ref (func (param i32) (result f64))) +(ref null (func (param i32) (result f64))) ;; Struct (struct) -(ref $struct.0) -(ref null $struct.0) -(struct (field i32 i64 (mut f32) (mut f64) anyref)) -(ref $struct.0) -(ref null $struct.0) +(ref (struct)) +(ref null (struct)) +(struct (field i32 i64 (mut f32) (mut f64) externref)) +(ref (struct (field i32 i64 (mut f32) (mut f64) externref))) +(ref null (struct (field i32 i64 (mut f32) (mut f64) externref))) ;; Array (array i32) -(ref $array.0) -(ref null $array.0) -(array (mut anyref)) -(ref $array.0) -(ref null $array.0) +(ref (array i32)) +(ref null (array i32)) +(array (mut externref)) +(ref (array (mut externref))) +(ref null (array (mut externref))) ;; Tuple () none -(i32 f64 anyref) -(i32 f64 anyref) +(i32 f64 externref) +(i32 f64 externref) ;; Rtt (rtt 0 func) (rtt 0 func) +(rtt 1 extern) +(rtt 1 extern) (rtt 2 any) (rtt 2 any) (rtt 3 eq) (rtt 3 eq) (rtt 4 i31) (rtt 4 i31) -(rtt 6 $func.0) -(rtt 6 $func.0) -(rtt 7 $struct.0) -(rtt 7 $struct.0) -(rtt 8 $array.0) -(rtt 8 $array.0) +(rtt 5 exn) +(rtt 5 exn) +(rtt 6 (func)) +(rtt 6 (func)) +(rtt 7 (struct)) +(rtt 7 (struct)) +(rtt 8 (array i32)) +(rtt 8 (array i32)) ;; Signature of references (param/result) -(func (param (ref null $struct.0)) (result (ref $array.0))) +(func (param (ref null (struct))) (result (ref (array (mut i32))))) ;; Signature of references (params/results) -(func (param (ref null $struct.0) (ref $array.0)) (result (ref $struct.0) (ref null $array.1))) +(func (param (ref null (struct)) (ref (array (mut i32)))) (result (ref (struct)) (ref null (array i32)))) ;; Struct of references -(struct (field (ref $func.0) (mut (ref $func.0)) (ref null $func.0) (mut (ref null $func.0)))) -(ref $struct.0) -(ref null $struct.0) -(struct (field (ref $struct.0) (mut (ref $struct.0)) (ref null $struct.0) (mut (ref null $struct.0)))) -(ref $struct.0) -(ref null $struct.0) -(struct (field (ref $array.0) (mut (ref $array.0)) (ref null $array.0) (mut (ref null $array.0)))) -(ref $struct.0) -(ref null $struct.0) -(struct (field (mut i32) (mut (ref null $func.0)) (mut (ref null $struct.0)) (mut (ref null $array.0)))) -(ref $struct.0) -(ref null $struct.0) +(struct (field (ref (func)) (mut (ref (func))) (ref null (func)) (mut (ref null (func))))) +(ref (struct (field (ref (func)) (mut (ref (func))) (ref null (func)) (mut (ref null (func)))))) +(ref null (struct (field (ref (func)) (mut (ref (func))) (ref null (func)) (mut (ref null (func)))))) +(struct (field (ref (struct)) (mut (ref (struct))) (ref null (struct)) (mut (ref null (struct))))) +(ref (struct (field (ref (struct)) (mut (ref (struct))) (ref null (struct)) (mut (ref null (struct)))))) +(ref null (struct (field (ref (struct)) (mut (ref (struct))) (ref null (struct)) (mut (ref null (struct)))))) +(struct (field (ref (array i32)) (mut (ref (array i32))) (ref null (array i32)) (mut (ref null (array i32))))) +(ref (struct (field (ref (array i32)) (mut (ref (array i32))) (ref null (array i32)) (mut (ref null (array i32)))))) +(ref null (struct (field (ref (array i32)) (mut (ref (array i32))) (ref null (array i32)) (mut (ref null (array i32)))))) +(struct (field (mut i32) (mut (ref null (func))) (mut (ref null (struct))) (mut (ref null (array (mut i32)))))) +(ref (struct (field (mut i32) (mut (ref null (func))) (mut (ref null (struct))) (mut (ref null (array (mut i32))))))) +(ref null (struct (field (mut i32) (mut (ref null (func))) (mut (ref null (struct))) (mut (ref null (array (mut i32))))))) ;; Array of references -(array (ref null $func.0)) -(ref $array.0) -(ref null $array.0) -(array (mut (ref null $struct.0))) -(ref $array.0) -(ref null $array.0) -(array (ref null $array.0)) -(ref $array.0) -(ref null $array.0) +(array (ref null (func))) +(ref (array (ref null (func)))) +(ref null (array (ref null (func)))) +(array (mut (ref null (struct)))) +(ref (array (mut (ref null (struct))))) +(ref null (array (mut (ref null (struct))))) +(array (ref null (array i32))) +(ref (array (ref null (array i32)))) +(ref null (array (ref null (array i32)))) ;; Tuple of references -((ref $func.0) (ref null $func.0) (ref $struct.0) (ref null $struct.0) (ref $array.0) (ref null $array.0)) -((ref $func.0) (ref null $func.0) (ref $struct.0) (ref null $struct.0) (ref $array.0) (ref null $array.0)) +((ref (func)) (ref null (func)) (ref (struct)) (ref null (struct)) (ref (array i32)) (ref null (array i32))) +((ref (func)) (ref null (func)) (ref (struct)) (ref null (struct)) (ref (array i32)) (ref null (array i32))) ;; Recursive (not really) -(func (param (ref $func.0))) -(ref $func.0) -(func (param (ref $array.0))) -(ref $func.0) +(func (param (ref (func)))) +(ref (func (param (ref (func))))) +(func (param (ref (array (ref (func)))))) +(ref (func (param (ref (array (ref (func))))))) diff -Nru binaryen-108/test/exception-handling.wast binaryen-99/test/exception-handling.wast --- binaryen-108/test/exception-handling.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/exception-handling.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,34 +1,28 @@ (module - (tag $e-i32 (param i32)) - (tag $e-i64 (param i64)) - (tag $e-i32-i64 (param i32 i64)) - (tag $e-anyref (param anyref)) - (tag $e-empty) + (event $e0 (attr 0) (param i32)) + (event $e1 (attr 0) (param externref)) + + (func $exnref_test (param $0 exnref) (result exnref) + (local.get $0) + ) (func $foo) (func $bar) - (func $eh-test (local $x (i32 i64)) - ;; Simple try-catch - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - ) - - ;; try-catch with multivalue tag + (func $eh_test (local $exn exnref) (try (do - (throw $e-i32-i64 (i32.const 0) (i64.const 0)) + (throw $e0 (i32.const 0)) ) - (catch $e-i32-i64 - (local.set $x (pop i32 i64)) + (catch + ;; Multi-value is not available yet, so block can't take a value from + ;; stack. So this uses locals for now. + (local.set $exn (pop exnref)) (drop - (tuple.extract 0 - (local.get $x) + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e0 (local.get $exn)) + ) ) ) ) @@ -39,8 +33,7 @@ (do (br $l1) ) - (catch $e-i32 - (drop (pop i32)) + (catch (br $l1) ) ) @@ -48,8 +41,8 @@ ;; Empty try body (try (do) - (catch $e-i32 - (drop (pop i32)) + (catch + (drop (pop exnref)) ) ) @@ -59,297 +52,11 @@ (call $foo) (call $bar) ) - (catch $e-i32 - (drop (pop i32)) - (call $foo) - (call $bar) - ) - ) - - ;; Multiple catch clauses - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - (catch $e-i64 - (drop (pop i64)) - ) - ) - - ;; Single catch-all clause - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch_all) - ) - - ;; catch and catch-all clauses together - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - (catch $e-i64 - (drop (pop i64)) - ) - (catch_all + (catch + (drop (pop exnref)) (call $foo) (call $bar) ) ) - - ;; nested try-catch - (try - (do - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - (catch_all) - ) - ) - (catch $e-i32 - (drop (pop i32)) - ) - (catch_all - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - (catch_all) - ) - ) - ) - - ;; try without catch or delegate - (try - (do - (throw $e-i32 (i32.const 0)) - ) - ) - ) - - (func $delegate-test - ;; Inner delegates target an outer catch - (try $l0 - (do - (try - (do - (call $foo) - ) - (delegate $l0) ;; by label - ) - (try - (do - (call $foo) - ) - (delegate 0) ;; by depth - ) - ) - (catch_all) - ) - - ;; When there are both a branch and a delegate that target the same try - ;; label. Because binaryen only allows blocks and loops to be targetted by - ;; branches, we wrap the try with a block and make branches that block - ;; instead, resulting in the br and delegate target different labels in the - ;; output. - (try $l0 - (do - (try - (do - (br_if $l0 (i32.const 1)) - ) - (delegate $l0) ;; by label - ) - (try - (do - (br_if $l0 (i32.const 1)) - ) - (delegate 0) ;; by depth - ) - ) - (catch_all) - ) - - ;; The inner delegate targets the outer delegate, which in turn targets the - ;; caller. - (try $l0 - (do - (try - (do - (call $foo) - ) - (delegate $l0) - ) - ) - (delegate 0) - ) - - ;; 'catch' body can be empty when the tag's type is none. - (try - (do) - (catch $e-empty) - ) - ) - - (func $rethrow-test - ;; Simple try-catch-rethrow - (try $l0 - (do - (call $foo) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l0) ;; by label - ) - (catch_all - (rethrow 0) ;; by depth - ) - ) - - ;; When there are both a branch and a rethrow that target the same try - ;; label. Because binaryen only allows blocks and loops to be targetted by - ;; branches, we wrap the try with a block and make branches that block - ;; instead, resulting in the br and rethrow target different labels in the - ;; output. - (try $l0 - (do - (call $foo) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l0) - ) - (catch_all - (br $l0) - ) - ) - - ;; One more level deep - (try $l0 - (do - (call $foo) - ) - (catch_all - (try - (do - (call $foo) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l0) ;; by label - ) - (catch_all - (rethrow 1) ;; by depth - ) - ) - ) - ) - - ;; Interleaving block - (try $l0 - (do - (call $foo) - ) - (catch_all - (try - (do - (call $foo) - ) - (catch $e-i32 - (drop (pop i32)) - (block $b0 - (rethrow $l0) ;; by label - ) - ) - (catch_all - (block $b1 - (rethrow 2) ;; by depth - ) - ) - ) - ) - ) - - ;; Within nested try, but rather in 'try' part and not 'catch' - (try $l0 - (do - (call $foo) - ) - (catch_all - (try - (do - (rethrow $l0) ;; by label - ) - (catch_all) - ) - ) - ) - (try $l0 - (do - (call $foo) - ) - (catch_all - (try - (do - (rethrow 1) ;; by depth - ) - (catch_all) - ) - ) - ) - ) - - (func $pop-test - (try - (do) - (catch $e-i32 - (throw $e-i32 - (if (result i32) - ;; pop is within an if condition, so this is OK. - (pop i32) - (i32.const 0) - (i32.const 3) - ) - ) - ) - ) - - (try - (do) - (catch $e-anyref - (drop - (pop funcref) ;; pop can be subtype - ) - ) - ) - ) - - (func $catchless-try-with-inner-delegate - (try $label$0 - (do - (try - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (delegate $label$0) - ) - ) - ) ) ) diff -Nru binaryen-108/test/exception-handling.wast.fromBinary binaryen-99/test/exception-handling.wast.fromBinary --- binaryen-108/test/exception-handling.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/exception-handling.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,428 +1,78 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i64_=>_none (func (param i64))) - (type $i32_i64_=>_none (func (param i32 i64))) - (type $anyref_=>_none (func (param anyref))) - (tag $tag$0 (param i32)) - (tag $tag$1 (param i64)) - (tag $tag$2 (param i32 i64)) - (tag $tag$3 (param anyref)) - (tag $tag$4 (param)) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_exnref (func (param exnref) (result exnref))) + (event $event$0 (attr 0) (param i32)) + (event $event$1 (attr 0) (param externref)) + (func $exnref_test (param $0 exnref) (result exnref) + (local.get $0) + ) (func $foo (nop) ) (func $bar (nop) ) - (func $eh-test - (local $x i32) - (local $1 i64) - (local $2 (i32 i64)) - (local $3 i32) - (local $4 i32) - (try $label$3 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - ) - (try $label$6 + (func $eh_test + (local $exn exnref) + (try (do - (throw $tag$2 + (throw $event$0 (i32.const 0) - (i64.const 0) ) ) - (catch $tag$2 - (local.set $2 - (pop i32 i64) - ) - (local.set $x - (block (result i32) - (local.set $3 - (tuple.extract 0 - (local.get $2) - ) - ) - (local.set $1 - (tuple.extract 1 - (local.get $2) - ) - ) - (local.get $3) - ) + (catch + (local.set $exn + (pop exnref) ) (drop - (block (result i32) - (local.set $4 - (local.get $x) - ) - (drop - (local.get $1) + (block $label$3 (result i32) + (rethrow + (br_on_exn $label$3 $event$0 + (local.get $exn) + ) ) - (local.get $4) ) ) ) ) - (block $label$7 - (try $label$10 + (block $label$4 + (try (do - (br $label$7) + (br $label$4) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) - (br $label$7) + (br $label$4) ) ) ) - (try $label$13 + (try (do (nop) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) ) ) - (try $label$16 + (try (do (call $foo) (call $bar) ) - (catch $tag$0 - (drop - (pop i32) - ) - (call $foo) - (call $bar) - ) - ) - (try $label$19 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch $tag$1 - (drop - (pop i64) - ) - ) - ) - (try $label$22 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch_all - (nop) - ) - ) - (try $label$25 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch $tag$1 + (catch (drop - (pop i64) + (pop exnref) ) - ) - (catch_all (call $foo) (call $bar) ) ) - (try $label$34 - (do - (try $label$29 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch_all - (nop) - ) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch_all - (try $label$33 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch_all - (nop) - ) - ) - ) - ) - (try $label$37 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - ) - ) - (func $delegate-test - (try $label$9 - (do - (block $label$1 - (try $label$4 - (do - (call $foo) - ) - (delegate $label$9) - ) - (try $label$7 - (do - (call $foo) - ) - (delegate $label$9) - ) - ) - ) - (catch_all - (nop) - ) - ) - (block $label$10 - (try $label$19 - (do - (block $label$11 - (try $label$14 - (do - (br_if $label$10 - (i32.const 1) - ) - ) - (delegate $label$19) - ) - (try $label$17 - (do - (br_if $label$10 - (i32.const 1) - ) - ) - (delegate $label$19) - ) - ) - ) - (catch_all - (nop) - ) - ) - ) - (try $label$25 - (do - (block $label$20 - (try $label$23 - (do - (call $foo) - ) - (delegate $label$25) - ) - ) - ) - (delegate 0) - ) - (try $label$28 - (do - (nop) - ) - (catch $tag$4 - (nop) - ) - ) - ) - (func $rethrow-test - (try $label$3 - (do - (call $foo) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (rethrow $label$3) - ) - (catch_all - (rethrow $label$3) - ) - ) - (block $label$4 - (try $label$7 - (do - (call $foo) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (rethrow $label$7) - ) - (catch_all - (br $label$4) - ) - ) - ) - (try $label$13 - (do - (call $foo) - ) - (catch_all - (try $label$12 - (do - (call $foo) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (rethrow $label$13) - ) - (catch_all - (rethrow $label$13) - ) - ) - ) - ) - (try $label$20 - (do - (call $foo) - ) - (catch_all - (try $label$19 - (do - (call $foo) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (block $label$18 - (rethrow $label$20) - ) - ) - (catch_all - (rethrow $label$20) - ) - ) - ) - ) - (try $label$26 - (do - (call $foo) - ) - (catch_all - (try $label$25 - (do - (rethrow $label$26) - ) - (catch_all - (nop) - ) - ) - ) - ) - (try $label$32 - (do - (call $foo) - ) - (catch_all - (try $label$31 - (do - (rethrow $label$32) - ) - (catch_all - (nop) - ) - ) - ) - ) - ) - (func $pop-test - (try $label$5 - (do - (nop) - ) - (catch $tag$0 - (throw $tag$0 - (if (result i32) - (pop i32) - (i32.const 0) - (i32.const 3) - ) - ) - ) - ) - (try $label$8 - (do - (nop) - ) - (catch $tag$3 - (drop - (pop anyref) - ) - ) - ) - ) - (func $catchless-try-with-inner-delegate - (try $label$6 - (do - (block $label$1 - (try $label$4 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (delegate $label$6) - ) - ) - ) - ) ) ) diff -Nru binaryen-108/test/exception-handling.wast.fromBinary.noDebugInfo binaryen-99/test/exception-handling.wast.fromBinary.noDebugInfo --- binaryen-108/test/exception-handling.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/exception-handling.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,426 +1,76 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i64_=>_none (func (param i64))) - (type $i32_i64_=>_none (func (param i32 i64))) - (type $anyref_=>_none (func (param anyref))) - (tag $tag$0 (param i32)) - (tag $tag$1 (param i64)) - (tag $tag$2 (param i32 i64)) - (tag $tag$3 (param anyref)) - (tag $tag$4 (param)) - (func $0 - (nop) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_exnref (func (param exnref) (result exnref))) + (event $event$0 (attr 0) (param i32)) + (event $event$1 (attr 0) (param externref)) + (func $0 (param $0 exnref) (result exnref) + (local.get $0) ) (func $1 (nop) ) (func $2 - (local $0 i32) - (local $1 i64) - (local $2 (i32 i64)) - (local $3 i32) - (local $4 i32) - (try $label$3 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - ) - (try $label$6 + (nop) + ) + (func $3 + (local $0 exnref) + (try (do - (throw $tag$2 + (throw $event$0 (i32.const 0) - (i64.const 0) ) ) - (catch $tag$2 - (local.set $2 - (pop i32 i64) - ) + (catch (local.set $0 - (block (result i32) - (local.set $3 - (tuple.extract 0 - (local.get $2) - ) - ) - (local.set $1 - (tuple.extract 1 - (local.get $2) - ) - ) - (local.get $3) - ) + (pop exnref) ) (drop - (block (result i32) - (local.set $4 - (local.get $0) - ) - (drop - (local.get $1) - ) - (local.get $4) - ) - ) - ) - ) - (block $label$7 - (try $label$10 - (do - (br $label$7) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (br $label$7) - ) - ) - ) - (try $label$13 - (do - (nop) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - ) - (try $label$16 - (do - (call $0) - (call $1) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (call $0) - (call $1) - ) - ) - (try $label$19 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch $tag$1 - (drop - (pop i64) - ) - ) - ) - (try $label$22 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch_all - (nop) - ) - ) - (try $label$25 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch $tag$1 - (drop - (pop i64) - ) - ) - (catch_all - (call $0) - (call $1) - ) - ) - (try $label$34 - (do - (try $label$29 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch_all - (nop) - ) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch_all - (try $label$33 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - (catch_all - (nop) - ) - ) - ) - ) - (try $label$37 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - ) - ) - (func $3 - (try $label$9 - (do - (block $label$1 - (try $label$4 - (do - (call $0) - ) - (delegate $label$9) - ) - (try $label$7 - (do - (call $0) - ) - (delegate $label$9) - ) - ) - ) - (catch_all - (nop) - ) - ) - (block $label$10 - (try $label$19 - (do - (block $label$11 - (try $label$14 - (do - (br_if $label$10 - (i32.const 1) - ) + (block $label$3 (result i32) + (rethrow + (br_on_exn $label$3 $event$0 + (local.get $0) ) - (delegate $label$19) - ) - (try $label$17 - (do - (br_if $label$10 - (i32.const 1) - ) - ) - (delegate $label$19) ) ) ) - (catch_all - (nop) - ) - ) - ) - (try $label$25 - (do - (block $label$20 - (try $label$23 - (do - (call $0) - ) - (delegate $label$25) - ) - ) - ) - (delegate 0) - ) - (try $label$28 - (do - (nop) - ) - (catch $tag$4 - (nop) - ) - ) - ) - (func $4 - (try $label$3 - (do - (call $0) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (rethrow $label$3) - ) - (catch_all - (rethrow $label$3) ) ) (block $label$4 - (try $label$7 + (try (do - (call $0) + (br $label$4) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) - (rethrow $label$7) - ) - (catch_all (br $label$4) ) ) ) - (try $label$13 - (do - (call $0) - ) - (catch_all - (try $label$12 - (do - (call $0) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (rethrow $label$13) - ) - (catch_all - (rethrow $label$13) - ) - ) - ) - ) - (try $label$20 - (do - (call $0) - ) - (catch_all - (try $label$19 - (do - (call $0) - ) - (catch $tag$0 - (drop - (pop i32) - ) - (block $label$18 - (rethrow $label$20) - ) - ) - (catch_all - (rethrow $label$20) - ) - ) - ) - ) - (try $label$26 - (do - (call $0) - ) - (catch_all - (try $label$25 - (do - (rethrow $label$26) - ) - (catch_all - (nop) - ) - ) - ) - ) - (try $label$32 - (do - (call $0) - ) - (catch_all - (try $label$31 - (do - (rethrow $label$32) - ) - (catch_all - (nop) - ) - ) - ) - ) - ) - (func $5 - (try $label$5 + (try (do (nop) ) - (catch $tag$0 - (throw $tag$0 - (if (result i32) - (pop i32) - (i32.const 0) - (i32.const 3) - ) + (catch + (drop + (pop exnref) ) ) ) - (try $label$8 + (try (do - (nop) + (call $1) + (call $2) ) - (catch $tag$3 + (catch (drop - (pop anyref) - ) - ) - ) - ) - (func $6 - (try $label$6 - (do - (block $label$1 - (try $label$4 - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (delegate $label$6) - ) + (pop exnref) ) + (call $1) + (call $2) ) ) ) diff -Nru binaryen-108/test/exception-handling.wast.from-wast binaryen-99/test/exception-handling.wast.from-wast --- binaryen-108/test/exception-handling.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/exception-handling.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,396 +1,74 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i64_=>_none (func (param i64))) - (type $i32_i64_=>_none (func (param i32 i64))) - (type $anyref_=>_none (func (param anyref))) - (tag $e-i32 (param i32)) - (tag $e-i64 (param i64)) - (tag $e-i32-i64 (param i32 i64)) - (tag $e-anyref (param anyref)) - (tag $e-empty (param)) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_exnref (func (param exnref) (result exnref))) + (event $e0 (attr 0) (param i32)) + (event $e1 (attr 0) (param externref)) + (func $exnref_test (param $0 exnref) (result exnref) + (local.get $0) + ) (func $foo (nop) ) (func $bar (nop) ) - (func $eh-test - (local $x (i32 i64)) - (try $try + (func $eh_test + (local $exn exnref) + (try (do - (throw $e-i32 + (throw $e0 (i32.const 0) ) ) - (catch $e-i32 - (drop - (pop i32) - ) - ) - ) - (try $try0 - (do - (throw $e-i32-i64 - (i32.const 0) - (i64.const 0) - ) - ) - (catch $e-i32-i64 - (local.set $x - (pop i32 i64) + (catch + (local.set $exn + (pop exnref) ) (drop - (tuple.extract 0 - (local.get $x) + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e0 + (local.get $exn) + ) + ) ) ) ) ) - (block $l11 - (try $l1 + (block $l1 + (try (do - (br $l11) + (br $l1) ) - (catch $e-i32 - (drop - (pop i32) - ) - (br $l11) + (catch + (br $l1) ) ) ) - (try $try2 + (try (do (nop) ) - (catch $e-i32 + (catch (drop - (pop i32) + (pop exnref) ) ) ) - (try $try3 + (try (do (call $foo) (call $bar) ) - (catch $e-i32 - (drop - (pop i32) - ) - (call $foo) - (call $bar) - ) - ) - (try $try4 - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (catch $e-i32 + (catch (drop - (pop i32) + (pop exnref) ) - ) - (catch $e-i64 - (drop - (pop i64) - ) - ) - ) - (try $try5 - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (catch_all - (nop) - ) - ) - (try $try6 - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (catch $e-i32 - (drop - (pop i32) - ) - ) - (catch $e-i64 - (drop - (pop i64) - ) - ) - (catch_all (call $foo) (call $bar) ) ) - (try $try7 - (do - (try $try8 - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (catch $e-i32 - (drop - (pop i32) - ) - ) - (catch_all - (nop) - ) - ) - ) - (catch $e-i32 - (drop - (pop i32) - ) - ) - (catch_all - (try $try9 - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (catch $e-i32 - (drop - (pop i32) - ) - ) - (catch_all - (nop) - ) - ) - ) - ) - (try $try10 - (do - (throw $e-i32 - (i32.const 0) - ) - ) - ) - ) - (func $delegate-test - (try $l0 - (do - (try $try - (do - (call $foo) - ) - (delegate $l0) - ) - (try $try11 - (do - (call $foo) - ) - (delegate $l0) - ) - ) - (catch_all - (nop) - ) - ) - (block $l015 - (try $l012 - (do - (try $try13 - (do - (br_if $l015 - (i32.const 1) - ) - ) - (delegate $l012) - ) - (try $try14 - (do - (br_if $l015 - (i32.const 1) - ) - ) - (delegate $l012) - ) - ) - (catch_all - (nop) - ) - ) - ) - (try $l016 - (do - (try $try17 - (do - (call $foo) - ) - (delegate $l016) - ) - ) - (delegate 0) - ) - (try $try18 - (do - (nop) - ) - (catch $e-empty - (nop) - ) - ) - ) - (func $rethrow-test - (try $l0 - (do - (call $foo) - ) - (catch $e-i32 - (drop - (pop i32) - ) - (rethrow $l0) - ) - (catch_all - (rethrow $l0) - ) - ) - (block $l020 - (try $l019 - (do - (call $foo) - ) - (catch $e-i32 - (drop - (pop i32) - ) - (rethrow $l019) - ) - (catch_all - (br $l020) - ) - ) - ) - (try $l021 - (do - (call $foo) - ) - (catch_all - (try $try - (do - (call $foo) - ) - (catch $e-i32 - (drop - (pop i32) - ) - (rethrow $l021) - ) - (catch_all - (rethrow $l021) - ) - ) - ) - ) - (try $l022 - (do - (call $foo) - ) - (catch_all - (try $try23 - (do - (call $foo) - ) - (catch $e-i32 - (drop - (pop i32) - ) - (block $b0 - (rethrow $l022) - ) - ) - (catch_all - (block $b1 - (rethrow $l022) - ) - ) - ) - ) - ) - (try $l024 - (do - (call $foo) - ) - (catch_all - (try $try25 - (do - (rethrow $l024) - ) - (catch_all - (nop) - ) - ) - ) - ) - (try $l026 - (do - (call $foo) - ) - (catch_all - (try $try27 - (do - (rethrow $l026) - ) - (catch_all - (nop) - ) - ) - ) - ) - ) - (func $pop-test - (try $try - (do - (nop) - ) - (catch $e-i32 - (throw $e-i32 - (if (result i32) - (pop i32) - (i32.const 0) - (i32.const 3) - ) - ) - ) - ) - (try $try28 - (do - (nop) - ) - (catch $e-anyref - (drop - (pop funcref) - ) - ) - ) - ) - (func $catchless-try-with-inner-delegate - (try $label$0 - (do - (try $try - (do - (throw $e-i32 - (i32.const 0) - ) - ) - (delegate $label$0) - ) - ) - ) ) ) diff -Nru binaryen-108/test/export-import.wast.fromBinary binaryen-99/test/export-import.wast.fromBinary --- binaryen-108/test/export-import.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/export-import.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $v (func)) + (type $none_=>_none (func)) (import "env" "test2" (global $test2 i32)) (import "env" "test1" (func $test1)) (export "test1" (func $test1)) diff -Nru binaryen-108/test/export-import.wast.from-wast binaryen-99/test/export-import.wast.from-wast --- binaryen-108/test/export-import.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/export-import.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $v (func)) + (type $none_=>_none (func)) (import "env" "test2" (global $test2 i32)) (import "env" "test1" (func $test1)) (export "test1" (func $test1)) diff -Nru binaryen-108/test/extended-names.wast binaryen-99/test/extended-names.wast --- binaryen-108/test/extended-names.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/extended-names.wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,5 +2,5 @@ (table $t1 1 funcref) (memory $m1 1 1) (data $mydata (i32.const 0) "a") - (data $passive_data "b") + (data $passive_data passive "b") ) diff -Nru binaryen-108/test/extended-names.wast.fromBinary binaryen-99/test/extended-names.wast.fromBinary --- binaryen-108/test/extended-names.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/extended-names.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module $foo (memory $m1 1 1) (data $mydata (i32.const 0) "a") - (data $passive_data "b") + (data $passive_data passive "b") (table $t1 1 funcref) ) diff -Nru binaryen-108/test/extended-names.wast.fromBinary.noDebugInfo binaryen-99/test/extended-names.wast.fromBinary.noDebugInfo --- binaryen-108/test/extended-names.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/extended-names.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (memory $0 1 1) (data (i32.const 0) "a") - (data "b") + (data passive "b") (table $0 1 funcref) ) diff -Nru binaryen-108/test/extended-names.wast.from-wast binaryen-99/test/extended-names.wast.from-wast --- binaryen-108/test/extended-names.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/extended-names.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module $foo (memory $m1 1 1) (data $mydata (i32.const 0) "a") - (data $passive_data "b") + (data $passive_data passive "b") (table $t1 1 funcref) ) diff -Nru binaryen-108/test/extra-unreachable.wast binaryen-99/test/extra-unreachable.wast --- binaryen-108/test/extra-unreachable.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/extra-unreachable.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,196 @@ +(module + (type $ii (func (param i32) (result i32))) + (memory (shared 1 1)) + (table 0 funcref) + (global $g (mut f32) (f32.const 0)) + (event $e (attr 0) (param i32)) + + (func $foo (param i32) (result i32) (i32.const 0)) + + (func $test_function_block + ;; block, which has unreachable type, can be omitted here because it is the + ;; only expression within a function. We emit an extra unreachable at the + ;; end. + (block + (unreachable) + (nop) + ) + ) + + (func $test + ;; block has unreachable type. We emit an unreachable at the end of the + ;; block and also outside the block too. + (block + (i32.eqz (unreachable)) + ) + + ;; If an if's condition is unreachable, don't emit the if and emit an + ;; unreachable instead. + (if + (unreachable) + (nop) + (nop) + ) + + ;; If an if is unreachable, i.e., the both sides are unreachable, we emit + ;; an extra unreachable after the if. + (if + (i32.const 1) + (unreachable) + (unreachable) + ) + + ;; If a try is unreachable, i.e., both the 'try' and 'catch' bodies are + ;; unreachable, we emit an extra unreachable after the try. + (try + (do + (unreachable) + ) + (catch + (unreachable) + ) + ) + + ;; If a br_if/br_on_exn's type is unreachable, emit an extra unreachable + ;; after it + (block + (br_if 0 (unreachable)) + ) + (drop + (block (result i32) + (br_on_exn 0 $e (unreachable)) + ) + ) + + ;; If a br_table is not reachable, emit an unreachable instead + (block $l + (block $default + (br_table $l $default + (unreachable) + ) + ) + ) + + ;; For all tests below, when a value-returning expression is unreachable, + ;; emit an unreachable instead of the operation, to prevent it from being + ;; consumed by the next operation. + ;; + ;; Here global.set is used to consume the value. If an unreachable is not + ;; emitted, the instruction itself will be consumed by global.set and will + ;; result in a type validation failure, because it expects a f32 but gets an + ;; i32. The reason we use global.set is the instruction does not return a + ;; value, so it will be emitted even if its argument is unreachable. + + ;; call / call_indirect + (global.set $g + (call $foo (unreachable)) + ) + (global.set $g + (call_indirect (type $ii) (unreachable) (unreachable)) + ) + + ;; unary + (global.set $g + (i32.eqz (unreachable)) + ) + + ;; binary + (global.set $g + (i32.add + (unreachable) + (i32.const 0) + ) + ) + + ;; select + (global.set $g + (select + (unreachable) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; load + (global.set $g + (i32.load (unreachable)) + ) + (global.set $g + (i32.atomic.load (unreachable)) + ) + + ;; atomic.rmw + (global.set $g + (i32.atomic.rmw.add + (unreachable) + (i32.const 0) + ) + ) + + ;; atomic.cmpxchg + (global.set $g + (i32.atomic.rmw.cmpxchg + (unreachable) + (i32.const 0) + (i32.const 0) + ) + ) + + ;; atomic.wait + (global.set $g + (memory.atomic.wait32 + (unreachable) + (i32.const 0) + (i64.const 0) + ) + ) + + ;; memory.atomic.notify + (global.set $g + (memory.atomic.notify + (unreachable) + (i32.const 0) + ) + ) + + ;; SIMD extract + (global.set $g + (i32x4.extract_lane 0 + (unreachable) + ) + ) + + ;; SIMD replace + (global.set $g + (i32x4.replace_lane 0 + (unreachable) + (i32.const 0) + ) + ) + + ;; SIMD shuffle + (global.set $g + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 + (unreachable) + (unreachable) + ) + ) + + ;; SIMD bitselect + (global.set $g + (v128.bitselect + (unreachable) + (unreachable) + (unreachable) + ) + ) + + ;; SIMD shift + (global.set $g + (i32x4.shl + (unreachable) + (i32.const 0) + ) + ) + ) +) diff -Nru binaryen-108/test/extra-unreachable.wast.fromBinary binaryen-99/test/extra-unreachable.wast.fromBinary --- binaryen-108/test/extra-unreachable.wast.fromBinary 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/extra-unreachable.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,21 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (memory $0 (shared 1 1)) + (table $0 0 funcref) + (global $g (mut f32) (f32.const 0)) + (event $event$0 (attr 0) (param i32)) + (func $foo (param $0 i32) (result i32) + (i32.const 0) + ) + (func $test_function_block + (unreachable) + ) + (func $test + (block $label$1 + (unreachable) + ) + ) +) + diff -Nru binaryen-108/test/extra-unreachable.wast.fromBinary.noDebugInfo binaryen-99/test/extra-unreachable.wast.fromBinary.noDebugInfo --- binaryen-108/test/extra-unreachable.wast.fromBinary.noDebugInfo 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/extra-unreachable.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,21 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (memory $0 (shared 1 1)) + (table $0 0 funcref) + (global $global$0 (mut f32) (f32.const 0)) + (event $event$0 (attr 0) (param i32)) + (func $0 (param $0 i32) (result i32) + (i32.const 0) + ) + (func $1 + (unreachable) + ) + (func $2 + (block $label$1 + (unreachable) + ) + ) +) + diff -Nru binaryen-108/test/extra-unreachable.wast.from-wast binaryen-99/test/extra-unreachable.wast.from-wast --- binaryen-108/test/extra-unreachable.wast.from-wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/extra-unreachable.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,157 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (memory $0 (shared 1 1)) + (table $0 0 funcref) + (global $g (mut f32) (f32.const 0)) + (event $e (attr 0) (param i32)) + (func $foo (param $0 i32) (result i32) + (i32.const 0) + ) + (func $test_function_block + (block $block + (unreachable) + (nop) + ) + ) + (func $test + (block $block + (i32.eqz + (unreachable) + ) + ) + (if + (unreachable) + (nop) + (nop) + ) + (if + (i32.const 1) + (unreachable) + (unreachable) + ) + (try + (do + (unreachable) + ) + (catch + (unreachable) + ) + ) + (block $block1 + (br_if $block1 + (unreachable) + ) + ) + (drop + (block $block2 (result i32) + (br_on_exn $block2 $e + (unreachable) + ) + ) + ) + (block $l + (block $default + (br_table $l $default + (unreachable) + ) + ) + ) + (global.set $g + (call $foo + (unreachable) + ) + ) + (global.set $g + (call_indirect (type $i32_=>_i32) + (unreachable) + (unreachable) + ) + ) + (global.set $g + (i32.eqz + (unreachable) + ) + ) + (global.set $g + (i32.add + (unreachable) + (i32.const 0) + ) + ) + (global.set $g + (select + (unreachable) + (i32.const 0) + (i32.const 0) + ) + ) + (global.set $g + (i32.load + (unreachable) + ) + ) + (global.set $g + (i32.atomic.load + (unreachable) + ) + ) + (global.set $g + (i32.atomic.rmw.add + (unreachable) + (i32.const 0) + ) + ) + (global.set $g + (i32.atomic.rmw.cmpxchg + (unreachable) + (i32.const 0) + (i32.const 0) + ) + ) + (global.set $g + (memory.atomic.wait32 + (unreachable) + (i32.const 0) + (i64.const 0) + ) + ) + (global.set $g + (memory.atomic.notify + (unreachable) + (i32.const 0) + ) + ) + (global.set $g + (i32x4.extract_lane 0 + (unreachable) + ) + ) + (global.set $g + (i32x4.replace_lane 0 + (unreachable) + (i32.const 0) + ) + ) + (global.set $g + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 + (unreachable) + (unreachable) + ) + ) + (global.set $g + (v128.bitselect + (unreachable) + (unreachable) + (unreachable) + ) + ) + (global.set $g + (i32x4.shl + (unreachable) + (i32.const 0) + ) + ) + ) +) diff -Nru binaryen-108/test/fannkuch.cpp binaryen-99/test/fannkuch.cpp --- binaryen-108/test/fannkuch.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/fannkuch.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -9,144 +9,151 @@ * Modified for emscripten by azakai */ -#include #include +#include struct worker_args { - int i, n; - struct worker_args* next; + int i, n; + struct worker_args *next; }; -int fannkuch_worker(void* _arg) { - struct worker_args* args = (worker_args*)_arg; - int *perm1, *count, *perm; - int maxflips, flips, i, n, r, j, k, tmp; - - maxflips = 0; - n = args->n; - perm1 = (int*)malloc(n * sizeof(int)); - perm = (int*)malloc(n * sizeof(int)); - count = (int*)malloc(n * sizeof(int)); - for (i = 0; i < n; i++) - perm1[i] = i; - perm1[args->i] = n - 1; - perm1[n - 1] = args->i; - r = n; - - for (;;) { - for (; r > 1; r--) - count[r - 1] = r; - if (perm1[0] != 0 && perm1[n - 1] != n - 1) { - for (i = 0; i < n; i++) - perm[i] = perm1[i]; - flips = 0; - k = perm[0]; - do { - for (i = 1, j = k - 1; i < j; i++, j--) { - tmp = perm[i]; - perm[i] = perm[j]; - perm[j] = tmp; - } - flips++; - tmp = perm[k]; - perm[k] = k; - k = tmp; - } while (k); - if (maxflips < flips) - maxflips = flips; - } - for (;;) { - if (r >= n - 1) { - free(perm1); - free(perm); - free(count); - return maxflips; +int +fannkuch_worker(void *_arg) +{ + struct worker_args *args = (worker_args*)_arg; + int *perm1, *count, *perm; + int maxflips, flips, i, n, r, j, k, tmp; + + maxflips = 0; + n = args->n; + perm1 = (int*)malloc(n * sizeof(int)); + perm = (int*)malloc(n * sizeof(int)); + count = (int*)malloc(n * sizeof(int)); + for (i = 0; i < n; i++) + perm1[i] = i; + perm1[args->i] = n - 1; + perm1[n - 1] = args->i; + r = n; + + for (;;) { + for (; r > 1; r--) + count[r - 1] = r; + if (perm1[0] != 0 && perm1[n - 1] != n - 1) { + for (i = 0; i < n; i++) + perm[i] = perm1[i]; + flips = 0; + k = perm[0]; + do { + for (i = 1, j = k - 1; i < j; i++, j--) { + tmp = perm[i]; + perm[i] = perm[j]; + perm[j] = tmp; + } + flips++; + tmp = perm[k]; + perm[k] = k; + k = tmp; + } while (k); + if (maxflips < flips) + maxflips = flips; } - - { - int p0 = perm1[0]; - for (i = 0; i < r; i++) - perm1[i] = perm1[i + 1]; - perm1[i] = p0; + for (;;) { + if (r >= n - 1) { + free(perm1); + free(perm); + free(count); + return maxflips; + } + + { + int p0 = perm1[0]; + for (i = 0; i < r; i++) + perm1[i] = perm1[i + 1]; + perm1[i] = p0; + } + if (--count[r] > 0) + break; + r++; } - if (--count[r] > 0) - break; - r++; - } - } + } } -static int fannkuch(int n) { - struct worker_args *args, *targs; - int showmax = 30; - int *perm1, *count, i, r, maxflips, flips; - - args = NULL; - for (i = 0; i < n - 1; i++) { - targs = (worker_args*)malloc(sizeof(struct worker_args)); - targs->i = i; - targs->n = n; - targs->next = args; - args = targs; - } - - perm1 = (int*)malloc(n * sizeof(int)); - count = (int*)malloc(n * sizeof(int)); - - for (i = 0; i < n; i++) - perm1[i] = i; - - r = n; - for (;;) { - if (showmax) { - for (i = 0; i < n; i++) - printf("%d", perm1[i] + 1); - printf("\n"); - showmax--; - } else - goto cleanup; - - for (; r > 1; r--) - count[r - 1] = r; - - for (;;) { - if (r == n) - goto cleanup; - { - int p0 = perm1[0]; - for (i = 0; i < r; i++) - perm1[i] = perm1[i + 1]; - perm1[i] = p0; +static int +fannkuch(int n) +{ + struct worker_args *args, *targs; + int showmax = 30; + int *perm1, *count, i, r, maxflips, flips; + + args = NULL; + for (i = 0; i < n - 1; i++) { + targs = (worker_args*)malloc(sizeof(struct worker_args)); + targs->i = i; + targs->n = n; + targs->next = args; + args = targs; + } + + perm1 = (int*)malloc(n * sizeof(int)); + count = (int*)malloc(n * sizeof(int)); + + for (i = 0; i < n; i++) + perm1[i] = i; + + r = n; + for (;;) { + if (showmax) { + for (i = 0; i < n; i++) + printf("%d", perm1[i] + 1); + printf("\n"); + showmax--; + } else + goto cleanup; + + for (; r > 1; r--) + count[r - 1] = r; + + for (;;) { + if (r == n) + goto cleanup; + { + int p0 = perm1[0]; + for (i = 0; i < r; i++) + perm1[i] = perm1[i + 1]; + perm1[i] = p0; + } + if (--count[r] > 0) + break; + + r++; } - if (--count[r] > 0) - break; + } - r++; - } - } - -cleanup: - free(perm1); - free(count); - maxflips = 0; - while (args != NULL) { - flips = (int)fannkuch_worker(args); - if (maxflips < flips) - maxflips = flips; - targs = args; - args = args->next; - free(targs); - } - return maxflips; + cleanup: + free(perm1); + free(count); + maxflips = 0; + while (args != NULL) { + flips = (int)fannkuch_worker(args); + if (maxflips < flips) + maxflips = flips; + targs = args; + args = args->next; + free(targs); + } + return maxflips; } -int main(int argc, char** argv) { - int n = argc > 1 ? atoi(argv[1]) : 0; - - if (n < 1) { - printf("Wrong argument.\n"); - return 1; - } - printf("Pfannkuchen(%d) = %d.\n", n, fannkuch(n)); - return 0; +int +main(int argc, char **argv) +{ + int n = argc > 1 ? atoi(argv[1]) : 0; + + if (n < 1) { + printf("Wrong argument.\n"); + return 1; + } + printf("Pfannkuchen(%d) = %d.\n", n, fannkuch(n)); + return 0; } + diff -Nru binaryen-108/test/fasta.cpp binaryen-99/test/fasta.cpp --- binaryen-108/test/fasta.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/fasta.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -8,7 +8,8 @@ #include // limit output, so we do not benchmark speed of printing -void puts_limited(char* x) { +void puts_limited(char *x) +{ static int left = 550; int len = strlen(x); if (len <= left) { @@ -25,175 +26,173 @@ } struct Random { - enum { IM = 139968, IA = 3877, IC = 29573 }; - Random() : last(42) {} - float get(float max = 1.0f) { - last = (last * IA + IC) % IM; - return max * last / IM; - } - + enum { IM = 139968, IA = 3877, IC = 29573 }; + Random() : last(42) {} + float get( float max = 1.0f ) { + last = ( last * IA + IC ) % IM; + return max * last / IM; + } protected: - unsigned int last; + unsigned int last; } rng; struct IUB { - int c; - double p; - unsigned int pi; + int c; + double p; + unsigned int pi; }; struct Cumulative { - enum { - slots = 512, - }; - - Cumulative(IUB* start) { - double p = 0; - for (IUB* iter = start; iter->c; ++iter) { - p += iter->p; - iter->p = p < 1.0 ? p : 1.0; - iter->pi = (unsigned int)(iter->p * slots); - } - - for (unsigned int i = 0; i <= slots; i++) { - while (i > start->pi && start->pi != 0) { - ++start; + enum { slots = 512, }; + + Cumulative( IUB *start ) { + double p = 0; + for ( IUB *iter = start; iter->c; ++iter ) { + p += iter->p; + iter->p = p < 1.0 ? p : 1.0; + iter->pi = (unsigned int )( iter->p * slots ); } - table[i] = start; - } - } + for ( unsigned int i = 0; i <= slots; i++ ) { + while ( i > start->pi && start->pi != 0) { + ++start; + } - const char operator[](float pct) const { - IUB* iter = table[(unsigned int)(pct * slots)]; - while (iter->p < pct) - ++iter; - return iter->c; - } + table[i] = start; + } + } + + const char operator[] ( float pct ) const { + IUB *iter = table[(unsigned int )( pct * slots )]; + while ( iter->p < pct ) + ++iter; + return iter->c; + } protected: - IUB* table[slots + 1]; + IUB *table[slots + 1]; }; static const size_t lineLength = 60; struct LineBuffer { - LineBuffer() : lastN(0) {} - LineBuffer& genrand(Cumulative& table, size_t N) { - // assert(N <= lineLength); - for (size_t i = 0; i < N; i++) - buffer[i] = table[rng.get()]; - buffer[N] = '\n'; - buffer[N + 1] = '\0'; - lastN = N + 1; - return *this; - } - void writeline() { puts_limited(buffer); } - + LineBuffer() : lastN(0) {} + LineBuffer &genrand( Cumulative &table, size_t N ) { + //assert(N <= lineLength); + for ( size_t i = 0; i < N; i++ ) + buffer[i] = table[rng.get()]; + buffer[N] = '\n'; + buffer[N+1] = '\0'; + lastN = N + 1; + return *this; + } + void writeline() { puts_limited(buffer); } protected: - char buffer[lineLength + 2]; - size_t lastN; + char buffer[lineLength + 2]; + size_t lastN; }; struct RotatingString { - RotatingString(const char* in) : pos(0) { - size = strlen(in); - buffer = new char[size + lineLength]; - memcpy(buffer, in, size); - memcpy(buffer + size, in, lineLength); - } - ~RotatingString() { delete[] buffer; } - void write(size_t bytes) { - char* temp = new char[bytes + 2]; - memcpy(temp, buffer + pos, bytes); - temp[bytes] = '\n'; - temp[bytes] = '\0'; - puts_limited(temp); - delete temp; - pos += bytes; - if (pos > size) - pos -= size; - } - -protected: - char* buffer; - size_t size, pos; -}; - -template -void makeFasta(const char* id, const char* desc, size_t N, Output& output) { - while (N) { - const size_t bytes = N < lineLength ? N : lineLength; - output.writeline(bytes); - N -= bytes; - } + RotatingString( const char *in ) : pos(0) { + size = strlen( in ); + buffer = new char[size + lineLength]; + memcpy( buffer, in, size ); + memcpy( buffer + size, in, lineLength ); + } + ~RotatingString() { delete[] buffer; } + void write( size_t bytes ) { + char* temp = new char[bytes+2]; + memcpy(temp, buffer + pos, bytes); + temp[bytes] = '\n'; + temp[bytes] = '\0'; + puts_limited(temp); + delete temp; + pos += bytes; + if ( pos > size ) + pos -= size; + } +protected: + char *buffer; + size_t size, pos; +}; + +template< class Output > +void makeFasta( const char *id, const char *desc, size_t N, Output &output ) { + while ( N ) { + const size_t bytes = N < lineLength ? N : lineLength; + output.writeline( bytes ); + N -= bytes; + } } struct Repeater { - Repeater(const char* alu) : rot(alu) {} - void writeline(size_t bytes) { rot.write(bytes); } - void run(const char* id, const char* desc, size_t N) { - makeFasta(id, desc, N, *this); - } - + Repeater( const char *alu ) : rot(alu) {} + void writeline( size_t bytes ) { rot.write( bytes ); } + void run( const char *id, const char *desc, size_t N ) { + makeFasta( id, desc, N, *this ); + } protected: - RotatingString rot; + RotatingString rot; }; struct Randomized { - Randomized(IUB* start) : table(start) {} - void writeline(size_t bytes) { line.genrand(table, bytes).writeline(); } - void run(const char* id, const char* desc, size_t N) { - makeFasta(id, desc, N, *this); - } - + Randomized( IUB *start ) : table(start) {} + void writeline( size_t bytes ) { line.genrand(table, bytes).writeline(); } + void run( const char *id, const char *desc, size_t N ) { + makeFasta( id, desc, N, *this ); + } protected: - Cumulative table; - LineBuffer line; + Cumulative table; + LineBuffer line; }; IUB iub[] = { - {'a', 0.27, 0}, - {'c', 0.12, 0}, - {'g', 0.12, 0}, - {'t', 0.27, 0}, - - {'B', 0.02, 0}, - {'D', 0.02, 0}, - {'H', 0.02, 0}, - {'K', 0.02, 0}, - {'M', 0.02, 0}, - {'N', 0.02, 0}, - {'R', 0.02, 0}, - {'S', 0.02, 0}, - {'V', 0.02, 0}, - {'W', 0.02, 0}, - {'Y', 0.02, 0}, - {0, 0, 0}, + { 'a', 0.27, 0 }, + { 'c', 0.12, 0 }, + { 'g', 0.12, 0 }, + { 't', 0.27, 0 }, + + { 'B', 0.02, 0 }, + { 'D', 0.02, 0 }, + { 'H', 0.02, 0 }, + { 'K', 0.02, 0 }, + { 'M', 0.02, 0 }, + { 'N', 0.02, 0 }, + { 'R', 0.02, 0 }, + { 'S', 0.02, 0 }, + { 'V', 0.02, 0 }, + { 'W', 0.02, 0 }, + { 'Y', 0.02, 0 }, + { 0, 0, 0 }, }; IUB homosapiens[] = { - {'a', 0.3029549426680, 0}, - {'c', 0.1979883004921, 0}, - {'g', 0.1975473066391, 0}, - {'t', 0.3015094502008, 0}, - {0, 0, 0}, -}; - -static const char alu[] = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG" - "GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA" - "GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA" - "AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT" - "CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC" - "CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG" - "CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; - -int main(int argc, const char* argv[]) { - const size_t n = (argc > 1) ? atoi(argv[1]) : 512; - - Repeater(alu).run("ONE", "Homo sapiens alu", n * 2); - Randomized(iub).run("TWO", "IUB ambiguity codes", n * 3); - Randomized(homosapiens).run("THREE", "Homo sapiens frequency", n * 5); + { 'a', 0.3029549426680, 0 }, + { 'c', 0.1979883004921, 0 }, + { 'g', 0.1975473066391, 0 }, + { 't', 0.3015094502008, 0 }, + { 0, 0, 0 }, +}; + +static const char alu[] = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG" + "GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA" + "GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA" + "AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT" + "CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC" + "CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG" + "CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + +int main( int argc, const char *argv[] ) { + const size_t n = ( argc > 1 ) ? atoi( argv[1] ) : 512; + + Repeater(alu) + .run( "ONE", "Homo sapiens alu", n*2 ); + Randomized(iub) + .run( "TWO", "IUB ambiguity codes", n*3 ); + Randomized(homosapiens) + .run( "THREE", "Homo sapiens frequency", n*5 ); - return 0; + return 0; } + diff -Nru binaryen-108/test/fib-dbg.wasm.fromBinary binaryen-99/test/fib-dbg.wasm.fromBinary --- binaryen-108/test/fib-dbg.wasm.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/fib-dbg.wasm.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_none (func (param i32 i32))) - (type $none_=>_i32 (func (result i32))) - (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (import "env" "table" (table $timport$0 0 0 funcref)) (import "env" "DYNAMICTOP_PTR" (global $gimport$0 i32)) diff -Nru binaryen-108/test/float_ops.cpp binaryen-99/test/float_ops.cpp --- binaryen-108/test/float_ops.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/float_ops.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ -#include #include +#include #include extern "C" { @@ -13,9 +13,7 @@ double EMSCRIPTEN_KEEPALIVE dsub(double x, double y) { return x - y; } double EMSCRIPTEN_KEEPALIVE dmul(double x, double y) { return x * y; } double EMSCRIPTEN_KEEPALIVE ddiv(double x, double y) { return x / y; } -double EMSCRIPTEN_KEEPALIVE dcopysign(double x, double y) { - return std::copysign(x, y); -} +double EMSCRIPTEN_KEEPALIVE dcopysign(double x, double y) { return std::copysign(x, y); } double EMSCRIPTEN_KEEPALIVE dmin(double x, double y) { return std::min(x, y); } double EMSCRIPTEN_KEEPALIVE dmax(double x, double y) { return std::max(x, y); } @@ -70,4 +68,6 @@ unsigned x = d; return x; } + } + diff -Nru binaryen-108/test/gc.wast binaryen-99/test/gc.wast --- binaryen-108/test/gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gc.wast 2021-01-07 20:01:06.000000000 +0000 @@ -15,12 +15,10 @@ (global $global_eqref2 (mut eqref) (i31.new (i32.const 0))) (func $test - (param $local_i31ref i31ref) - (param $local_dataref dataref) - (local $local_i32 i32) (local $local_anyref anyref) (local $local_eqref eqref) + (local $local_i31ref i31ref) ;; Test types for local.get/set (local.set $local_anyref (local.get $local_anyref)) @@ -72,9 +70,7 @@ ) (func $test-variants - (param $local_i31refnull (ref null i31)) - (param $local_i31refnonnull (ref i31)) - (param $local_datarefnull (ref null data)) - (param $local_datarefnonnull (ref data)) + (local $local_i31refnull (ref null i31)) + (local $local_i31refnonnull (ref i31)) ) ) diff -Nru binaryen-108/test/gc.wast.fromBinary binaryen-99/test/gc.wast.fromBinary --- binaryen-108/test/gc.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gc.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,8 @@ (module - (type $i31ref_dataref_=>_none (func (param i31ref dataref))) - (type $ref?|i31|_i31ref_ref?|data|_dataref_=>_none (func (param (ref null i31) i31ref (ref null data) dataref))) + (type $none_=>_none (func)) (global $global_anyref (mut anyref) (ref.null any)) (global $global_eqref (mut eqref) (ref.null eq)) - (global $global_i31ref (mut i31ref) (i31.new + (global $global_i31ref (mut (ref null i31)) (i31.new (i32.const 0) )) (global $global_anyref2 (mut anyref) (ref.null eq)) @@ -13,10 +12,11 @@ (global $global_eqref2 (mut eqref) (i31.new (i32.const 0) )) - (func $test (param $local_i31ref i31ref) (param $local_dataref dataref) + (func $test (local $local_i32 i32) (local $local_anyref anyref) (local $local_eqref eqref) + (local $local_i31ref (ref null i31)) (local.set $local_anyref (local.get $local_anyref) ) @@ -148,7 +148,9 @@ ) ) ) - (func $test-variants (param $local_i31refnull (ref null i31)) (param $local_i31refnonnull i31ref) (param $local_datarefnull (ref null data)) (param $local_datarefnonnull dataref) + (func $test-variants + (local $local_i31refnull (ref null i31)) + (local $local_i31refnonnull (ref null i31)) (nop) ) ) diff -Nru binaryen-108/test/gc.wast.fromBinary.noDebugInfo binaryen-99/test/gc.wast.fromBinary.noDebugInfo --- binaryen-108/test/gc.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gc.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,8 @@ (module - (type $i31ref_dataref_=>_none (func (param i31ref dataref))) - (type $ref?|i31|_i31ref_ref?|data|_dataref_=>_none (func (param (ref null i31) i31ref (ref null data) dataref))) + (type $none_=>_none (func)) (global $global$0 (mut anyref) (ref.null any)) (global $global$1 (mut eqref) (ref.null eq)) - (global $global$2 (mut i31ref) (i31.new + (global $global$2 (mut (ref null i31)) (i31.new (i32.const 0) )) (global $global$3 (mut anyref) (ref.null eq)) @@ -13,72 +12,73 @@ (global $global$5 (mut eqref) (i31.new (i32.const 0) )) - (func $0 (param $0 i31ref) (param $1 dataref) - (local $2 i32) - (local $3 anyref) - (local $4 eqref) - (local.set $3 - (local.get $3) + (func $0 + (local $0 i32) + (local $1 anyref) + (local $2 eqref) + (local $3 (ref null i31)) + (local.set $1 + (local.get $1) ) - (local.set $3 + (local.set $1 (global.get $global$0) ) - (local.set $3 + (local.set $1 (ref.null any) ) - (local.set $4 - (local.get $4) + (local.set $2 + (local.get $2) ) - (local.set $4 + (local.set $2 (global.get $global$1) ) - (local.set $4 + (local.set $2 (ref.null eq) ) - (local.set $0 - (local.get $0) + (local.set $3 + (local.get $3) ) - (local.set $0 + (local.set $3 (global.get $global$2) ) - (local.set $0 + (local.set $3 (i31.new (i32.const 0) ) ) - (local.set $3 - (local.get $4) + (local.set $1 + (local.get $2) ) - (local.set $3 + (local.set $1 (global.get $global$1) ) - (local.set $3 + (local.set $1 (ref.null eq) ) - (local.set $3 - (local.get $0) + (local.set $1 + (local.get $3) ) - (local.set $3 + (local.set $1 (global.get $global$2) ) - (local.set $3 + (local.set $1 (i31.new (i32.const 0) ) ) - (local.set $4 - (local.get $0) + (local.set $2 + (local.get $3) ) - (local.set $4 + (local.set $2 (global.get $global$2) ) - (local.set $4 + (local.set $2 (i31.new (i32.const 0) ) ) (global.set $global$0 - (local.get $3) + (local.get $1) ) (global.set $global$0 (global.get $global$0) @@ -87,7 +87,7 @@ (ref.null any) ) (global.set $global$1 - (local.get $4) + (local.get $2) ) (global.set $global$1 (global.get $global$1) @@ -96,7 +96,7 @@ (ref.null eq) ) (global.set $global$2 - (local.get $0) + (local.get $3) ) (global.set $global$2 (global.get $global$2) @@ -107,7 +107,7 @@ ) ) (global.set $global$0 - (local.get $4) + (local.get $2) ) (global.set $global$0 (global.get $global$1) @@ -116,7 +116,7 @@ (ref.null eq) ) (global.set $global$0 - (local.get $0) + (local.get $3) ) (global.set $global$0 (global.get $global$2) @@ -127,7 +127,7 @@ ) ) (global.set $global$1 - (local.get $0) + (local.get $3) ) (global.set $global$1 (global.get $global$2) @@ -137,18 +137,20 @@ (i32.const 0) ) ) - (local.set $2 + (local.set $0 (i31.get_s - (local.get $0) + (local.get $3) ) ) - (local.set $2 + (local.set $0 (i31.get_u - (local.get $0) + (local.get $3) ) ) ) - (func $1 (param $0 (ref null i31)) (param $1 i31ref) (param $2 (ref null data)) (param $3 dataref) + (func $1 + (local $0 (ref null i31)) + (local $1 (ref null i31)) (nop) ) ) diff -Nru binaryen-108/test/gc.wast.from-wast binaryen-99/test/gc.wast.from-wast --- binaryen-108/test/gc.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gc.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,8 @@ (module - (type $i31ref_dataref_=>_none (func (param i31ref dataref))) - (type $ref?|i31|_i31ref_ref?|data|_dataref_=>_none (func (param (ref null i31) i31ref (ref null data) dataref))) + (type $none_=>_none (func)) (global $global_anyref (mut anyref) (ref.null any)) (global $global_eqref (mut eqref) (ref.null eq)) - (global $global_i31ref (mut i31ref) (i31.new + (global $global_i31ref (mut (ref null i31)) (i31.new (i32.const 0) )) (global $global_anyref2 (mut anyref) (ref.null eq)) @@ -13,10 +12,11 @@ (global $global_eqref2 (mut eqref) (i31.new (i32.const 0) )) - (func $test (param $local_i31ref i31ref) (param $local_dataref dataref) + (func $test (local $local_i32 i32) (local $local_anyref anyref) (local $local_eqref eqref) + (local $local_i31ref (ref null i31)) (local.set $local_anyref (local.get $local_anyref) ) @@ -148,7 +148,9 @@ ) ) ) - (func $test-variants (param $local_i31refnull (ref null i31)) (param $local_i31refnonnull i31ref) (param $local_datarefnull (ref null data)) (param $local_datarefnonnull dataref) + (func $test-variants + (local $local_i31refnull (ref null i31)) + (local $local_i31refnonnull (ref null i31)) (nop) ) ) diff -Nru binaryen-108/test/grow_memory.cpp binaryen-99/test/grow_memory.cpp --- binaryen-108/test/grow_memory.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/grow_memory.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,20 @@ -#include #include #include +#include volatile int writeOnly; int main() { - EM_ASM({ assert(HEAPU8.length == = 16 * 1024 * 1024); }); + EM_ASM({ + assert(HEAPU8.length === 16*1024*1024); + }); for (int i = 0; i < 20; i++) { printf("alloc 1MB: %d\n", i); - writeOnly = (int)malloc(1024 * 1024); + writeOnly = (int)malloc(1024*1024); } - EM_ASM({ assert(HEAPU8.length > 16 * 1024 * 1024); }); + EM_ASM({ + assert(HEAPU8.length > 16*1024*1024); + }); printf("ok.\n"); } + diff -Nru binaryen-108/test/grow_memory.wast.fromBinary binaryen-99/test/grow_memory.wast.fromBinary --- binaryen-108/test/grow_memory.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/grow_memory.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $0 (func (param i32) (result i32))) - (type $1 (func (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 1) (export "memory" (memory $0)) (export "grow" (func $0)) diff -Nru binaryen-108/test/grow_memory.wast.fromBinary.noDebugInfo binaryen-99/test/grow_memory.wast.fromBinary.noDebugInfo --- binaryen-108/test/grow_memory.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/grow_memory.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 1) (export "memory" (memory $0)) (export "grow" (func $0)) diff -Nru binaryen-108/test/grow_memory.wast.from-wast binaryen-99/test/grow_memory.wast.from-wast --- binaryen-108/test/grow_memory.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/grow_memory.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $0 (func (param i32) (result i32))) - (type $1 (func (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 1) (export "memory" (memory $0)) (export "grow" (func $0)) diff -Nru binaryen-108/test/gtest/CMakeLists.txt binaryen-99/test/gtest/CMakeLists.txt --- binaryen-108/test/gtest/CMakeLists.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gtest/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -include_directories(../../third_party/googletest/googletest/include) - -set(unittest_SOURCES - type-builder.cpp -) - -binaryen_add_executable(binaryen-unittests "${unittest_SOURCES}") -target_link_libraries(binaryen-unittests gtest gtest_main) diff -Nru binaryen-108/test/gtest/type-builder.cpp binaryen-99/test/gtest/type-builder.cpp --- binaryen-108/test/gtest/type-builder.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gtest/type-builder.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,500 +0,0 @@ -#include "type-test.h" -#include "wasm-type-printing.h" -#include "wasm-type.h" -#include "gtest/gtest.h" - -using namespace wasm; - -TEST_F(TypeTest, TypeBuilderGrowth) { - TypeBuilder builder; - EXPECT_EQ(builder.size(), 0u); - builder.grow(3); - EXPECT_EQ(builder.size(), 3u); -} - -TEST_F(TypeTest, TypeIterator) { - Type none = Type::none; - Type i32 = Type::i32; - Type i64 = Type::i64; - Type f32 = Type::f32; - Type f64 = Type::f64; - Type tuple = Tuple{i32, i64, f32, f64}; - - EXPECT_EQ(none.size(), 0u); - EXPECT_EQ(none.begin(), none.end()); - EXPECT_EQ(none.end() - none.begin(), 0u); - EXPECT_EQ(none.begin() + 0, none.end()); - - EXPECT_EQ(i32.size(), 1u); - EXPECT_NE(i32.begin(), i32.end()); - EXPECT_EQ(i32.end() - i32.begin(), 1u); - - EXPECT_EQ(*i32.begin(), i32); - EXPECT_EQ(i32[0], i32); - - EXPECT_EQ(i32.begin() + 1, i32.end()); - EXPECT_EQ(i32.end() - 1, i32.begin()); - - auto preInc = i32.begin(); - EXPECT_EQ(++preInc, i32.end()); - EXPECT_EQ(preInc, i32.end()); - - auto postInc = i32.begin(); - EXPECT_EQ(postInc++, i32.begin()); - EXPECT_EQ(postInc, i32.end()); - - auto preDec = i32.end(); - EXPECT_EQ(--preDec, i32.begin()); - EXPECT_EQ(preDec, i32.begin()); - - auto postDec = i32.end(); - EXPECT_EQ(postDec--, i32.end()); - EXPECT_EQ(postDec, i32.begin()); - - EXPECT_EQ(tuple.size(), 4u); - EXPECT_NE(tuple.begin(), tuple.end()); - EXPECT_EQ(tuple.end() - tuple.begin(), 4u); - - EXPECT_EQ(*tuple.begin(), i32); - EXPECT_EQ(*(tuple.begin() + 1), i64); - EXPECT_EQ(*(tuple.begin() + 2), f32); - EXPECT_EQ(*(tuple.begin() + 3), f64); - EXPECT_EQ(tuple[0], i32); - EXPECT_EQ(tuple[1], i64); - EXPECT_EQ(tuple[2], f32); - EXPECT_EQ(tuple[3], f64); - - auto reverse = tuple.rbegin(); - EXPECT_EQ(*reverse++, f64); - EXPECT_EQ(*reverse++, f32); - EXPECT_EQ(*reverse++, i64); - EXPECT_EQ(*reverse++, i32); - EXPECT_EQ(reverse, tuple.rend()); -} - -TEST_F(TypeTest, IndexedTypePrinter) { - TypeBuilder builder(4); - builder.createRecGroup(0, 4); - - Type refStructA = builder.getTempRefType(builder[0], Nullable); - Type refStructB = builder.getTempRefType(builder[1], Nullable); - Type refArrayA = builder.getTempRefType(builder[2], Nullable); - Type refArrayB = builder.getTempRefType(builder[3], Nullable); - builder[0] = Struct({Field(refArrayB, Immutable)}); - builder[1] = Struct({Field(refStructA, Immutable)}); - builder[2] = Array(Field(refStructB, Immutable)); - builder[3] = Array(Field(refArrayA, Immutable)); - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - std::vector structs{built[0], built[1]}; - std::vector arrays{built[2], built[3]}; - - // Check that IndexedTypePrinters configured with fallbacks work correctly. - using ArrayPrinter = IndexedTypeNameGenerator; - ArrayPrinter printArrays(arrays, "array"); - using StructPrinter = IndexedTypeNameGenerator; - StructPrinter print(structs, printArrays, "struct"); - - std::stringstream stream; - stream << print(built[0]); - EXPECT_EQ(stream.str(), "(struct_subtype (field (ref null $array1)) data)"); - - stream.str(""); - stream << print(built[1]); - EXPECT_EQ(stream.str(), "(struct_subtype (field (ref null $struct0)) data)"); - - stream.str(""); - stream << print(built[2]); - EXPECT_EQ(stream.str(), "(array_subtype (ref null $struct1) data)"); - - stream.str(""); - stream << print(built[3]); - EXPECT_EQ(stream.str(), "(array_subtype (ref null $array0) data)"); -} - -TEST_F(EquirecursiveTest, Basics) { - // (type $sig (func (param (ref $struct)) (result (ref $array) i32))) - // (type $struct (struct (field (ref null $array) (mut rtt 0 $array)))) - // (type $array (array (mut anyref))) - TypeBuilder builder(3); - ASSERT_EQ(builder.size(), size_t{3}); - - Type refSig = builder.getTempRefType(builder[0], NonNullable); - Type refStruct = builder.getTempRefType(builder[1], NonNullable); - Type refArray = builder.getTempRefType(builder[2], NonNullable); - Type refNullArray = builder.getTempRefType(builder[2], Nullable); - Type rttArray = builder.getTempRttType(Rtt(0, builder[2])); - Type refNullAny(HeapType::any, Nullable); - - Signature sig(refStruct, builder.getTempTupleType({refArray, Type::i32})); - Struct struct_({Field(refNullArray, Immutable), Field(rttArray, Mutable)}); - Array array(Field(refNullAny, Mutable)); - - builder[0] = sig; - builder[1] = struct_; - builder[2] = array; - - auto result = builder.build(); - ASSERT_TRUE(result); - std::vector built = *result; - ASSERT_EQ(built.size(), size_t{3}); - - // The built types should have the correct kinds. - ASSERT_TRUE(built[0].isSignature()); - ASSERT_TRUE(built[1].isStruct()); - ASSERT_TRUE(built[2].isArray()); - - // The built types should have the correct structure. - Type newRefSig = Type(built[0], NonNullable); - Type newRefStruct = Type(built[1], NonNullable); - Type newRefArray = Type(built[2], NonNullable); - Type newRefNullArray = Type(built[2], Nullable); - Type newRttArray = Type(Rtt(0, built[2])); - - EXPECT_EQ(built[0].getSignature(), - Signature(newRefStruct, {newRefArray, Type::i32})); - EXPECT_EQ( - built[1].getStruct(), - Struct({Field(newRefNullArray, Immutable), Field(newRttArray, Mutable)})); - EXPECT_EQ(built[2].getArray(), Array(Field(refNullAny, Mutable))); - - // The built types should be different from the temporary types. - EXPECT_NE(newRefSig, refSig); - EXPECT_NE(newRefStruct, refStruct); - EXPECT_NE(newRefArray, refArray); - EXPECT_NE(newRefNullArray, refNullArray); - EXPECT_NE(newRttArray, rttArray); -} - -static void testDirectSelfSupertype() { - // Type is directly a supertype of itself. - TypeBuilder builder(1); - builder[0] = Struct{}; - builder[0].subTypeOf(builder[0]); - - auto result = builder.build(); - EXPECT_FALSE(result); - - const auto* error = result.getError(); - ASSERT_TRUE(error); - if (getTypeSystem() == TypeSystem::Nominal) { - EXPECT_EQ(error->reason, TypeBuilder::ErrorReason::SelfSupertype); - } else if (getTypeSystem() == TypeSystem::Isorecursive) { - EXPECT_EQ(error->reason, - TypeBuilder::ErrorReason::ForwardSupertypeReference); - } - EXPECT_EQ(error->index, 0u); -} - -TEST_F(NominalTest, DirectSelfSupertype) { testDirectSelfSupertype(); } -TEST_F(IsorecursiveTest, DirectSelfSupertype) { testDirectSelfSupertype(); } - -static void testIndirectSelfSupertype() { - // Type is indirectly a supertype of itself. - TypeBuilder builder(2); - builder.createRecGroup(0, 2); - builder[0] = Struct{}; - builder[1] = Struct{}; - builder[0].subTypeOf(builder[1]); - builder[1].subTypeOf(builder[0]); - - auto result = builder.build(); - EXPECT_FALSE(result); - - const auto* error = result.getError(); - ASSERT_TRUE(error); - if (getTypeSystem() == TypeSystem::Nominal) { - EXPECT_EQ(error->reason, TypeBuilder::ErrorReason::SelfSupertype); - } else if (getTypeSystem() == TypeSystem::Isorecursive) { - EXPECT_EQ(error->reason, - TypeBuilder::ErrorReason::ForwardSupertypeReference); - } else { - WASM_UNREACHABLE("unexpected type system"); - } - EXPECT_EQ(error->index, 0u); -} - -TEST_F(NominalTest, IndirectSelfSupertype) { testIndirectSelfSupertype(); } -TEST_F(IsorecursiveTest, IndirectSelfSupertype) { testIndirectSelfSupertype(); } - -static void testInvalidSupertype() { - TypeBuilder builder(2); - builder.createRecGroup(0, 2); - builder[0] = Struct({Field(Type::i32, Immutable)}); - builder[1] = Struct{}; - builder[1].subTypeOf(builder[0]); - - auto result = builder.build(); - EXPECT_FALSE(result); - - const auto* error = result.getError(); - ASSERT_TRUE(error); - EXPECT_EQ(error->reason, TypeBuilder::ErrorReason::InvalidSupertype); - EXPECT_EQ(error->index, 1u); -} - -TEST_F(NominalTest, InvalidSupertype) { testInvalidSupertype(); } -TEST_F(IsorecursiveTest, InvalidSupertype) { testInvalidSupertype(); } - -TEST_F(IsorecursiveTest, ForwardReferencedChild) { - TypeBuilder builder(3); - builder.createRecGroup(0, 2); - Type refA1 = builder.getTempRefType(builder[1], Nullable); - Type refB0 = builder.getTempRefType(builder[2], Nullable); - // Forward reference to same group is ok. - builder[0] = Struct({Field(refA1, Mutable)}); - // Forward reference to different group is not ok. - builder[1] = Struct({Field(refB0, Mutable)}); - builder[2] = Struct{}; - - auto result = builder.build(); - EXPECT_FALSE(result); - - const auto* error = result.getError(); - ASSERT_TRUE(error); - EXPECT_EQ(error->reason, TypeBuilder::ErrorReason::ForwardChildReference); - EXPECT_EQ(error->index, 1u); -} - -TEST_F(IsorecursiveTest, RecGroupIndices) { - TypeBuilder builder(5); - - builder.createRecGroup(0, 2); - builder[0] = Struct{}; - builder[1] = Struct{}; - - builder.createRecGroup(2, 3); - builder[2] = Struct{}; - builder[3] = Struct{}; - builder[4] = Struct{}; - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[0].getRecGroup(), built[1].getRecGroup()); - EXPECT_EQ(built[0].getRecGroupIndex(), 0u); - EXPECT_EQ(built[1].getRecGroupIndex(), 1u); - - EXPECT_EQ(built[2].getRecGroup(), built[3].getRecGroup()); - EXPECT_EQ(built[3].getRecGroup(), built[4].getRecGroup()); - EXPECT_EQ(built[2].getRecGroupIndex(), 0u); - EXPECT_EQ(built[3].getRecGroupIndex(), 1u); - EXPECT_EQ(built[4].getRecGroupIndex(), 2u); -} - -TEST_F(IsorecursiveTest, CanonicalizeGroups) { - // Trivial types in the same group are not equivalent. - TypeBuilder builderA(2); - builderA.createRecGroup(0, 2); - builderA[0] = Struct{}; - builderA[1] = Struct{}; - auto resultA = builderA.build(); - ASSERT_TRUE(resultA); - auto builtA = *resultA; - - EXPECT_NE(builtA[0], builtA[1]); - - // But if they are in their own separate groups, they are equivalent. - TypeBuilder builderB(2); - builderB[0] = Struct{}; - builderB[1] = Struct{}; - auto resultB = builderB.build(); - ASSERT_TRUE(resultB); - auto builtB = *resultB; - - EXPECT_EQ(builtB[0], builtB[1]); - EXPECT_NE(builtB[0], builtA[0]); - EXPECT_NE(builtB[0], builtA[1]); - - // If we build the same groups again, we should get the same results. - TypeBuilder builderA2(4); - builderA2.createRecGroup(0, 2); - builderA2.createRecGroup(2, 2); - builderA2[0] = Struct{}; - builderA2[1] = Struct{}; - builderA2[2] = Struct{}; - builderA2[3] = Struct{}; - auto resultA2 = builderA2.build(); - ASSERT_TRUE(resultA2); - auto builtA2 = *resultA2; - - EXPECT_EQ(builtA2[0], builtA[0]); - EXPECT_EQ(builtA2[1], builtA[1]); - EXPECT_EQ(builtA2[2], builtA[0]); - EXPECT_EQ(builtA2[3], builtA[1]); - - TypeBuilder builderB2(1); - builderB2[0] = Struct{}; - auto resultB2 = builderB2.build(); - ASSERT_TRUE(resultB2); - auto builtB2 = *resultB2; - - EXPECT_EQ(builtB2[0], builtB[0]); -} - -TEST_F(IsorecursiveTest, CanonicalizeUses) { - TypeBuilder builder(8); - builder[0] = makeStruct(builder, {}); - builder[1] = makeStruct(builder, {}); - builder[2] = makeStruct(builder, {0}); - builder[3] = makeStruct(builder, {1}); - builder[4] = makeStruct(builder, {0, 2}); - builder[5] = makeStruct(builder, {1, 3}); - builder[6] = makeStruct(builder, {2, 4}); - builder[7] = makeStruct(builder, {3, 5}); - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[0], built[1]); - EXPECT_EQ(built[2], built[3]); - EXPECT_EQ(built[4], built[5]); - EXPECT_EQ(built[6], built[7]); - - EXPECT_NE(built[0], built[2]); - EXPECT_NE(built[0], built[4]); - EXPECT_NE(built[0], built[6]); - EXPECT_NE(built[2], built[4]); - EXPECT_NE(built[2], built[6]); - EXPECT_NE(built[4], built[6]); -} - -TEST_F(IsorecursiveTest, DISABLED_CanonicalizeSelfReferences) { - TypeBuilder builder(5); - // Single self-reference - builder[0] = makeStruct(builder, {0}); - builder[1] = makeStruct(builder, {1}); - // Single other reference - builder[2] = makeStruct(builder, {0}); - // Other reference followed by self-reference - builder[3] = makeStruct(builder, {2, 3}); - // Self-reference followed by other reference - builder[4] = makeStruct(builder, {4, 2}); - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[0], built[1]); - - EXPECT_NE(built[0], built[2]); - EXPECT_NE(built[0], built[3]); - EXPECT_NE(built[0], built[4]); - EXPECT_NE(built[2], built[3]); - EXPECT_NE(built[2], built[4]); - EXPECT_NE(built[3], built[4]); -} - -TEST_F(IsorecursiveTest, CanonicalizeSupertypes) { - TypeBuilder builder(6); - builder[0] = Struct{}; - builder[1] = Struct{}; - // Type with a supertype - builder[2] = Struct{}; - builder[2].subTypeOf(builder[0]); - // Type with the same supertype after canonicalization. - builder[3] = Struct{}; - builder[3].subTypeOf(builder[1]); - // Type with a different supertype - builder[4] = Struct{}; - builder[4].subTypeOf(builder[2]); - // Type with no supertype - builder[5] = Struct{}; - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[2], built[3]); - - EXPECT_NE(built[3], built[4]); - EXPECT_NE(built[3], built[5]); - EXPECT_NE(built[4], built[5]); -} - -TEST_F(IsorecursiveTest, HeapTypeConstructors) { - HeapType sig(Signature(Type::i32, Type::i32)); - HeapType struct_(Struct({Field(Type(sig, Nullable), Mutable)})); - HeapType array(Field(Type(struct_, Nullable), Mutable)); - - TypeBuilder builder(3); - builder[0] = Signature(Type::i32, Type::i32); - Type sigRef = builder.getTempRefType(builder[0], Nullable); - builder[1] = Struct({Field(sigRef, Mutable)}); - Type structRef = builder.getTempRefType(builder[1], Nullable); - builder[2] = Array(Field(structRef, Mutable)); - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[0], sig); - EXPECT_EQ(built[1], struct_); - EXPECT_EQ(built[2], array); - - HeapType sig2(Signature(Type::i32, Type::i32)); - HeapType struct2(Struct({Field(Type(sig, Nullable), Mutable)})); - HeapType array2(Field(Type(struct_, Nullable), Mutable)); - - EXPECT_EQ(sig, sig2); - EXPECT_EQ(struct_, struct2); - EXPECT_EQ(array, array2); -} - -TEST_F(IsorecursiveTest, CanonicalizeTypesBeforeSubtyping) { - TypeBuilder builder(6); - // A rec group - builder.createRecGroup(0, 2); - builder[0] = Struct{}; - builder[1] = Struct{}; - builder[1].subTypeOf(builder[0]); - - // The same rec group again - builder.createRecGroup(2, 2); - builder[2] = Struct{}; - builder[3] = Struct{}; - builder[3].subTypeOf(builder[2]); - - // This subtyping only validates if the previous two groups are deduplicated - // before checking subtype validity. - builder[4] = - Struct({Field(builder.getTempRefType(builder[0], Nullable), Immutable)}); - builder[5] = - Struct({Field(builder.getTempRefType(builder[3], Nullable), Immutable)}); - builder[5].subTypeOf(builder[4]); - - auto result = builder.build(); - EXPECT_TRUE(result); -} - -static void testCanonicalizeBasicTypes() { - TypeBuilder builder(5); - - Type anyref = builder.getTempRefType(builder[0], Nullable); - Type anyrefs = builder.getTempTupleType({anyref, anyref}); - - builder[0] = HeapType::any; - builder[1] = Struct({Field(anyref, Immutable)}); - builder[2] = Struct({Field(Type::anyref, Immutable)}); - builder[3] = Signature(anyrefs, Type::none); - builder[4] = Signature({Type::anyref, Type::anyref}, Type::none); - - auto result = builder.build(); - ASSERT_TRUE(result); - auto built = *result; - - EXPECT_EQ(built[1], built[2]); - EXPECT_EQ(built[3], built[4]); -} - -TEST_F(EquirecursiveTest, CanonicalizeBasicTypes) { - testCanonicalizeBasicTypes(); -} -TEST_F(IsorecursiveTest, CanonicalizeBasicTypes) { - testCanonicalizeBasicTypes(); -} diff -Nru binaryen-108/test/gtest/type-test.h binaryen-99/test/gtest/type-test.h --- binaryen-108/test/gtest/type-test.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/gtest/type-test.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#include "wasm-type.h" -#include "gtest/gtest.h" - -#ifndef wasm_test_gtest_type_test_h -#define wasm_test_gtest_type_test_h - -// Helper test fixture for managing the global type system state. -template -class TypeSystemTest : public ::testing::Test { - wasm::TypeSystem originalSystem; - -protected: - void SetUp() override { - originalSystem = wasm::getTypeSystem(); - wasm::setTypeSystem(system); - } - void TearDown() override { - wasm::destroyAllTypesForTestingPurposesOnly(); - wasm::setTypeSystem(originalSystem); - } - - // Utilities - wasm::Struct makeStruct(wasm::TypeBuilder& builder, - std::initializer_list indices) { - using namespace wasm; - FieldList fields; - for (auto index : indices) { - Type ref = builder.getTempRefType(builder[index], Nullable); - fields.emplace_back(ref, Mutable); - } - return Struct(std::move(fields)); - } -}; - -using TypeTest = TypeSystemTest; -using EquirecursiveTest = TypeSystemTest; -using NominalTest = TypeSystemTest; -using IsorecursiveTest = TypeSystemTest; - -#endif // wasm_test_gtest_type_test_h diff -Nru binaryen-108/test/heap-types.wast binaryen-99/test/heap-types.wast --- binaryen-108/test/heap-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/heap-types.wast 2021-01-07 20:01:06.000000000 +0000 @@ -6,13 +6,6 @@ (field f32) (field $named f64) )) - ;; identical to $struct.A, so will be canonicalized with it, but field names - ;; are different - (type $struct.A.prime (struct - i32 - (field f32) - (field $othername f64) - )) (type $struct.B (struct (field i8) (field (mut i16)) @@ -25,7 +18,7 @@ ;; Arrays (type $vector (array (mut f64))) - (type $matrix (array (mut (ref null $vector)))) + (type $matrix (array (ref $vector))) (type $bytes (array (mut i8))) (type $words (array (mut i32))) @@ -36,16 +29,6 @@ (global $rttparent (rtt 0 $parent) (rtt.canon $parent)) (global $rttchild (rtt 1 $child) (rtt.sub $child (global.get $rttparent))) (global $rttgrandchild (rtt 2 $grandchild) (rtt.sub $grandchild (global.get $rttchild))) - (global $rttfreshgrandchild (rtt 2 $grandchild) (rtt.fresh_sub $grandchild (global.get $rttchild))) - - (type $nested-child-struct (struct (field (mut (ref $child))))) - (type $nested-child-array (array (mut (ref $child)))) - - (global $struct.new-in-global (ref $struct.A) - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) (func $structs (param $x (ref $struct.A)) (result (ref $struct.B)) (local $tA (ref null $struct.A)) @@ -69,18 +52,11 @@ (struct.get $struct.A $named (local.get $x)) ) (drop - (struct.get $struct.A.prime $othername (ref.null $struct.A.prime)) - ) - (drop (struct.get_u $struct.B 0 (local.get $tB)) ) (drop (struct.get_s $struct.B 0 (local.get $tB)) ) - ;; immutable fields allow subtyping. - (drop - (struct.get $child 0 (ref.null $grandchild)) - ) (drop (ref.null $struct.A) ) @@ -108,16 +84,9 @@ (i32.const 1) ) ) - (struct.set $struct.C 0 - (ref.null $struct.C) - (f32.const 100) - ) - ;; values may be subtypes - (struct.set $nested-child-struct 0 - (ref.null $nested-child-struct) - (ref.as_non_null - (ref.null $grandchild) - ) + (struct.set $struct.A 0 + (local.get $x) + (i32.const 100) ) (drop (struct.new_default_with_rtt $struct.A @@ -126,10 +95,10 @@ ) (drop (struct.new_with_rtt $struct.A + (rtt.canon $struct.A) (i32.const 1) (f32.const 2.345) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) (unreachable) @@ -141,15 +110,15 @@ (local $tw (ref null $words)) (drop (array.new_with_rtt $vector - (f64.const 3.14159) - (i32.const 3) (rtt.canon $vector) + (i32.const 3) + (f64.const 3.14159) ) ) (drop (array.new_default_with_rtt $matrix - (i32.const 10) (rtt.canon $matrix) + (i32.const 10) ) ) (drop @@ -163,14 +132,6 @@ (i32.const 2) (f64.const 2.18281828) ) - ;; values may be subtypes - (array.set $nested-child-array - (ref.null $nested-child-array) - (i32.const 3) - (ref.as_non_null - (ref.null $grandchild) - ) - ) (drop (array.len $vector (local.get $x) @@ -201,256 +162,24 @@ (func $rtt-param-without-depth (param $rtt (rtt $parent))) (func $rtt-operations (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) (drop - (ref.test (ref.null $struct.A) (rtt.canon $struct.B)) + (ref.test $struct.B (ref.null $struct.A) (rtt.canon $struct.B)) ) (drop - (ref.cast (ref.null $struct.A) (rtt.canon $struct.B)) + (ref.cast $struct.B (ref.null $struct.A) (rtt.canon $struct.B)) ) (drop (block $out (result (ref $struct.B)) ;; set the value to a local with type $struct.A, showing that the value ;; flowing out has the right type (local.set $temp.A - (br_on_cast $out (ref.null $struct.A) (rtt.canon $struct.B)) + (br_on_cast $out $struct.B (ref.null $struct.A) (rtt.canon $struct.B)) ) ;; an untaken br_on_cast, with unreachable rtt - so we cannot use the ;; RTT in binaryen IR to find the cast type. - (br_on_cast $out (ref.null $struct.A) (unreachable)) - (unreachable) - ) - ) - (drop - (block $out2 (result (ref null $struct.A)) - ;; set the value to a local with type $struct.A, showing that the value - ;; flowing out has the right type - (local.set $temp.B - (br_on_cast_fail $out2 (ref.null $struct.A) (rtt.canon $struct.B)) - ) - (ref.null $struct.A) - ) - ) - ) - (func $ref.is_X (param $x anyref) - (if (ref.is_func (local.get $x)) (unreachable)) - (if (ref.is_data (local.get $x)) (unreachable)) - (if (ref.is_i31 (local.get $x)) (unreachable)) - ) - (func $ref.as_X (param $x anyref) - (drop (ref.as_non_null (local.get $x))) - (drop (ref.as_func (local.get $x))) - (drop (ref.as_data (local.get $x))) - (drop (ref.as_i31 (local.get $x))) - ) - (func $br_on_X (param $x anyref) - (local $y anyref) - (local $z (ref null any)) - (local $temp-func (ref null func)) - (local $temp-data (ref null data)) - (local $temp-i31 (ref null i31)) - (block $null - (local.set $z - (br_on_null $null (local.get $x)) - ) - ) - (drop - (block $func (result funcref) - (local.set $y - (br_on_func $func (local.get $x)) - ) - (ref.null func) - ) - ) - (drop - (block $data (result (ref null data)) - (local.set $y - (br_on_data $data (local.get $x)) - ) - (ref.null data) - ) - ) - (drop - (block $i31 (result (ref null i31)) - (local.set $y - (br_on_i31 $i31 (local.get $x)) - ) - (ref.null i31) - ) - ) - (drop - (block $non-null (result (ref any)) - (br_on_non_null $non-null (local.get $x)) + (br_on_cast $out $struct.B (ref.null $struct.A) (unreachable)) (unreachable) ) ) - (drop - (block $non-func (result anyref) - (local.set $temp-func - (br_on_non_func $non-func (local.get $x)) - ) - (ref.null any) - ) - ) - (drop - (block $non-data (result anyref) - (local.set $temp-data - (br_on_non_data $non-data (local.get $x)) - ) - (ref.null any) - ) - ) - (drop - (block $non-i31 (result anyref) - (local.set $temp-i31 - (br_on_non_i31 $non-i31 (local.get $x)) - ) - (ref.null any) - ) - ) - ) - (func $unreachables-1 - (drop - (struct.get $struct.C 0 (unreachable)) - ) - ) - (func $unreachables-2 - (struct.set $struct.C 0 (ref.null $struct.C) (unreachable)) - ) - (func $unreachables-3 - (struct.set $struct.C 0 (unreachable) (unreachable)) - ) - (func $unreachables-4 - (struct.set $struct.C 0 (unreachable) (f32.const 1)) - ) - (func $unreachables-array-1 - (array.get $vector - (unreachable) - (i32.const 2) - ) - ) - (func $unreachables-array-2 - (array.get $vector - (ref.null $vector) - (unreachable) - ) - ) - (func $unreachables-array-3 - (array.set $vector - (unreachable) - (i32.const 2) - (f64.const 2.18281828) - ) - ) - (func $unreachables-array-4 - (array.set $vector - (ref.null $vector) - (unreachable) - (f64.const 2.18281828) - ) - ) - (func $unreachables-array-5 - (array.set $vector - (ref.null $vector) - (i32.const 2) - (unreachable) - ) - ) - (func $unreachables-array-6 - (drop - (array.len $vector - (unreachable) - ) - ) - ) - (func $unreachables-7 - (drop - (struct.new_default_with_rtt $struct.A - (unreachable) - ) - ) - ) - (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector)) - (array.copy $vector $vector - (local.get $x) - (i32.const 11) - (local.get $y) - (i32.const 42) - (i32.const 1337) - ) - ) - (func $array-init (result (ref $vector)) - (array.init $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - (rtt.canon $vector) - ) - ) - (func $array-init-packed (result (ref $bytes)) - (array.init $bytes - (i32.const 4) - (i32.const 2) - (i32.const 1) - (rtt.canon $bytes) - ) - ) - (func $static-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test_static $struct.B (ref.null $struct.A)) - ) - (drop - (ref.cast_static $struct.B (ref.null $struct.A)) - ) - (drop - (block $out-B (result (ref $struct.B)) - (local.set $temp.A - (br_on_cast_static $out-B $struct.B (ref.null $struct.A)) - ) - (unreachable) - ) - ) - (drop - (block $out-A (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_static_fail $out-A $struct.B (ref.null $struct.A)) - ) - (unreachable) - ) - ) - ) - (func $static-constructions - (drop - (struct.new_default $struct.A) - ) - (drop - (struct.new $struct.A - (i32.const 1) - (f32.const 2.345) - (f64.const 3.14159) - ) - ) - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $matrix - (i32.const 10) - ) - ) - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) ) ) diff -Nru binaryen-108/test/heap-types.wast.fromBinary binaryen-99/test/heap-types.wast.fromBinary --- binaryen-108/test/heap-types.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/heap-types.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,511 +1,196 @@ (module - (type $struct.A (struct (field i32) (field f32) (field $named f64))) - (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) - (type $vector (array (mut f64))) + (type ${i32_f32_f64} (struct (field i32) (field f32) (field f64))) + (type $[mut:f64] (array (mut f64))) + (type ${} (struct )) (type $none_=>_none (func)) - (type $grandchild (struct (field i32) (field i64))) - (type $matrix (array (mut (ref null $vector)))) - (type $struct.C (struct (field $named-mut (mut f32)))) - (type $parent (struct )) - (type $child (struct (field i32))) - (type $bytes (array (mut i8))) - (type $anyref_=>_none (func (param anyref))) - (type $nested-child-struct (struct (field (mut (ref $child))))) - (type $ref|$struct.A|_=>_ref|$struct.B| (func (param (ref $struct.A)) (result (ref $struct.B)))) - (type $ref|$vector|_=>_ref|$matrix| (func (param (ref $vector)) (result (ref $matrix)))) - (type $words (array (mut i32))) - (type $nested-child-array (array (mut (ref $child)))) - (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) - (type $rtt_$parent_=>_none (func (param (rtt $parent)))) - (type $ref|$vector|_ref?|$vector|_=>_none (func (param (ref $vector) (ref null $vector)))) - (type $none_=>_ref|$vector| (func (result (ref $vector)))) - (type $none_=>_ref|$bytes| (func (result (ref $bytes)))) - (global $rttparent (rtt 0 $parent) (rtt.canon $parent)) - (global $rttchild (rtt 1 $child) (rtt.sub $child + (type ${i32} (struct (field i32))) + (type ${i32_i64} (struct (field i32) (field i64))) + (type ${mut:f32} (struct (field (mut f32)))) + (type $[mut:i32] (array (mut i32))) + (type $[mut:i8] (array (mut i8))) + (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64}))))) + (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64]))) + (type $rtt_1_${}_=>_none (func (param (rtt 1 ${})))) + (type $rtt_${}_=>_none (func (param (rtt ${})))) + (type $ref?|{i32_f32_f64}|_=>_ref?|{i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}| (func (param (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})))) + (type $ref?|[mut:f64]|_=>_ref?|[ref?|[mut:f64]|]| (func (param (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|])))) + (global $rttparent (rtt 0 ${}) (rtt.canon ${})) + (global $rttchild (rtt 1 ${i32}) (rtt.sub ${i32} (global.get $rttparent) )) - (global $rttgrandchild (rtt 2 $grandchild) (rtt.sub $grandchild + (global $rttgrandchild (rtt 2 ${i32_i64}) (rtt.sub ${i32_i64} (global.get $rttchild) )) - (global $rttfreshgrandchild (rtt 2 $grandchild) (rtt.fresh_sub $grandchild - (global.get $rttchild) - )) - (global $struct.new-in-global (ref $struct.A) (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - )) - (func $structs (param $x (ref $struct.A)) (result (ref $struct.B)) - (local $tA (ref null $struct.A)) - (local $tB (ref null $struct.B)) - (local $tc (ref null $struct.C)) - (local $tv (ref null $vector)) - (local $tm (ref null $matrix)) + (func $structs (param $x (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) + (local $tA (ref null ${i32_f32_f64})) + (local $tB (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) + (local $tc (ref null ${mut:f32})) + (local $tv (ref null $[ref?|[mut:f64]|])) + (local $tm (ref null $[mut:f64])) (drop (local.get $x) ) (drop - (struct.get $struct.A 0 + (struct.get ${i32_f32_f64} 0 (local.get $x) ) ) (drop - (struct.get $struct.A 1 + (struct.get ${i32_f32_f64} 1 (local.get $x) ) ) (drop - (struct.get $struct.A $named + (struct.get ${i32_f32_f64} 2 (local.get $x) ) ) (drop - (struct.get $struct.A $named + (struct.get ${i32_f32_f64} 2 (local.get $x) ) ) (drop - (struct.get $struct.A $named - (ref.null $struct.A) - ) - ) - (drop - (struct.get_u $struct.B 0 + (struct.get_u ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0 (local.get $tB) ) ) (drop - (struct.get_s $struct.B 0 + (struct.get_s ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0 (local.get $tB) ) ) (drop - (struct.get $grandchild 0 - (ref.null $grandchild) - ) - ) - (drop - (ref.null $struct.A) + (ref.null ${i32_f32_f64}) ) (drop - (block $label$1 (result (ref null $struct.A)) + (block $label$1 (result (ref null ${i32_f32_f64})) (local.get $x) ) ) (drop - (if (result (ref null $struct.A)) + (if (result (ref null ${i32_f32_f64})) (i32.const 1) (local.get $x) (local.get $x) ) ) (drop - (loop $label$4 (result (ref null $struct.A)) + (loop $label$4 (result (ref null ${i32_f32_f64})) (local.get $x) ) ) (drop - (select (result (ref null $struct.A)) + (select (result (ref null ${i32_f32_f64})) (local.get $x) (local.get $x) (i32.const 1) ) ) - (struct.set $struct.C $named-mut - (ref.null $struct.C) - (f32.const 100) - ) - (struct.set $nested-child-struct 0 - (ref.null $nested-child-struct) - (ref.as_non_null - (ref.null $grandchild) - ) + (struct.set ${i32_f32_f64} 0 + (local.get $x) + (i32.const 100) ) (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) + (struct.new_default_with_rtt ${i32_f32_f64} + (rtt.canon ${i32_f32_f64}) ) ) (drop - (struct.new_with_rtt $struct.A + (struct.new_with_rtt ${i32_f32_f64} + (rtt.canon ${i32_f32_f64}) (i32.const 1) (f32.const 2.3450000286102295) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) (unreachable) ) - (func $arrays (param $x (ref $vector)) (result (ref $matrix)) - (local $tv (ref null $vector)) - (local $tm (ref null $matrix)) - (local $tb (ref null $bytes)) - (local $tw (ref null $words)) + (func $arrays (param $x (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|])) + (local $tv (ref null $[ref?|[mut:f64]|])) + (local $tm (ref null $[mut:i32])) + (local $tb (ref null $[mut:i8])) + (local $tw (ref null $[mut:f64])) (drop - (array.new_with_rtt $vector - (f64.const 3.14159) + (array.new_with_rtt $[mut:f64] + (rtt.canon $[mut:f64]) (i32.const 3) - (rtt.canon $vector) + (f64.const 3.14159) ) ) (drop - (array.new_default_with_rtt $matrix + (array.new_default_with_rtt $[ref?|[mut:f64]|] + (rtt.canon $[ref?|[mut:f64]|]) (i32.const 10) - (rtt.canon $matrix) ) ) (drop - (array.get $vector + (array.get $[mut:f64] (local.get $x) (i32.const 2) ) ) - (array.set $vector + (array.set $[mut:f64] (local.get $x) (i32.const 2) (f64.const 2.18281828) ) - (array.set $nested-child-array - (ref.null $nested-child-array) - (i32.const 3) - (ref.as_non_null - (ref.null $grandchild) - ) - ) (drop - (array.len $vector + (array.len $[mut:f64] (local.get $x) ) ) (drop - (array.get $words - (local.get $tw) + (array.get $[mut:i32] + (local.get $tm) (i32.const 1) ) ) (drop - (array.get_u $bytes + (array.get_u $[mut:i8] (local.get $tb) (i32.const 2) ) ) (drop - (array.get_s $bytes + (array.get_s $[mut:i8] (local.get $tb) (i32.const 3) ) ) (unreachable) ) - (func $rtt-param-with-depth (param $rtt (rtt 1 $parent)) + (func $rtt-param-with-depth (param $rtt (rtt 1 ${})) (nop) ) - (func $rtt-param-without-depth (param $rtt (rtt $parent)) + (func $rtt-param-without-depth (param $rtt (rtt ${})) (nop) ) (func $rtt-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (drop - (ref.cast - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (drop - (block $label$1 (result (ref $struct.B)) - (local.set $temp.A - (br_on_cast $label$1 - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (block $label$2 - (drop - (ref.null $struct.A) - ) - (unreachable) - ) - ) - ) - (drop - (block $label$3 (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_fail $label$3 - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (ref.null $struct.A) - ) - ) - ) - (func $ref.is_X (param $x anyref) - (if - (ref.is_func - (local.get $x) - ) - (unreachable) - ) - (if - (ref.is_data - (local.get $x) - ) - (unreachable) - ) - (if - (ref.is_i31 - (local.get $x) - ) - (unreachable) - ) - ) - (func $ref.as_X (param $x anyref) - (drop - (ref.as_non_null - (local.get $x) - ) - ) - (drop - (ref.as_func - (local.get $x) - ) - ) - (drop - (ref.as_data - (local.get $x) - ) - ) - (drop - (ref.as_i31 - (local.get $x) - ) - ) - ) - (func $br_on_X (param $x anyref) - (local $y anyref) - (local $z anyref) - (local $temp-func funcref) - (local $temp-data (ref null data)) - (local $temp-i31 (ref null i31)) - (block $label$1 - (local.set $z - (br_on_null $label$1 - (local.get $x) - ) - ) - ) - (drop - (block $label$2 (result funcref) - (local.set $y - (br_on_func $label$2 - (local.get $x) - ) - ) - (ref.null func) - ) - ) - (drop - (block $label$3 (result (ref null data)) - (local.set $y - (br_on_data $label$3 - (local.get $x) - ) - ) - (ref.null data) - ) - ) - (drop - (block $label$4 (result (ref null i31)) - (local.set $y - (br_on_i31 $label$4 - (local.get $x) - ) - ) - (ref.null i31) - ) - ) - (drop - (block $label$5 (result (ref any)) - (br_on_non_null $label$5 - (local.get $x) - ) - (unreachable) - ) - ) + (local $temp.A (ref null ${i32_f32_f64})) (drop - (block $label$6 (result anyref) - (local.set $temp-func - (br_on_non_func $label$6 - (local.get $x) - ) - ) - (ref.null any) + (ref.test ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (drop - (block $label$7 (result anyref) - (local.set $temp-data - (br_on_non_data $label$7 - (local.get $x) - ) - ) - (ref.null any) + (ref.cast ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (drop - (block $label$8 (result anyref) - (local.set $temp-i31 - (br_on_non_i31 $label$8 - (local.get $x) - ) - ) - (ref.null any) - ) - ) - ) - (func $unreachables-1 - (unreachable) - ) - (func $unreachables-2 - (drop - (ref.null $struct.C) - ) - (unreachable) - ) - (func $unreachables-3 - (unreachable) - ) - (func $unreachables-4 - (unreachable) - ) - (func $unreachables-array-1 - (unreachable) - ) - (func $unreachables-array-2 - (drop - (ref.null $vector) - ) - (unreachable) - ) - (func $unreachables-array-3 - (unreachable) - ) - (func $unreachables-array-4 - (drop - (ref.null $vector) - ) - (unreachable) - ) - (func $unreachables-array-5 - (drop - (ref.null $vector) - ) - (drop - (i32.const 2) - ) - (unreachable) - ) - (func $unreachables-array-6 - (unreachable) - ) - (func $unreachables-7 - (unreachable) - ) - (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector)) - (array.copy $vector $vector - (local.get $x) - (i32.const 11) - (local.get $y) - (i32.const 42) - (i32.const 1337) - ) - ) - (func $array-init (result (ref $vector)) - (array.init $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - (rtt.canon $vector) - ) - ) - (func $array-init-packed (result (ref $bytes)) - (array.init $bytes - (i32.const 4) - (i32.const 2) - (i32.const 1) - (rtt.canon $bytes) - ) - ) - (func $static-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test_static $struct.B - (ref.null $struct.A) - ) - ) - (drop - (ref.cast_static $struct.B - (ref.null $struct.A) - ) - ) - (drop - (block $label$1 (result (ref $struct.B)) + (block $label$1 (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) (local.set $temp.A - (br_on_cast_static $label$1 $struct.B - (ref.null $struct.A) - ) - ) - (unreachable) - ) - ) - (drop - (block $label$2 (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_static_fail $label$2 $struct.B - (ref.null $struct.A) + (br_on_cast $label$1 ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (unreachable) ) ) ) - (func $static-constructions - (drop - (struct.new_default $struct.A) - ) - (drop - (struct.new $struct.A - (i32.const 1) - (f32.const 2.3450000286102295) - (f64.const 3.14159) - ) - ) - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $matrix - (i32.const 10) - ) - ) - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) ) diff -Nru binaryen-108/test/heap-types.wast.fromBinary.noDebugInfo binaryen-99/test/heap-types.wast.fromBinary.noDebugInfo --- binaryen-108/test/heap-types.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/heap-types.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,25 +1,19 @@ (module (type ${i32_f32_f64} (struct (field i32) (field f32) (field f64))) - (type ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref ${i32_f32_f64})) (field (mut (ref ${i32_f32_f64}))))) (type $[mut:f64] (array (mut f64))) + (type ${} (struct )) (type $none_=>_none (func)) + (type ${i32} (struct (field i32))) (type ${i32_i64} (struct (field i32) (field i64))) - (type $[mut:ref?|[mut:f64]|] (array (mut (ref null $[mut:f64])))) (type ${mut:f32} (struct (field (mut f32)))) - (type ${} (struct )) - (type ${i32} (struct (field i32))) - (type $[mut:i8] (array (mut i8))) - (type $anyref_=>_none (func (param anyref))) - (type ${mut:ref|{i32}|} (struct (field (mut (ref ${i32}))))) - (type $ref|{i32_f32_f64}|_=>_ref|{i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}| (func (param (ref ${i32_f32_f64})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})))) - (type $ref|[mut:f64]|_=>_ref|[mut:ref?|[mut:f64]|]| (func (param (ref $[mut:f64])) (result (ref $[mut:ref?|[mut:f64]|])))) (type $[mut:i32] (array (mut i32))) - (type $[mut:ref|{i32}|] (array (mut (ref ${i32})))) - (type $rtt_1_{}_=>_none (func (param (rtt 1 ${})))) - (type $rtt_{}_=>_none (func (param (rtt ${})))) - (type $ref|[mut:f64]|_ref?|[mut:f64]|_=>_none (func (param (ref $[mut:f64]) (ref null $[mut:f64])))) - (type $none_=>_ref|[mut:f64]| (func (result (ref $[mut:f64])))) - (type $none_=>_ref|[mut:i8]| (func (result (ref $[mut:i8])))) + (type $[mut:i8] (array (mut i8))) + (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64}))))) + (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64]))) + (type $rtt_1_${}_=>_none (func (param (rtt 1 ${})))) + (type $rtt_${}_=>_none (func (param (rtt ${})))) + (type $ref?|{i32_f32_f64}|_=>_ref?|{i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}| (func (param (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})))) + (type $ref?|[mut:f64]|_=>_ref?|[ref?|[mut:f64]|]| (func (param (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|])))) (global $global$0 (rtt 0 ${}) (rtt.canon ${})) (global $global$1 (rtt 1 ${i32}) (rtt.sub ${i32} (global.get $global$0) @@ -27,18 +21,12 @@ (global $global$2 (rtt 2 ${i32_i64}) (rtt.sub ${i32_i64} (global.get $global$1) )) - (global $global$3 (rtt 2 ${i32_i64}) (rtt.fresh_sub ${i32_i64} - (global.get $global$1) - )) - (global $global$4 (ref ${i32_f32_f64}) (struct.new_default_with_rtt ${i32_f32_f64} - (rtt.canon ${i32_f32_f64}) - )) - (func $0 (param $0 (ref ${i32_f32_f64})) (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) + (func $0 (param $0 (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) (local $1 (ref null ${i32_f32_f64})) - (local $2 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) + (local $2 (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) (local $3 (ref null ${mut:f32})) - (local $4 (ref null $[mut:f64])) - (local $5 (ref null $[mut:ref?|[mut:f64]|])) + (local $4 (ref null $[ref?|[mut:f64]|])) + (local $5 (ref null $[mut:f64])) (drop (local.get $0) ) @@ -63,26 +51,16 @@ ) ) (drop - (struct.get ${i32_f32_f64} 2 - (ref.null ${i32_f32_f64}) - ) - ) - (drop - (struct.get_u ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} 0 + (struct.get_u ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0 (local.get $2) ) ) (drop - (struct.get_s ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} 0 + (struct.get_s ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0 (local.get $2) ) ) (drop - (struct.get ${i32_i64} 0 - (ref.null ${i32_i64}) - ) - ) - (drop (ref.null ${i32_f32_f64}) ) (drop @@ -109,15 +87,9 @@ (i32.const 1) ) ) - (struct.set ${mut:f32} 0 - (ref.null ${mut:f32}) - (f32.const 100) - ) - (struct.set ${mut:ref|{i32}|} 0 - (ref.null ${mut:ref|{i32}|}) - (ref.as_non_null - (ref.null ${i32_i64}) - ) + (struct.set ${i32_f32_f64} 0 + (local.get $0) + (i32.const 100) ) (drop (struct.new_default_with_rtt ${i32_f32_f64} @@ -126,30 +98,30 @@ ) (drop (struct.new_with_rtt ${i32_f32_f64} + (rtt.canon ${i32_f32_f64}) (i32.const 1) (f32.const 2.3450000286102295) (f64.const 3.14159) - (rtt.canon ${i32_f32_f64}) ) ) (unreachable) ) - (func $1 (param $0 (ref $[mut:f64])) (result (ref $[mut:ref?|[mut:f64]|])) - (local $1 (ref null $[mut:f64])) - (local $2 (ref null $[mut:ref?|[mut:f64]|])) + (func $1 (param $0 (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|])) + (local $1 (ref null $[ref?|[mut:f64]|])) + (local $2 (ref null $[mut:i32])) (local $3 (ref null $[mut:i8])) - (local $4 (ref null $[mut:i32])) + (local $4 (ref null $[mut:f64])) (drop (array.new_with_rtt $[mut:f64] - (f64.const 3.14159) - (i32.const 3) (rtt.canon $[mut:f64]) + (i32.const 3) + (f64.const 3.14159) ) ) (drop - (array.new_default_with_rtt $[mut:ref?|[mut:f64]|] + (array.new_default_with_rtt $[ref?|[mut:f64]|] + (rtt.canon $[ref?|[mut:f64]|]) (i32.const 10) - (rtt.canon $[mut:ref?|[mut:f64]|]) ) ) (drop @@ -163,13 +135,6 @@ (i32.const 2) (f64.const 2.18281828) ) - (array.set $[mut:ref|{i32}|] - (ref.null $[mut:ref|{i32}|]) - (i32.const 3) - (ref.as_non_null - (ref.null ${i32_i64}) - ) - ) (drop (array.len $[mut:f64] (local.get $0) @@ -177,7 +142,7 @@ ) (drop (array.get $[mut:i32] - (local.get $4) + (local.get $2) (i32.const 1) ) ) @@ -203,309 +168,29 @@ ) (func $4 (local $0 (ref null ${i32_f32_f64})) - (local $1 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) - (drop - (ref.test - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (drop - (ref.cast - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (drop - (block $label$1 (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) - (local.set $0 - (br_on_cast $label$1 - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (block $label$2 - (drop - (ref.null ${i32_f32_f64}) - ) - (unreachable) - ) - ) - ) - (drop - (block $label$3 (result (ref null ${i32_f32_f64})) - (local.set $1 - (br_on_cast_fail $label$3 - (ref.null ${i32_f32_f64}) - (rtt.canon ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|}) - ) - ) - (ref.null ${i32_f32_f64}) - ) - ) - ) - (func $5 (param $0 anyref) - (if - (ref.is_func - (local.get $0) - ) - (unreachable) - ) - (if - (ref.is_data - (local.get $0) - ) - (unreachable) - ) - (if - (ref.is_i31 - (local.get $0) - ) - (unreachable) - ) - ) - (func $6 (param $0 anyref) - (drop - (ref.as_non_null - (local.get $0) - ) - ) - (drop - (ref.as_func - (local.get $0) - ) - ) - (drop - (ref.as_data - (local.get $0) - ) - ) - (drop - (ref.as_i31 - (local.get $0) - ) - ) - ) - (func $7 (param $0 anyref) - (local $1 anyref) - (local $2 anyref) - (local $3 funcref) - (local $4 (ref null data)) - (local $5 (ref null i31)) - (block $label$1 - (local.set $2 - (br_on_null $label$1 - (local.get $0) - ) - ) - ) - (drop - (block $label$2 (result funcref) - (local.set $1 - (br_on_func $label$2 - (local.get $0) - ) - ) - (ref.null func) - ) - ) - (drop - (block $label$3 (result (ref null data)) - (local.set $1 - (br_on_data $label$3 - (local.get $0) - ) - ) - (ref.null data) - ) - ) - (drop - (block $label$4 (result (ref null i31)) - (local.set $1 - (br_on_i31 $label$4 - (local.get $0) - ) - ) - (ref.null i31) - ) - ) - (drop - (block $label$5 (result (ref any)) - (br_on_non_null $label$5 - (local.get $0) - ) - (unreachable) - ) - ) - (drop - (block $label$6 (result anyref) - (local.set $3 - (br_on_non_func $label$6 - (local.get $0) - ) - ) - (ref.null any) - ) - ) - (drop - (block $label$7 (result anyref) - (local.set $4 - (br_on_non_data $label$7 - (local.get $0) - ) - ) - (ref.null any) - ) - ) - (drop - (block $label$8 (result anyref) - (local.set $5 - (br_on_non_i31 $label$8 - (local.get $0) - ) - ) - (ref.null any) - ) - ) - ) - (func $8 - (unreachable) - ) - (func $9 - (drop - (ref.null ${mut:f32}) - ) - (unreachable) - ) - (func $10 - (unreachable) - ) - (func $11 - (unreachable) - ) - (func $12 - (unreachable) - ) - (func $13 - (drop - (ref.null $[mut:f64]) - ) - (unreachable) - ) - (func $14 - (unreachable) - ) - (func $15 - (drop - (ref.null $[mut:f64]) - ) - (unreachable) - ) - (func $16 - (drop - (ref.null $[mut:f64]) - ) - (drop - (i32.const 2) - ) - (unreachable) - ) - (func $17 - (unreachable) - ) - (func $18 - (unreachable) - ) - (func $19 (param $0 (ref $[mut:f64])) (param $1 (ref null $[mut:f64])) - (array.copy $[mut:f64] $[mut:f64] - (local.get $0) - (i32.const 11) - (local.get $1) - (i32.const 42) - (i32.const 1337) - ) - ) - (func $20 (result (ref $[mut:f64])) - (array.init $[mut:f64] - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - (rtt.canon $[mut:f64]) - ) - ) - (func $21 (result (ref $[mut:i8])) - (array.init $[mut:i8] - (i32.const 4) - (i32.const 2) - (i32.const 1) - (rtt.canon $[mut:i8]) - ) - ) - (func $22 - (local $0 (ref null ${i32_f32_f64})) - (local $1 (ref null ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) (drop - (ref.test_static ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} + (ref.test ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (drop - (ref.cast_static ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} + (ref.cast ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (drop - (block $label$1 (result (ref ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|})) + (block $label$1 (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) (local.set $0 - (br_on_cast_static $label$1 ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} - (ref.null ${i32_f32_f64}) - ) - ) - (unreachable) - ) - ) - (drop - (block $label$2 (result (ref null ${i32_f32_f64})) - (local.set $1 - (br_on_cast_static_fail $label$2 ${i8_mut:i16_ref|{i32_f32_f64}|_mut:ref|{i32_f32_f64}|} + (br_on_cast $label$1 ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (unreachable) ) ) ) - (func $23 - (drop - (struct.new_default ${i32_f32_f64}) - ) - (drop - (struct.new ${i32_f32_f64} - (i32.const 1) - (f32.const 2.3450000286102295) - (f64.const 3.14159) - ) - ) - (drop - (array.new $[mut:f64] - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $[mut:ref?|[mut:f64]|] - (i32.const 10) - ) - ) - (drop - (array.init_static $[mut:f64] - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) ) diff -Nru binaryen-108/test/heap-types.wast.from-wast binaryen-99/test/heap-types.wast.from-wast --- binaryen-108/test/heap-types.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/heap-types.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,557 +1,199 @@ (module - (type $struct.A (struct (field i32) (field f32) (field $named f64))) - (type $struct.B (struct (field i8) (field (mut i16)) (field (ref $struct.A)) (field (mut (ref $struct.A))))) - (type $vector (array (mut f64))) + (type ${i32_f32_f64} (struct (field i32) (field f32) (field f64))) + (type $[mut:f64] (array (mut f64))) + (type ${} (struct )) (type $none_=>_none (func)) - (type $grandchild (struct (field i32) (field i64))) - (type $matrix (array (mut (ref null $vector)))) - (type $struct.C (struct (field $named-mut (mut f32)))) - (type $parent (struct )) - (type $child (struct (field i32))) - (type $bytes (array (mut i8))) - (type $anyref_=>_none (func (param anyref))) - (type $nested-child-struct (struct (field (mut (ref $child))))) - (type $ref|$struct.A|_=>_ref|$struct.B| (func (param (ref $struct.A)) (result (ref $struct.B)))) - (type $ref|$vector|_=>_ref|$matrix| (func (param (ref $vector)) (result (ref $matrix)))) - (type $words (array (mut i32))) - (type $nested-child-array (array (mut (ref $child)))) - (type $rtt_1_$parent_=>_none (func (param (rtt 1 $parent)))) - (type $rtt_$parent_=>_none (func (param (rtt $parent)))) - (type $ref|$vector|_ref?|$vector|_=>_none (func (param (ref $vector) (ref null $vector)))) - (type $none_=>_ref|$vector| (func (result (ref $vector)))) - (type $none_=>_ref|$bytes| (func (result (ref $bytes)))) - (global $rttparent (rtt 0 $parent) (rtt.canon $parent)) - (global $rttchild (rtt 1 $child) (rtt.sub $child + (type ${i32} (struct (field i32))) + (type ${i32_i64} (struct (field i32) (field i64))) + (type ${mut:f32} (struct (field (mut f32)))) + (type $[mut:i32] (array (mut i32))) + (type $[mut:i8] (array (mut i8))) + (type ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} (struct (field i8) (field (mut i16)) (field (ref null ${i32_f32_f64})) (field (mut (ref null ${i32_f32_f64}))))) + (type $[ref?|[mut:f64]|] (array (ref null $[mut:f64]))) + (type $rtt_1_${}_=>_none (func (param (rtt 1 ${})))) + (type $rtt_${}_=>_none (func (param (rtt ${})))) + (type $ref?|{i32_f32_f64}|_=>_ref?|{i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}| (func (param (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})))) + (type $ref?|[mut:f64]|_=>_ref?|[ref?|[mut:f64]|]| (func (param (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|])))) + (global $rttparent (rtt 0 ${}) (rtt.canon ${})) + (global $rttchild (rtt 1 ${i32}) (rtt.sub ${i32} (global.get $rttparent) )) - (global $rttgrandchild (rtt 2 $grandchild) (rtt.sub $grandchild + (global $rttgrandchild (rtt 2 ${i32_i64}) (rtt.sub ${i32_i64} (global.get $rttchild) )) - (global $rttfreshgrandchild (rtt 2 $grandchild) (rtt.fresh_sub $grandchild - (global.get $rttchild) - )) - (global $struct.new-in-global (ref $struct.A) (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - )) - (func $structs (param $x (ref $struct.A)) (result (ref $struct.B)) - (local $tA (ref null $struct.A)) - (local $tB (ref null $struct.B)) - (local $tc (ref null $struct.C)) - (local $tv (ref null $vector)) - (local $tm (ref null $matrix)) + (func $structs (param $x (ref null ${i32_f32_f64})) (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) + (local $tA (ref null ${i32_f32_f64})) + (local $tB (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) + (local $tc (ref null ${mut:f32})) + (local $tv (ref null $[mut:f64])) + (local $tm (ref null $[ref?|[mut:f64]|])) (drop (local.get $x) ) (drop - (struct.get $struct.A 0 + (struct.get ${i32_f32_f64} 0 (local.get $x) ) ) (drop - (struct.get $struct.A 1 + (struct.get ${i32_f32_f64} 1 (local.get $x) ) ) (drop - (struct.get $struct.A $named + (struct.get ${i32_f32_f64} 2 (local.get $x) ) ) (drop - (struct.get $struct.A $named + (struct.get ${i32_f32_f64} 2 (local.get $x) ) ) (drop - (struct.get $struct.A $named - (ref.null $struct.A) - ) - ) - (drop - (struct.get_u $struct.B 0 + (struct.get_u ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0 (local.get $tB) ) ) (drop - (struct.get_s $struct.B 0 + (struct.get_s ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0 (local.get $tB) ) ) (drop - (struct.get $grandchild 0 - (ref.null $grandchild) - ) - ) - (drop - (ref.null $struct.A) + (ref.null ${i32_f32_f64}) ) (drop - (block $block (result (ref null $struct.A)) + (block $block (result (ref null ${i32_f32_f64})) (local.get $x) ) ) (drop - (if (result (ref null $struct.A)) + (if (result (ref null ${i32_f32_f64})) (i32.const 1) (local.get $x) (local.get $x) ) ) (drop - (loop $loop-in (result (ref null $struct.A)) + (loop $loop-in (result (ref null ${i32_f32_f64})) (local.get $x) ) ) (drop - (select (result (ref null $struct.A)) + (select (result (ref null ${i32_f32_f64})) (local.get $x) (local.get $x) (i32.const 1) ) ) - (struct.set $struct.C $named-mut - (ref.null $struct.C) - (f32.const 100) - ) - (struct.set $nested-child-struct 0 - (ref.null $nested-child-struct) - (ref.as_non_null - (ref.null $grandchild) - ) + (struct.set ${i32_f32_f64} 0 + (local.get $x) + (i32.const 100) ) (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) + (struct.new_default_with_rtt ${i32_f32_f64} + (rtt.canon ${i32_f32_f64}) ) ) (drop - (struct.new_with_rtt $struct.A + (struct.new_with_rtt ${i32_f32_f64} + (rtt.canon ${i32_f32_f64}) (i32.const 1) (f32.const 2.3450000286102295) (f64.const 3.14159) - (rtt.canon $struct.A) ) ) (unreachable) ) - (func $arrays (param $x (ref $vector)) (result (ref $matrix)) - (local $tv (ref null $vector)) - (local $tm (ref null $matrix)) - (local $tb (ref null $bytes)) - (local $tw (ref null $words)) + (func $arrays (param $x (ref null $[mut:f64])) (result (ref null $[ref?|[mut:f64]|])) + (local $tv (ref null $[mut:f64])) + (local $tm (ref null $[ref?|[mut:f64]|])) + (local $tb (ref null $[mut:i8])) + (local $tw (ref null $[mut:i32])) (drop - (array.new_with_rtt $vector - (f64.const 3.14159) + (array.new_with_rtt $[mut:f64] + (rtt.canon $[mut:f64]) (i32.const 3) - (rtt.canon $vector) + (f64.const 3.14159) ) ) (drop - (array.new_default_with_rtt $matrix + (array.new_default_with_rtt $[ref?|[mut:f64]|] + (rtt.canon $[ref?|[mut:f64]|]) (i32.const 10) - (rtt.canon $matrix) ) ) (drop - (array.get $vector + (array.get $[mut:f64] (local.get $x) (i32.const 2) ) ) - (array.set $vector + (array.set $[mut:f64] (local.get $x) (i32.const 2) (f64.const 2.18281828) ) - (array.set $nested-child-array - (ref.null $nested-child-array) - (i32.const 3) - (ref.as_non_null - (ref.null $grandchild) - ) - ) (drop - (array.len $vector + (array.len $[mut:f64] (local.get $x) ) ) (drop - (array.get $words + (array.get $[mut:i32] (local.get $tw) (i32.const 1) ) ) (drop - (array.get_u $bytes + (array.get_u $[mut:i8] (local.get $tb) (i32.const 2) ) ) (drop - (array.get_s $bytes + (array.get_s $[mut:i8] (local.get $tb) (i32.const 3) ) ) (unreachable) ) - (func $rtt-param-with-depth (param $rtt (rtt 1 $parent)) + (func $rtt-param-with-depth (param $rtt (rtt 1 ${})) (nop) ) - (func $rtt-param-without-depth (param $rtt (rtt $parent)) + (func $rtt-param-without-depth (param $rtt (rtt ${})) (nop) ) (func $rtt-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) + (local $temp.A (ref null ${i32_f32_f64})) (drop - (ref.test - (ref.null $struct.A) - (rtt.canon $struct.B) + (ref.test ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (drop - (ref.cast - (ref.null $struct.A) - (rtt.canon $struct.B) + (ref.cast ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) (drop - (block $out (result (ref $struct.B)) + (block $out (result (ref null ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|})) (local.set $temp.A - (br_on_cast $out - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (block - (drop - (ref.null $struct.A) - ) - (unreachable) - ) - (unreachable) - ) - ) - (drop - (block $out2 (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_fail $out2 - (ref.null $struct.A) - (rtt.canon $struct.B) - ) - ) - (ref.null $struct.A) - ) - ) - ) - (func $ref.is_X (param $x anyref) - (if - (ref.is_func - (local.get $x) - ) - (unreachable) - ) - (if - (ref.is_data - (local.get $x) - ) - (unreachable) - ) - (if - (ref.is_i31 - (local.get $x) - ) - (unreachable) - ) - ) - (func $ref.as_X (param $x anyref) - (drop - (ref.as_non_null - (local.get $x) - ) - ) - (drop - (ref.as_func - (local.get $x) - ) - ) - (drop - (ref.as_data - (local.get $x) - ) - ) - (drop - (ref.as_i31 - (local.get $x) - ) - ) - ) - (func $br_on_X (param $x anyref) - (local $y anyref) - (local $z anyref) - (local $temp-func funcref) - (local $temp-data (ref null data)) - (local $temp-i31 (ref null i31)) - (block $null - (local.set $z - (br_on_null $null - (local.get $x) - ) - ) - ) - (drop - (block $func (result funcref) - (local.set $y - (br_on_func $func - (local.get $x) - ) - ) - (ref.null func) - ) - ) - (drop - (block $data (result (ref null data)) - (local.set $y - (br_on_data $data - (local.get $x) - ) - ) - (ref.null data) - ) - ) - (drop - (block $i31 (result (ref null i31)) - (local.set $y - (br_on_i31 $i31 - (local.get $x) + (br_on_cast $out ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) + (rtt.canon ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|}) ) ) - (ref.null i31) - ) - ) - (drop - (block $non-null (result (ref any)) - (br_on_non_null $non-null - (local.get $x) - ) - (unreachable) - ) - ) - (drop - (block $non-func (result anyref) - (local.set $temp-func - (br_on_non_func $non-func - (local.get $x) - ) - ) - (ref.null any) - ) - ) - (drop - (block $non-data (result anyref) - (local.set $temp-data - (br_on_non_data $non-data - (local.get $x) - ) - ) - (ref.null any) - ) - ) - (drop - (block $non-i31 (result anyref) - (local.set $temp-i31 - (br_on_non_i31 $non-i31 - (local.get $x) - ) - ) - (ref.null any) - ) - ) - ) - (func $unreachables-1 - (drop - (block ;; (replaces something unreachable we can't emit) - (drop - (unreachable) - ) - ) - ) - ) - (func $unreachables-2 - (struct.set $struct.C $named-mut - (ref.null $struct.C) - (unreachable) - ) - ) - (func $unreachables-3 - (block ;; (replaces something unreachable we can't emit) - (drop - (unreachable) - ) - (drop - (unreachable) - ) - ) - ) - (func $unreachables-4 - (block ;; (replaces something unreachable we can't emit) - (drop - (unreachable) - ) - (drop - (f32.const 1) - ) - ) - ) - (func $unreachables-array-1 - (block ;; (replaces something unreachable we can't emit) - (drop - (unreachable) - ) - (drop - (i32.const 2) - ) - ) - ) - (func $unreachables-array-2 - (array.get $vector - (ref.null $vector) - (unreachable) - ) - ) - (func $unreachables-array-3 - (block ;; (replaces something unreachable we can't emit) - (drop - (unreachable) - ) - (drop - (i32.const 2) - ) - (drop - (f64.const 2.18281828) - ) - ) - ) - (func $unreachables-array-4 - (array.set $vector - (ref.null $vector) - (unreachable) - (f64.const 2.18281828) - ) - ) - (func $unreachables-array-5 - (array.set $vector - (ref.null $vector) - (i32.const 2) - (unreachable) - ) - ) - (func $unreachables-array-6 - (drop - (block - (unreachable) - ) - ) - ) - (func $unreachables-7 - (drop - (block ;; (replaces something unreachable we can't emit) - (drop + (br_on_cast $out ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} + (ref.null ${i32_f32_f64}) (unreachable) ) - ) - ) - ) - (func $array-copy (param $x (ref $vector)) (param $y (ref null $vector)) - (array.copy $vector $vector - (local.get $x) - (i32.const 11) - (local.get $y) - (i32.const 42) - (i32.const 1337) - ) - ) - (func $array-init (result (ref $vector)) - (array.init $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - (rtt.canon $vector) - ) - ) - (func $array-init-packed (result (ref $bytes)) - (array.init $bytes - (i32.const 4) - (i32.const 2) - (i32.const 1) - (rtt.canon $bytes) - ) - ) - (func $static-operations - (local $temp.A (ref null $struct.A)) - (local $temp.B (ref null $struct.B)) - (drop - (ref.test_static $struct.B - (ref.null $struct.A) - ) - ) - (drop - (ref.cast_static $struct.B - (ref.null $struct.A) - ) - ) - (drop - (block $out-B (result (ref $struct.B)) - (local.set $temp.A - (br_on_cast_static $out-B $struct.B - (ref.null $struct.A) - ) - ) (unreachable) ) ) - (drop - (block $out-A (result (ref null $struct.A)) - (local.set $temp.B - (br_on_cast_static_fail $out-A $struct.B - (ref.null $struct.A) - ) - ) - (unreachable) - ) - ) - ) - (func $static-constructions - (drop - (struct.new_default $struct.A) - ) - (drop - (struct.new $struct.A - (i32.const 1) - (f32.const 2.3450000286102295) - (f64.const 3.14159) - ) - ) - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - (drop - (array.new_default $matrix - (i32.const 10) - ) - ) - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) ) ) diff -Nru binaryen-108/test/hello_libcxx.cpp binaryen-99/test/hello_libcxx.cpp --- binaryen-108/test/hello_libcxx.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/hello_libcxx.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,8 @@ #include -int main() { +int main() +{ std::cout << "hello, world!" << std::endl; return 0; } + diff -Nru binaryen-108/test/hello_world.c binaryen-99/test/hello_world.c --- binaryen-108/test/hello_world.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/hello_world.c 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,7 @@ -#include +#include int main() { printf("hello, world!\n"); return 0; } + diff -Nru binaryen-108/test/int_ops.c binaryen-99/test/int_ops.c --- binaryen-108/test/int_ops.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/int_ops.c 2021-01-07 20:01:06.000000000 +0000 @@ -11,12 +11,10 @@ unsigned EMSCRIPTEN_KEEPALIVE udiv(unsigned x, unsigned y) { return x / y; } int EMSCRIPTEN_KEEPALIVE srem(int x, int y) { return x % y; } unsigned EMSCRIPTEN_KEEPALIVE urem(unsigned x, unsigned y) { return x % y; } -int EMSCRIPTEN_KEEPALIVE and (int x, int y) { return x & y; } -int EMSCRIPTEN_KEEPALIVE or (int x, int y) { return x | y; } -int EMSCRIPTEN_KEEPALIVE xor - (int x, int y) { return x ^ y; } int EMSCRIPTEN_KEEPALIVE shl(int x, int y) { - return x << y; -} +int EMSCRIPTEN_KEEPALIVE and(int x, int y) { return x & y; } +int EMSCRIPTEN_KEEPALIVE or(int x, int y) { return x | y; } +int EMSCRIPTEN_KEEPALIVE xor(int x, int y) { return x ^ y; } +int EMSCRIPTEN_KEEPALIVE shl(int x, int y) { return x << y; } int EMSCRIPTEN_KEEPALIVE sshr(int x, int y) { return x >> y; } unsigned EMSCRIPTEN_KEEPALIVE ushr(unsigned x, unsigned y) { return x >> y; } @@ -31,3 +29,4 @@ int EMSCRIPTEN_KEEPALIVE gtu(unsigned x, unsigned y) { return x > y; } int EMSCRIPTEN_KEEPALIVE ges(int x, int y) { return x >= y; } int EMSCRIPTEN_KEEPALIVE geu(unsigned x, unsigned y) { return x >= y; } + diff -Nru binaryen-108/test/kitchen_sink.wast.fromBinary binaryen-99/test/kitchen_sink.wast.fromBinary --- binaryen-108/test/kitchen_sink.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/kitchen_sink.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 4096 4096) (data (i32.const 1026) "\14\00") (func $kitchensink (result i32) diff -Nru binaryen-108/test/kitchen_sink.wast.from-wast binaryen-99/test/kitchen_sink.wast.from-wast --- binaryen-108/test/kitchen_sink.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/kitchen_sink.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 4096 4096) (data (i32.const 1026) "\14\00") (func $kitchensink (result i32) diff -Nru binaryen-108/test/let.txt binaryen-99/test/let.txt --- binaryen-108/test/let.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/let.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -;; source code for let.wasm, which was created by wasp -(module - (type $vector (array (mut f64))) - (func $main - (local $x i32) - (local $y i32) - (drop (local.get $x)) ;; 0 is the index appearing in the binary - ;; first let - (array.new_with_rtt $vector - (f64.const 3.14159) - (i32.const 1) - (rtt.canon $vector) - ) - (let (local $v (ref $vector)) - (drop (local.get $v)) ;; 0 - (drop (local.get $x)) ;; 1 - ;; another one, nested - (array.new_with_rtt $vector - (f64.const 1234) - (i32.const 2) - (rtt.canon $vector) - ) - (let (local $w (ref $vector)) - (drop (local.get $v)) ;; 1 - (drop (local.get $w)) ;; 0 - (drop (local.get $x)) ;; 2 - ) - ) - ;; another one, later - (array.new_with_rtt $vector - (f64.const 2.1828) - (i32.const 3) - (rtt.canon $vector) - ) - (let (local $v (ref $vector)) - (drop (local.get $v)) ;; 0 - (drop (local.get $x)) ;; 1 - ) - (drop (local.get $x)) ;; 0 - ) -) - Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/let.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/let.wasm differ diff -Nru binaryen-108/test/let.wasm.fromBinary binaryen-99/test/let.wasm.fromBinary --- binaryen-108/test/let.wasm.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/let.wasm.fromBinary 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -(module - (type $[mut:f64] (array (mut f64))) - (type $none_=>_none (func)) - (func $0 - (local $0 i32) - (local $1 i32) - (local $2 (ref null $[mut:f64])) - (local $3 (ref null $[mut:f64])) - (local $4 (ref null $[mut:f64])) - (drop - (local.get $0) - ) - (block - (local.set $2 - (array.new_with_rtt $[mut:f64] - (f64.const 3.14159) - (i32.const 1) - (rtt.canon $[mut:f64]) - ) - ) - (block - (drop - (ref.as_non_null - (local.get $2) - ) - ) - (drop - (local.get $0) - ) - (block - (local.set $3 - (array.new_with_rtt $[mut:f64] - (f64.const 1234) - (i32.const 2) - (rtt.canon $[mut:f64]) - ) - ) - (block - (drop - (ref.as_non_null - (local.get $2) - ) - ) - (drop - (ref.as_non_null - (local.get $3) - ) - ) - (drop - (local.get $0) - ) - ) - ) - ) - ) - (block - (local.set $4 - (array.new_with_rtt $[mut:f64] - (f64.const 2.1828) - (i32.const 3) - (rtt.canon $[mut:f64]) - ) - ) - (block - (drop - (ref.as_non_null - (local.get $4) - ) - ) - (drop - (local.get $0) - ) - ) - ) - (drop - (local.get $0) - ) - ) -) - diff -Nru binaryen-108/test/linker/baz.c binaryen-99/test/linker/baz.c --- binaryen-108/test/linker/baz.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/linker/baz.c 2021-01-07 20:01:06.000000000 +0000 @@ -1 +1,2 @@ -void baz() {} +void baz() { +} diff -Nru binaryen-108/test/linker/foo.c binaryen-99/test/linker/foo.c --- binaryen-108/test/linker/foo.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/linker/foo.c 2021-01-07 20:01:06.000000000 +0000 @@ -1 +1,3 @@ -int foo() { return 43; } +int foo() { + return 43; +} diff -Nru binaryen-108/test/linker/main.c binaryen-99/test/linker/main.c --- binaryen-108/test/linker/main.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/linker/main.c 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,6 @@ -int foo() { return 42; } +int foo() { + return 42; +} void bar(); diff -Nru binaryen-108/test/lit/binary/bad-ref-as.test binaryen-99/test/lit/binary/bad-ref-as.test --- binaryen-108/test/lit/binary/bad-ref-as.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/binary/bad-ref-as.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -;; Test that we error properly on a file with a ref.as of a non-ref type. - -;; RUN: not wasm-opt %s.wasm 2>&1 | filecheck %s - -;; CHECK: parse exception: bad input type for ref.as: i32 - Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lit/binary/bad-ref-as.test.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lit/binary/bad-ref-as.test.wasm differ diff -Nru binaryen-108/test/lit/binary/dylink.test binaryen-99/test/lit/binary/dylink.test --- binaryen-108/test/lit/binary/dylink.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/binary/dylink.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -# Verify that extra bytes in the dylink section are preserved. -# -# `dylink.test.wasm` was generated using emscripten to build a side -# module with two TLS exports (which adds extra information to the -# dylink section) using: -# `emcc -s USE_PTHREAD -s SIDE_MODULE side.c` -# -# side.c: -# _Thread_local int foo = 10; -# _Thread_local int bar = 11; -# -# and then removing all sections except the dylink.0 section using: -# `llvm-objcopy --only-section=dylink.0` -RUN: wasm-opt -O1 %s.wasm -o %t.o -RUN: cmp %s.wasm %t.o Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lit/binary/dylink.test.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lit/binary/dylink.test.wasm differ diff -Nru binaryen-108/test/lit/binary/empty-param-name.test binaryen-99/test/lit/binary/empty-param-name.test --- binaryen-108/test/lit/binary/empty-param-name.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/binary/empty-param-name.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -;; Test that we show a warning on an empty local name, and do not crash. -;; -;; The binary contains this, processed by wabt with debug names: -;; -;; (module -;; (func $foo (import "imports" "foo") (param i32))) -;; -;; Wabt emits a name for that parameter, but it is the empty string. See -;; https://github.com/WebAssembly/wabt/issues/1799 - -;; RUN: wasm-opt %s.wasm 2>&1 | filecheck %s - -;; CHECK: warning: empty local name at index 0 in function foo - Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lit/binary/empty-param-name.test.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lit/binary/empty-param-name.test.wasm differ diff -Nru binaryen-108/test/lit/binary/prototype-nominal-format.test binaryen-99/test/lit/binary/prototype-nominal-format.test --- binaryen-108/test/lit/binary/prototype-nominal-format.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/binary/prototype-nominal-format.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -;; Test the we can properly parse the prototype nominal binary format that we no -;; longer emit. - -;; RUN: wasm-dis %s.wasm -all | filecheck %s - -;; CHECK: (module -;; CHECK-NEXT: (type $super-struct (struct (field i32))) -;; CHECK-NEXT: (type $sub-struct (struct (field i32) (field i64))) -;; CHECK-NEXT: (type $none_=>_ref|$super-struct| (func (result (ref $super-struct)))) -;; CHECK-NEXT: (type $none_=>_ref|$sub-struct| (func (result (ref $sub-struct)))) -;; CHECK-NEXT: (type $none_=>_ref|$super-array| (func (result (ref $super-array)))) -;; CHECK-NEXT: (type $none_=>_ref|$sub-array| (func (result (ref $sub-array)))) -;; CHECK-NEXT: (type $super-array (array (ref $super-struct))) -;; CHECK-NEXT: (type $sub-array (array (ref $sub-struct))) -;; CHECK-NEXT: (func $make-super-struct (result (ref $super-struct)) -;; CHECK-NEXT: (call $make-sub-struct) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (func $make-sub-struct (result (ref $sub-struct)) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (func $make-super-array (result (ref $super-array)) -;; CHECK-NEXT: (call $make-sub-array) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (func $make-sub-array (result (ref $sub-array)) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lit/binary/prototype-nominal-format.test.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lit/binary/prototype-nominal-format.test.wasm differ diff -Nru binaryen-108/test/lit/binary/stacky-eh.test binaryen-99/test/lit/binary/stacky-eh.test --- binaryen-108/test/lit/binary/stacky-eh.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/binary/stacky-eh.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -# Verify stacky EH binary can be parsed correctly. -# -# stacky-eh.test.wasm contains below: -# try -# nop -# catch 0 # tag type i32 -# i32.const 3 -# local.set 1 -# local.set 2 -# -# (This binary was generated by -# 'wasm-opt --optimize-level=3 --generate-stack-ir -optimize-stack-ir') -# -# This code is 'stacky' in Binaryen parlance. In the binary reader, Binaryen has -# a special routine of creating a block and a local.get/local.set to read stacky -# code into Binaryen AST. So if we don't do any post-fixup, the 'catch' block -# becomes: -# (catch $e-i32 -# (local.set 2 -# (block (result i32) -# (local.set $new -# (pop i32) -# ) -# (local.set 1 -# (i32.const 3) -# ) -# (local.get $new) -# ) -# ) -# ) -# Here the 'block' and `local $new' are newly created to read the stacky code. -# But now the 'pop' ends up nested within the 'block', which is invalid. This -# test tests if this invalid code is correctly fixed up in the binary reader. -# The fixup will hoist the 'pop' and create another local to store it right -# after 'catch'. - -RUN: wasm-opt -all %s.wasm --print | filecheck %s - -# CHECK: (func $0 -# CHECK-NEXT: (local $0 i32) -# CHECK-NEXT: (local $1 i32) -# CHECK-NEXT: (local $2 i32) -# CHECK-NEXT: (local $3 i32) -# CHECK-NEXT: (local $4 i32) -# CHECK-NEXT: (try $label$3 -# CHECK-NEXT: (do -# CHECK-NEXT: (nop) -# CHECK-NEXT: ) -# CHECK-NEXT: (catch $tag$0 -# CHECK-NEXT: (local.set $4 -# CHECK-NEXT: (pop i32) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.set $2 -# CHECK-NEXT: (block (result i32) -# CHECK-NEXT: (local.set $3 -# CHECK-NEXT: (local.get $4) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.set $1 -# CHECK-NEXT: (i32.const 3) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.get $3) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: ) Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lit/binary/stacky-eh.test.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lit/binary/stacky-eh.test.wasm differ diff -Nru binaryen-108/test/lit/binary/stacky-nn-tuple.test binaryen-99/test/lit/binary/stacky-nn-tuple.test --- binaryen-108/test/lit/binary/stacky-nn-tuple.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/binary/stacky-nn-tuple.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,112 +0,0 @@ -# Verify stacky non-nullable tuples binary can be parsed correctly. The wasm -# contains code that uses pops to get a tuple and store it in a local, then -# reads those values. The file contains this: -# -# (module -# (type $A (struct (field (mut i32)))) -# (type $B (struct (field (mut i32)) (field (mut i32)))) -# (tag $tag$0 (param (ref $A) (ref $B))) -# (func $foo -# (local $temp ((ref null $A) (ref null $B))) -# (try $label$3 -# (do -# (nop) -# ) -# (catch $tag$0 -# (local.set $temp -# (pop (ref $A) (ref $B)) -# ) -# (drop -# (ref.as_non_null -# (tuple.extract 0 -# (local.get $temp) -# ) -# ) -# ) -# (drop -# (ref.as_non_null -# (tuple.extract 1 -# (local.get $temp) -# ) -# ) -# ) -# (unreachable) -# ) -# ) -# ) -# ) - -RUN: wasm-opt -all --enable-gc-nn-locals %s.wasm -all --print - -# CHECK: (module -# CHECK-NEXT: (type ${mut:i32} (struct (field (mut i32)))) -# CHECK-NEXT: (type ${mut:i32_mut:i32} (struct (field (mut i32)) (field (mut i32)))) -# CHECK-NEXT: (type $ref|{mut:i32}|_ref|{mut:i32_mut:i32}|_=>_none (func (param (ref ${mut:i32}) (ref ${mut:i32_mut:i32})))) -# CHECK-NEXT: (type $none_=>_none (func)) -# CHECK-NEXT: (tag $tag$0 (param (ref ${mut:i32}) (ref ${mut:i32_mut:i32}))) -# CHECK-NEXT: (func $0 -# CHECK-NEXT: (local $0 (ref null ${mut:i32})) -# CHECK-NEXT: (local $1 (ref null ${mut:i32_mut:i32})) -# CHECK-NEXT: (local $2 (ref null ${mut:i32_mut:i32})) -# CHECK-NEXT: (local $3 ((ref ${mut:i32}) (ref ${mut:i32_mut:i32}))) -# CHECK-NEXT: (local $4 (ref ${mut:i32})) -# CHECK-NEXT: (local $5 (ref null ${mut:i32})) -# CHECK-NEXT: (local $6 (ref null ${mut:i32})) -# CHECK-NEXT: (try $label$3 -# CHECK-NEXT: (do -# CHECK-NEXT: (nop) -# CHECK-NEXT: ) -# CHECK-NEXT: (catch $tag$0 -# CHECK-NEXT: (local.set $3 -# CHECK-NEXT: (pop (ref ${mut:i32}) (ref ${mut:i32_mut:i32})) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.set $0 -# CHECK-NEXT: (block (result (ref ${mut:i32})) -# CHECK-NEXT: (local.set $4 -# CHECK-NEXT: (tuple.extract 0 -# CHECK-NEXT: (local.get $3) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.set $1 -# CHECK-NEXT: (tuple.extract 1 -# CHECK-NEXT: (local.get $3) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.get $4) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: (drop -# CHECK-NEXT: (ref.as_non_null -# CHECK-NEXT: (block (result (ref null ${mut:i32})) -# CHECK-NEXT: (local.set $5 -# CHECK-NEXT: (local.get $0) -# CHECK-NEXT: ) -# CHECK-NEXT: (drop -# CHECK-NEXT: (local.get $1) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.get $5) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: (drop -# CHECK-NEXT: (block (result (ref null ${mut:i32})) -# CHECK-NEXT: (local.set $6 -# CHECK-NEXT: (local.get $0) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.set $2 -# CHECK-NEXT: (local.get $1) -# CHECK-NEXT: ) -# CHECK-NEXT: (local.get $6) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: (drop -# CHECK-NEXT: (ref.as_non_null -# CHECK-NEXT: (local.get $2) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: (unreachable) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: ) -# CHECK-NEXT: Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lit/binary/stacky-nn-tuple.test.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lit/binary/stacky-nn-tuple.test.wasm differ diff -Nru binaryen-108/test/lit/exec/delegate-vacuum.wast binaryen-99/test/lit/exec/delegate-vacuum.wast --- binaryen-108/test/lit/exec/delegate-vacuum.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/exec/delegate-vacuum.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. - -;; RUN: wasm-opt %s --vacuum --fuzz-exec -all -q -o /dev/null 2>&1 | filecheck %s -;; Test the effect of vaccum on delegation. The delegate target must not -;; "escape" the current function scope and affect anything external, that is, -;; it must be cleared on function exit. - -(module - (tag $tag$0 (param i32)) - ;; CHECK: [fuzz-exec] calling export-1 - ;; CHECK-NEXT: [exception thrown: tag$0 0] - (func "export-1" - (try - (do - (try - (do - (throw $tag$0 - (i32.const 0) - ) - ) - ;; A delegation that leads to the caller. This sets the delegate field on - ;; this function scope. - (delegate 1) - ) - ) - (catch_all - (nop) - ) - ) - ) - ;; CHECK: [fuzz-exec] calling export-2 - ;; CHECK-NEXT: [trap unreachable] - (func "export-2" - (call $inner) - (unreachable) - ) - (func $inner - ;; This inner function must not notice the delegate field that was set by - ;; the call to the previous export (if it does notice it, it would delegate - ;; to the caller or something else invalid, and the execution results would - ;; differ, causing fuzz-exec to fail). - (try - (do - (throw $tag$0 - (i32.const 0) - ) - ) - (catch_all - (nop) - ) - ) - ) -) -;; CHECK: [fuzz-exec] calling export-1 -;; CHECK-NEXT: [exception thrown: tag$0 0] - -;; CHECK: [fuzz-exec] calling export-2 -;; CHECK-NEXT: [trap unreachable] -;; CHECK-NEXT: [fuzz-exec] comparing export-1 -;; CHECK-NEXT: [fuzz-exec] comparing export-2 diff -Nru binaryen-108/test/lit/exec/eh.wast binaryen-99/test/lit/exec/eh.wast --- binaryen-108/test/lit/exec/eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/exec/eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. - -;; RUN: wasm-opt %s -all --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s - -(module - (tag $e-i32 (param i32)) - - ;; CHECK: [fuzz-exec] calling throw - ;; CHECK-NEXT: [exception thrown: e-i32 1] - (func "throw" - (throw $e-i32 (i32.const 1)) - ) - - ;; CHECK: [fuzz-exec] calling try-catch - (func "try-catch" - (try - (do - (throw $e-i32 (i32.const 2)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - ) - ) - - ;; CHECK: [fuzz-exec] calling catchless-try - ;; CHECK-NEXT: [exception thrown: e-i32 3] - (func "catchless-try" - (try - (do - (throw $e-i32 (i32.const 3)) - ) - ) - ) - - ;; CHECK: [fuzz-exec] calling try-delegate - ;; CHECK-NEXT: [exception thrown: e-i32 4] - (func "try-delegate" - (try $l0 - (do - (try - (do - (throw $e-i32 (i32.const 4)) - ) - (delegate $l0) - ) - ) - ) - ) -) -;; CHECK: [fuzz-exec] calling throw -;; CHECK-NEXT: [exception thrown: e-i32 1] - -;; CHECK: [fuzz-exec] calling try-catch - -;; CHECK: [fuzz-exec] calling catchless-try -;; CHECK-NEXT: [exception thrown: e-i32 3] - -;; CHECK: [fuzz-exec] calling try-delegate -;; CHECK-NEXT: [exception thrown: e-i32 4] -;; CHECK-NEXT: [fuzz-exec] comparing catchless-try -;; CHECK-NEXT: [fuzz-exec] comparing throw -;; CHECK-NEXT: [fuzz-exec] comparing try-catch -;; CHECK-NEXT: [fuzz-exec] comparing try-delegate diff -Nru binaryen-108/test/lit/exec/non-nullable.wast binaryen-99/test/lit/exec/non-nullable.wast --- binaryen-108/test/lit/exec/non-nullable.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/exec/non-nullable.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. - -;; RUN: wasm-opt %s -all --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s - -(module - ;; CHECK: [fuzz-exec] calling get-ref - ;; CHECK-NEXT: [trap fuzzer can only send defaultable parameters to exports] - (func "get-ref" (param $0 (ref any)) - (nop) - ) -) -;; CHECK: [fuzz-exec] calling get-ref -;; CHECK-NEXT: [trap fuzzer can only send defaultable parameters to exports] -;; CHECK-NEXT: [fuzz-exec] comparing get-ref diff -Nru binaryen-108/test/lit/exec/rtts.wast binaryen-99/test/lit/exec/rtts.wast --- binaryen-108/test/lit/exec/rtts.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/exec/rtts.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,153 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. - -;; Check that allocation and casting instructions with and without RTTs can be -;; mixed correctly. - -;; RUN: wasm-opt %s -all --fuzz-exec-before -q --structural -o /dev/null 2>&1 \ -;; RUN: | filecheck %s --check-prefix=EQREC - -;; RUN: wasm-opt %s -all --fuzz-exec-before -q --nominal -o /dev/null 2>&1 \ -;; RUN: | filecheck %s --check-prefix=NOMNL - -(module - (type $struct (struct_subtype i32 data)) - (type $sub-struct (struct_subtype i32 i32 $struct)) - - (import "fuzzing-support" "log-i32" (func $log (param i32))) - - (global $sub-rtt (rtt 1 $sub-struct) - (rtt.sub $sub-struct - (rtt.canon $struct) - ) - ) - - (func $make-sub-struct-canon (result (ref $struct)) - (struct.new_default_with_rtt $sub-struct - (rtt.canon $sub-struct) - ) - ) - - (func $make-sub-struct-sub (result (ref $struct)) - (struct.new_default_with_rtt $sub-struct - (global.get $sub-rtt) - ) - ) - - (func $make-sub-struct-static (result (ref $struct)) - (struct.new_default $sub-struct) - ) - - ;; EQREC: [fuzz-exec] calling canon-canon - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling canon-canon - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "canon-canon" - (call $log - (ref.test - (call $make-sub-struct-canon) - (rtt.canon $sub-struct) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling canon-sub - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling canon-sub - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "canon-sub" - (call $log - (ref.test - (call $make-sub-struct-canon) - (global.get $sub-rtt) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling canon-static - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling canon-static - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "canon-static" - (call $log - (ref.test_static $sub-struct - (call $make-sub-struct-canon) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling sub-canon - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling sub-canon - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "sub-canon" - (call $log - (ref.test - (call $make-sub-struct-sub) - (rtt.canon $sub-struct) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling sub-sub - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling sub-sub - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "sub-sub" - (call $log - (ref.test - (call $make-sub-struct-sub) - (global.get $sub-rtt) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling sub-static - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling sub-static - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "sub-static" - (call $log - (ref.test_static $sub-struct - (call $make-sub-struct-sub) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling static-canon - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling static-canon - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "static-canon" - (call $log - (ref.test - (call $make-sub-struct-static) - (rtt.canon $sub-struct) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling static-sub - ;; EQREC-NEXT: [LoggingExternalInterface logging 0] - ;; NOMNL: [fuzz-exec] calling static-sub - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "static-sub" - (call $log - (ref.test - (call $make-sub-struct-static) - (global.get $sub-rtt) - ) - ) - ) - - ;; EQREC: [fuzz-exec] calling static-static - ;; EQREC-NEXT: [LoggingExternalInterface logging 1] - ;; NOMNL: [fuzz-exec] calling static-static - ;; NOMNL-NEXT: [LoggingExternalInterface logging 1] - (func "static-static" - (call $log - (ref.test_static $sub-struct - (call $make-sub-struct-static) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/exec/trap.wast binaryen-99/test/lit/exec/trap.wast --- binaryen-108/test/lit/exec/trap.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/exec/trap.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. - -;; RUN: wasm-opt %s --vacuum --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s -;; RUN: wasm-opt %s --ignore-implicit-traps --vacuum --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s --check-prefix=IIT -;; RUN: wasm-opt %s --traps-never-happen --vacuum --fuzz-exec -q -o /dev/null 2>&1 | filecheck %s --check-prefix=TNH - -(module - ;; CHECK: [fuzz-exec] calling trap - ;; CHECK-NEXT: [trap unreachable] - ;; IIT: [fuzz-exec] calling trap - ;; IIT-NEXT: [trap unreachable] - ;; TNH: [fuzz-exec] calling trap - ;; TNH-NEXT: [trap unreachable] - (func "trap" - (unreachable) - ) - - (memory 1 1) - ;; CHECK: [fuzz-exec] calling load-trap - ;; CHECK-NEXT: [trap highest > memory: 65536 > 65532] - ;; IIT: [fuzz-exec] calling load-trap - ;; IIT-NEXT: [trap highest > memory: 65536 > 65532] - ;; TNH: [fuzz-exec] calling load-trap - ;; TNH-NEXT: [trap highest > memory: 65536 > 65532] - (func "load-trap" - ;; This load traps, so this cannot be removed. But if either of - ;; --ignore-implicit-traps or --traps-never-happen is set, this load is - ;; assumed not to trap and we end up optimizing this out with --vacuum, - ;; causes the trap behavior to change. This should not result in [fuzz-exec] - ;; comparison failure. - (drop - (i32.load (i32.const 65536)) - ) - ) -) -;; CHECK: [fuzz-exec] calling trap -;; CHECK-NEXT: [trap unreachable] - -;; CHECK: [fuzz-exec] calling load-trap -;; CHECK-NEXT: [trap highest > memory: 65536 > 65532] -;; CHECK-NEXT: [fuzz-exec] comparing load-trap -;; CHECK-NEXT: [fuzz-exec] comparing trap - -;; IIT: [fuzz-exec] calling trap -;; IIT-NEXT: [trap unreachable] - -;; IIT: [fuzz-exec] calling load-trap -;; IIT-NEXT: [fuzz-exec] comparing load-trap -;; IIT-NEXT: [fuzz-exec] comparing trap - -;; TNH: [fuzz-exec] calling trap - -;; TNH: [fuzz-exec] calling load-trap -;; TNH-NEXT: [fuzz-exec] comparing load-trap -;; TNH-NEXT: [fuzz-exec] comparing trap diff -Nru binaryen-108/test/lit/forward-declared-types.wast binaryen-99/test/lit/forward-declared-types.wast --- binaryen-108/test/lit/forward-declared-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/forward-declared-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; Test that types can be used before they are defined - -;; RUN: wasm-opt %s -all -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $func (func)) - - ;; CHECK: (type $struct (struct (field (ref $array)) (field (ref null $func)))) - ;; NOMNL: (type $func (func_subtype func)) - - ;; NOMNL: (type $struct (struct_subtype (field (ref $array)) (field (ref null $func)) data)) - (type $struct (struct - (field (ref $array)) - (field (ref null $func)) - )) - ;; CHECK: (type $array (array (rtt 2 $func))) - ;; NOMNL: (type $array (array_subtype (rtt 2 $func) data)) - (type $array (array (field (rtt 2 $func)))) - (type $func (func)) - - (func (result (ref null $struct)) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/fuzz-types/isorecursive.test binaryen-99/test/lit/fuzz-types/isorecursive.test --- binaryen-108/test/lit/fuzz-types/isorecursive.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/fuzz-types/isorecursive.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -;; RUN: wasm-fuzz-types --hybrid -v --seed=0 | filecheck %s - -;; CHECK: (rec -;; CHECK-NEXT: (type $0 (struct_subtype data)) -;; CHECK-NEXT: (type $1 (func_subtype (param i31ref) (result dataref) func)) -;; CHECK-NEXT: (type $2 (array_subtype i32 data)) -;; CHECK-NEXT: (type $3 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $4 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $5 (array_subtype i32 $3)) -;; CHECK-NEXT: (type $6 (array_subtype i32 $3)) -;; CHECK-NEXT: (type $7 (struct_subtype $0)) -;; CHECK-NEXT: (type $8 (struct_subtype $0)) -;; CHECK-NEXT: (type $9 (array_subtype i32 $6)) -;; CHECK-NEXT: (type $10 (struct_subtype $0)) -;; CHECK-NEXT: (type $11 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $12 (struct_subtype $0)) -;; CHECK-NEXT: (type $13 (array_subtype i32 $6)) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $14 (struct_subtype $10)) -;; CHECK-NEXT: (type $15 (func_subtype (param i31ref) (result dataref) $1)) -;; CHECK-NEXT: (type $16 (array_subtype i32 $2)) -;; CHECK-NEXT: (type $17 (struct_subtype $14)) -;; CHECK-NEXT: (type $18 (struct_subtype (field (mut funcref) (mut (ref null $7)) funcref) $12)) -;; CHECK-NEXT: (type $19 (func_subtype (param i31ref) (result dataref) $15)) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/fuzz-types/nominal.test binaryen-99/test/lit/fuzz-types/nominal.test --- binaryen-108/test/lit/fuzz-types/nominal.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/fuzz-types/nominal.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -;; RUN: wasm-fuzz-types --nominal -v --seed=0 | filecheck %s - -;; CHECK: (type $0 (struct_subtype (field (ref null $9) (ref $5)) data)) -;; CHECK-NEXT: (type $1 (func_subtype (param (rtt 0 $8)) func)) -;; CHECK-NEXT: (type $2 (struct_subtype (field (mut (rtt $19)) (ref $4)) data)) -;; CHECK-NEXT: (type $3 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $2)) -;; CHECK-NEXT: (type $4 (struct_subtype (field (mut (rtt $19)) (ref $4) (mut (ref $13))) $2)) -;; CHECK-NEXT: (type $5 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $3)) -;; CHECK-NEXT: (type $6 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $3)) -;; CHECK-NEXT: (type $7 (struct_subtype (field (ref null $9) (ref $5) eqref (mut (ref null $3)) (mut (rtt $18)) dataref) $0)) -;; CHECK-NEXT: (type $8 (struct_subtype (field (ref $9) (ref $5) (rtt 2 $1) (mut (rtt $17)) (mut (rtt i31)) (rtt $8)) $0)) -;; CHECK-NEXT: (type $9 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64) (rtt 2 $15)) $6)) -;; CHECK-NEXT: (type $10 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $11 (struct_subtype (field (mut (rtt $19)) (ref $4)) $2)) -;; CHECK-NEXT: (type $12 (struct_subtype (field (ref null $9) (ref $5)) $0)) -;; CHECK-NEXT: (type $13 (struct_subtype (field (mut (rtt $19)) (ref $4) i64 (mut (ref null $2)) (mut i64)) $6)) -;; CHECK-NEXT: (type $14 (struct_subtype (field (ref null $9) (ref $5)) $10)) -;; CHECK-NEXT: (type $15 (func_subtype (param (rtt 0 $8)) $1)) -;; CHECK-NEXT: (type $16 (struct_subtype (field (mut (rtt $19)) (ref $4) v128) $2)) -;; CHECK-NEXT: (type $17 (struct_subtype (field (ref null $9) (ref $5)) $14)) -;; CHECK-NEXT: (type $18 (struct_subtype (field (ref null $9) (ref $5)) $12)) -;; CHECK-NEXT: (type $19 (func_subtype (param (rtt 0 $8)) $15)) diff -Nru binaryen-108/test/lit/fuzz-types/structural.test binaryen-99/test/lit/fuzz-types/structural.test --- binaryen-108/test/lit/fuzz-types/structural.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/fuzz-types/structural.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -;; RUN: wasm-fuzz-types --structural -v --seed=0 | filecheck %s - -;; CHECK: (type $0 (struct (field (ref null $9) (ref $3)))) -;; CHECK-NEXT: (type $1 (func (param (rtt 0 $8)))) -;; CHECK-NEXT: (type $2 (struct (field (mut (rtt $1)) (ref $4)))) -;; CHECK-NEXT: (type $3 (struct (field (mut (rtt $1)) (ref $4) i64 (mut (ref null $2)) (mut i64)))) -;; CHECK-NEXT: (type $4 (struct (field (mut (rtt $1)) (ref $4) (mut (ref $3))))) -;; CHECK-NEXT: (type $5 identical to $3) -;; CHECK-NEXT: (type $6 identical to $3) -;; CHECK-NEXT: (type $7 (struct (field (ref null $9) (ref $3) eqref (mut (ref null $3)) (mut (rtt $0)) dataref))) -;; CHECK-NEXT: (type $8 (struct (field (ref $9) (ref $3) (rtt 2 $1) (mut (rtt $0)) (mut (rtt i31)) (rtt $8)))) -;; CHECK-NEXT: (type $9 (struct (field (mut (rtt $1)) (ref $4) i64 (mut (ref null $2)) (mut i64) (rtt 2 $1)))) -;; CHECK-NEXT: (type $10 identical to $0) -;; CHECK-NEXT: (type $11 identical to $2) -;; CHECK-NEXT: (type $12 identical to $0) -;; CHECK-NEXT: (type $13 identical to $3) -;; CHECK-NEXT: (type $14 identical to $0) -;; CHECK-NEXT: (type $15 identical to $1) -;; CHECK-NEXT: (type $16 (struct (field (mut (rtt $1)) (ref $4) v128))) -;; CHECK-NEXT: (type $17 identical to $0) -;; CHECK-NEXT: (type $18 identical to $0) -;; CHECK-NEXT: (type $19 identical to $1) diff -Nru binaryen-108/test/lit/gc-eh.wast binaryen-99/test/lit/gc-eh.wast --- binaryen-108/test/lit/gc-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/gc-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; Check that pops of GC types work correctly. - -;; RUN: wasm-opt -all %s -S -o - | filecheck %s -;; RUN: wasm-opt -all --nominal %s -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $A (struct (field (mut i32)))) - ;; NOMNL: (type $A (struct_subtype (field (mut i32)) data)) - (type $A (struct - (field (mut i32)) - )) - - ;; CHECK: (tag $tagA (param (ref $A))) - ;; NOMNL: (tag $tagA (param (ref $A))) - (tag $tagA (param (ref $A))) - - ;; CHECK: (func $foo (result (ref null $A)) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tagA - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (pop (ref $A)) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $none_=>_ref?|$A|) (result (ref null $A)) - ;; NOMNL-NEXT: (try $try - ;; NOMNL-NEXT: (do - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (catch $tagA - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (pop (ref $A)) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - (func $foo (result (ref null $A)) - (try - (do - (nop) - ) - (catch $tagA - (return - (pop (ref $A)) - ) - ) - ) - (ref.null $A) - ) -) diff -Nru binaryen-108/test/lit/gc-read-write-effects.wast binaryen-99/test/lit/gc-read-write-effects.wast --- binaryen-108/test/lit/gc-read-write-effects.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/gc-read-write-effects.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; Check that writing a struct field is not reordered with reading the same -;; struct field. - -;; RUN: wasm-opt -all --simplify-locals %s -S -o - | filecheck %s -;; RUN: wasm-opt -all --simplify-locals %s --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $A (struct (field (mut i32)))) - ;; NOMNL: (type $A (struct_subtype (field (mut i32)) data)) - (type $A (struct - (field (mut i32)) - )) - - ;; Check that this: - ;; - ;; y = a.0 - ;; a.0 = 10 - ;; return y - ;; - ;; Is not turned into this: - ;; - ;; a.0 = 10 - ;; return a.0 - ;; - ;; CHECK: (func $test (param $x (ref null $A)) (result i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $A 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $ref?|$A|_=>_i32) (param $x (ref null $A)) (result i32) - ;; NOMNL-NEXT: (local $y i32) - ;; NOMNL-NEXT: (local.set $y - ;; NOMNL-NEXT: (struct.get $A 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $A 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 10) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - (func $test (export "test") (param $x (ref null $A)) (result i32) - (local $y i32) - (local.set $y - (struct.get $A 0 - (local.get $x) - ) - ) - (struct.set $A 0 - (local.get $x) - (i32.const 10) - ) - (local.get $y) - ) -) diff -Nru binaryen-108/test/lit/heap-types.wast binaryen-99/test/lit/heap-types.wast --- binaryen-108/test/lit/heap-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/heap-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; Check that heap types are emitted properly in the binary format. This file -;; contains small modules that each use a single instruction with a heap type. -;; If we forgot to update collectHeapTypes then we would not write out their -;; type, and hit an error during --roundtrip. - -;; RUN: foreach %s %t wasm-opt -all --roundtrip -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt -all --roundtrip -S --nominal -o - | filecheck %s --check-prefix NOMNL - -(module - ;; CHECK: (type $struct.A (struct (field i32))) - ;; NOMNL: (type $struct.A (struct_subtype (field i32) data)) - (type $struct.A (struct i32)) - ;; NOMNL: (type $struct.B (struct_subtype (field i32) data)) - (type $struct.B (struct i32)) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test_static $struct.A - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test_static $struct.B - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $test - (drop - (ref.test_static $struct.B (ref.null $struct.A)) - ) - ) -) - -(module - ;; CHECK: (type $struct.A (struct (field i32))) - ;; NOMNL: (type $struct.A (struct_subtype (field i32) data)) - (type $struct.A (struct i32)) - ;; NOMNL: (type $struct.B (struct_subtype (field i32) data)) - (type $struct.B (struct i32)) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $struct.A - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $struct.B - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $test - (drop - (ref.cast_static $struct.B (ref.null $struct.A)) - ) - ) -) - -(module - ;; CHECK: (type $struct.A (struct (field i32))) - ;; NOMNL: (type $struct.A (struct_subtype (field i32) data)) - (type $struct.A (struct i32)) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.new_default $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $test - (drop - (struct.new_default $struct.A) - ) - ) -) - -(module - ;; CHECK: (type $vector (array (mut f64))) - ;; NOMNL: (type $vector (array_subtype (mut f64) data)) - (type $vector (array (mut f64))) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.new $vector - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (array.new $vector - ;; NOMNL-NEXT: (f64.const 3.14159) - ;; NOMNL-NEXT: (i32.const 3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $test - (drop - (array.new $vector - (f64.const 3.14159) - (i32.const 3) - ) - ) - ) -) - -(module - ;; CHECK: (type $vector (array (mut f64))) - ;; NOMNL: (type $vector (array_subtype (mut f64) data)) - (type $vector (array (mut f64))) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.init_static $vector - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: (f64.const 4) - ;; CHECK-NEXT: (f64.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (array.init_static $vector - ;; NOMNL-NEXT: (f64.const 1) - ;; NOMNL-NEXT: (f64.const 2) - ;; NOMNL-NEXT: (f64.const 4) - ;; NOMNL-NEXT: (f64.const 8) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $test - (drop - (array.init_static $vector - (f64.const 1) - (f64.const 2) - (f64.const 4) - (f64.const 8) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/help/wasm2js.test binaryen-99/test/lit/help/wasm2js.test --- binaryen-108/test/lit/help/wasm2js.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm2js.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,597 +0,0 @@ -;; RUN: wasm2js --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm2js INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Transform .wasm/.wat files to asm.js -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm2js options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file (stdout if not -;; CHECK-NEXT: specified) -;; CHECK-NEXT: -;; CHECK-NEXT: --allow-asserts Allow compilation of .wast -;; CHECK-NEXT: testing asserts -;; CHECK-NEXT: -;; CHECK-NEXT: --pedantic Emulate WebAssembly trapping -;; CHECK-NEXT: behavior -;; CHECK-NEXT: -;; CHECK-NEXT: --emscripten Emulate the glue in -;; CHECK-NEXT: emscripten-compatible form (and -;; CHECK-NEXT: not ES6 module form) -;; CHECK-NEXT: -;; CHECK-NEXT: --deterministic Replace WebAssembly trapping -;; CHECK-NEXT: behavior deterministically (the -;; CHECK-NEXT: default is to not care about -;; CHECK-NEXT: what would trap in wasm, like a -;; CHECK-NEXT: load out of bounds or integer -;; CHECK-NEXT: divide by zero; with this flag, -;; CHECK-NEXT: we try to be deterministic at -;; CHECK-NEXT: least in what happens, which -;; CHECK-NEXT: might or might not be to trap -;; CHECK-NEXT: like wasm, but at least should -;; CHECK-NEXT: not vary) -;; CHECK-NEXT: -;; CHECK-NEXT: --symbols-file Emit a symbols file that maps -;; CHECK-NEXT: function indexes to their -;; CHECK-NEXT: original names -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Optimization passes: -;; CHECK-NEXT: -------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --alignment-lowering lower unaligned loads and stores -;; CHECK-NEXT: to smaller aligned ones -;; CHECK-NEXT: -;; CHECK-NEXT: --asyncify async/await style transform, -;; CHECK-NEXT: allowing pausing and resuming -;; CHECK-NEXT: -;; CHECK-NEXT: --avoid-reinterprets Tries to avoid reinterpret -;; CHECK-NEXT: operations via more loads -;; CHECK-NEXT: -;; CHECK-NEXT: --cfp propagate constant struct field -;; CHECK-NEXT: values -;; CHECK-NEXT: -;; CHECK-NEXT: --coalesce-locals reduce # of locals by coalescing -;; CHECK-NEXT: -;; CHECK-NEXT: --coalesce-locals-learning reduce # of locals by coalescing -;; CHECK-NEXT: and learning -;; CHECK-NEXT: -;; CHECK-NEXT: --code-folding fold code, merging duplicates -;; CHECK-NEXT: -;; CHECK-NEXT: --code-pushing push code forward, potentially -;; CHECK-NEXT: making it not always execute -;; CHECK-NEXT: -;; CHECK-NEXT: --const-hoisting hoist repeated constants to a -;; CHECK-NEXT: local -;; CHECK-NEXT: -;; CHECK-NEXT: --dae removes arguments to calls in an -;; CHECK-NEXT: lto-like manner -;; CHECK-NEXT: -;; CHECK-NEXT: --dae-optimizing removes arguments to calls in an -;; CHECK-NEXT: lto-like manner, and optimizes -;; CHECK-NEXT: where we removed -;; CHECK-NEXT: -;; CHECK-NEXT: --dce removes unreachable code -;; CHECK-NEXT: -;; CHECK-NEXT: --dealign forces all loads and stores to -;; CHECK-NEXT: have alignment 1 -;; CHECK-NEXT: -;; CHECK-NEXT: --denan instrument the wasm to convert -;; CHECK-NEXT: NaNs into 0 at runtime -;; CHECK-NEXT: -;; CHECK-NEXT: --dfo optimizes using the DataFlow SSA -;; CHECK-NEXT: IR -;; CHECK-NEXT: -;; CHECK-NEXT: --directize turns indirect calls into direct -;; CHECK-NEXT: ones -;; CHECK-NEXT: -;; CHECK-NEXT: --duplicate-function-elimination removes duplicate functions -;; CHECK-NEXT: -;; CHECK-NEXT: --duplicate-import-elimination removes duplicate imports -;; CHECK-NEXT: -;; CHECK-NEXT: --dwarfdump dump DWARF debug info sections -;; CHECK-NEXT: from the read binary -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-target-features emit the target features section -;; CHECK-NEXT: in the output -;; CHECK-NEXT: -;; CHECK-NEXT: --extract-function leaves just one function (useful -;; CHECK-NEXT: for debugging) -;; CHECK-NEXT: -;; CHECK-NEXT: --extract-function-index leaves just one function -;; CHECK-NEXT: selected by index -;; CHECK-NEXT: -;; CHECK-NEXT: --flatten flattens out code, removing -;; CHECK-NEXT: nesting -;; CHECK-NEXT: -;; CHECK-NEXT: --fpcast-emu emulates function pointer casts, -;; CHECK-NEXT: allowing incorrect indirect -;; CHECK-NEXT: calls to (sometimes) work -;; CHECK-NEXT: -;; CHECK-NEXT: --func-metrics reports function metrics -;; CHECK-NEXT: -;; CHECK-NEXT: --generate-dyncalls generate dynCall fuctions used -;; CHECK-NEXT: by emscripten ABI -;; CHECK-NEXT: -;; CHECK-NEXT: --generate-i64-dyncalls generate dynCall functions used -;; CHECK-NEXT: by emscripten ABI, but only for -;; CHECK-NEXT: functions with i64 in their -;; CHECK-NEXT: signature (which cannot be -;; CHECK-NEXT: invoked via the wasm table -;; CHECK-NEXT: without JavaScript BigInt -;; CHECK-NEXT: support). -;; CHECK-NEXT: -;; CHECK-NEXT: --generate-stack-ir generate Stack IR -;; CHECK-NEXT: -;; CHECK-NEXT: --global-refining refine the types of globals -;; CHECK-NEXT: -;; CHECK-NEXT: --gto globally optimize GC types -;; CHECK-NEXT: -;; CHECK-NEXT: --heap2local replace GC allocations with -;; CHECK-NEXT: locals -;; CHECK-NEXT: -;; CHECK-NEXT: --i64-to-i32-lowering lower all uses of i64s to use -;; CHECK-NEXT: i32s instead -;; CHECK-NEXT: -;; CHECK-NEXT: --inline-main inline __original_main into main -;; CHECK-NEXT: -;; CHECK-NEXT: --inlining inline functions (you probably -;; CHECK-NEXT: want inlining-optimizing) -;; CHECK-NEXT: -;; CHECK-NEXT: --inlining-optimizing inline functions and optimizes -;; CHECK-NEXT: where we inlined -;; CHECK-NEXT: -;; CHECK-NEXT: --instrument-locals instrument the build with code -;; CHECK-NEXT: to intercept all loads and -;; CHECK-NEXT: stores -;; CHECK-NEXT: -;; CHECK-NEXT: --instrument-memory instrument the build with code -;; CHECK-NEXT: to intercept all loads and -;; CHECK-NEXT: stores -;; CHECK-NEXT: -;; CHECK-NEXT: --intrinsic-lowering lower away binaryen intrinsics -;; CHECK-NEXT: -;; CHECK-NEXT: --legalize-js-interface legalizes i64 types on the -;; CHECK-NEXT: import/export boundary -;; CHECK-NEXT: -;; CHECK-NEXT: --legalize-js-interface-minimally legalizes i64 types on the -;; CHECK-NEXT: import/export boundary in a -;; CHECK-NEXT: minimal manner, only on things -;; CHECK-NEXT: only JS will call -;; CHECK-NEXT: -;; CHECK-NEXT: --licm loop invariant code motion -;; CHECK-NEXT: -;; CHECK-NEXT: --limit-segments attempt to merge segments to fit -;; CHECK-NEXT: within web limits -;; CHECK-NEXT: -;; CHECK-NEXT: --local-cse common subexpression elimination -;; CHECK-NEXT: inside basic blocks -;; CHECK-NEXT: -;; CHECK-NEXT: --local-subtyping apply more specific subtypes to -;; CHECK-NEXT: locals where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --log-execution instrument the build with -;; CHECK-NEXT: logging of where execution goes -;; CHECK-NEXT: -;; CHECK-NEXT: --memory-packing packs memory into separate -;; CHECK-NEXT: segments, skipping zeros -;; CHECK-NEXT: -;; CHECK-NEXT: --memory64-lowering lower loads and stores to a -;; CHECK-NEXT: 64-bit memory to instead use a -;; CHECK-NEXT: 32-bit one -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-blocks merges blocks to their parents -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-locals merges locals when beneficial -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-similar-functions merges similar functions when -;; CHECK-NEXT: benefical -;; CHECK-NEXT: -;; CHECK-NEXT: --metrics reports metrics -;; CHECK-NEXT: -;; CHECK-NEXT: --minify-imports minifies import names (only -;; CHECK-NEXT: those, and not export names), -;; CHECK-NEXT: and emits a mapping to the -;; CHECK-NEXT: minified ones -;; CHECK-NEXT: -;; CHECK-NEXT: --minify-imports-and-exports minifies both import and export -;; CHECK-NEXT: names, and emits a mapping to -;; CHECK-NEXT: the minified ones -;; CHECK-NEXT: -;; CHECK-NEXT: --minify-imports-and-exports-and-modules minifies both import and export -;; CHECK-NEXT: names, and emits a mapping to -;; CHECK-NEXT: the minified ones, and minifies -;; CHECK-NEXT: the modules as well -;; CHECK-NEXT: -;; CHECK-NEXT: --mod-asyncify-always-and-only-unwind apply the assumption that -;; CHECK-NEXT: asyncify imports always unwind, -;; CHECK-NEXT: and we never rewind -;; CHECK-NEXT: -;; CHECK-NEXT: --mod-asyncify-never-unwind apply the assumption that -;; CHECK-NEXT: asyncify never unwinds -;; CHECK-NEXT: -;; CHECK-NEXT: --name-types (re)name all heap types -;; CHECK-NEXT: -;; CHECK-NEXT: --nm name list -;; CHECK-NEXT: -;; CHECK-NEXT: --once-reduction reduces calls to code that only -;; CHECK-NEXT: runs once -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-added-constants optimizes added constants into -;; CHECK-NEXT: load/store offsets -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-added-constants-propagate optimizes added constants into -;; CHECK-NEXT: load/store offsets, propagating -;; CHECK-NEXT: them across locals too -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-for-js early optimize of the -;; CHECK-NEXT: instruction combinations for js -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-instructions optimizes instruction -;; CHECK-NEXT: combinations -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-stack-ir optimize Stack IR -;; CHECK-NEXT: -;; CHECK-NEXT: --pick-load-signs pick load signs based on their -;; CHECK-NEXT: uses -;; CHECK-NEXT: -;; CHECK-NEXT: --poppify Tranform Binaryen IR into Poppy -;; CHECK-NEXT: IR -;; CHECK-NEXT: -;; CHECK-NEXT: --post-emscripten miscellaneous optimizations for -;; CHECK-NEXT: Emscripten-generated code -;; CHECK-NEXT: -;; CHECK-NEXT: --precompute computes compile-time -;; CHECK-NEXT: evaluatable expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --precompute-propagate computes compile-time -;; CHECK-NEXT: evaluatable expressions and -;; CHECK-NEXT: propagates them through locals -;; CHECK-NEXT: -;; CHECK-NEXT: --print print in s-expression format -;; CHECK-NEXT: -;; CHECK-NEXT: --print-call-graph print call graph -;; CHECK-NEXT: -;; CHECK-NEXT: --print-features print options for enabled -;; CHECK-NEXT: features -;; CHECK-NEXT: -;; CHECK-NEXT: --print-full print in full s-expression -;; CHECK-NEXT: format -;; CHECK-NEXT: -;; CHECK-NEXT: --print-function-map print a map of function indexes -;; CHECK-NEXT: to names -;; CHECK-NEXT: -;; CHECK-NEXT: --print-minified print in minified s-expression -;; CHECK-NEXT: format -;; CHECK-NEXT: -;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for -;; CHECK-NEXT: internal debugging) -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-imports removes imports and replaces -;; CHECK-NEXT: them with nops -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-memory removes memory segments -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-non-js-ops removes operations incompatible -;; CHECK-NEXT: with js -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-brs removes breaks from locations -;; CHECK-NEXT: that are not needed -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-module-elements removes unused module elements -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-names removes names from locations -;; CHECK-NEXT: that are never branched to -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-nonfunction-module-elements removes unused module elements -;; CHECK-NEXT: that are not functions -;; CHECK-NEXT: -;; CHECK-NEXT: --reorder-functions sorts functions by access -;; CHECK-NEXT: frequency -;; CHECK-NEXT: -;; CHECK-NEXT: --reorder-locals sorts locals by access frequency -;; CHECK-NEXT: -;; CHECK-NEXT: --rereloop re-optimize control flow using -;; CHECK-NEXT: the relooper algorithm -;; CHECK-NEXT: -;; CHECK-NEXT: --roundtrip write the module to binary, then -;; CHECK-NEXT: read it -;; CHECK-NEXT: -;; CHECK-NEXT: --rse remove redundant local.sets -;; CHECK-NEXT: -;; CHECK-NEXT: --safe-heap instrument loads and stores to -;; CHECK-NEXT: check for invalid behavior -;; CHECK-NEXT: -;; CHECK-NEXT: --set-globals sets specified globals to -;; CHECK-NEXT: specified values -;; CHECK-NEXT: -;; CHECK-NEXT: --signature-pruning remove params from function -;; CHECK-NEXT: signature types where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --signature-refining apply more specific subtypes to -;; CHECK-NEXT: signature types where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-globals miscellaneous globals-related -;; CHECK-NEXT: optimizations -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-globals-optimizing miscellaneous globals-related -;; CHECK-NEXT: optimizations, and optimizes -;; CHECK-NEXT: where we replaced global.gets -;; CHECK-NEXT: with constants -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals miscellaneous locals-related -;; CHECK-NEXT: optimizations -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-nonesting miscellaneous locals-related -;; CHECK-NEXT: optimizations (no nesting at -;; CHECK-NEXT: all; preserves flatness) -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-nostructure miscellaneous locals-related -;; CHECK-NEXT: optimizations (no structure) -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-notee miscellaneous locals-related -;; CHECK-NEXT: optimizations (no tees) -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-notee-nostructure miscellaneous locals-related -;; CHECK-NEXT: optimizations (no tees or -;; CHECK-NEXT: structure) -;; CHECK-NEXT: -;; CHECK-NEXT: --souperify emit Souper IR in text form -;; CHECK-NEXT: -;; CHECK-NEXT: --souperify-single-use emit Souper IR in text form -;; CHECK-NEXT: (single-use nodes only) -;; CHECK-NEXT: -;; CHECK-NEXT: --ssa ssa-ify variables so that they -;; CHECK-NEXT: have a single assignment -;; CHECK-NEXT: -;; CHECK-NEXT: --ssa-nomerge ssa-ify variables so that they -;; CHECK-NEXT: have a single assignment, -;; CHECK-NEXT: ignoring merges -;; CHECK-NEXT: -;; CHECK-NEXT: --stack-check enforce limits on llvm's -;; CHECK-NEXT: __stack_pointer global -;; CHECK-NEXT: -;; CHECK-NEXT: --strip deprecated; same as strip-debug -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-debug strip debug info (including the -;; CHECK-NEXT: names section) -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-dwarf strip dwarf debug info -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-producers strip the wasm producers section -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-target-features strip the wasm target features -;; CHECK-NEXT: section -;; CHECK-NEXT: -;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --symbolmap (alias for print-function-map) -;; CHECK-NEXT: -;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with -;; CHECK-NEXT: clamping semantics -;; CHECK-NEXT: -;; CHECK-NEXT: --trap-mode-js replace trapping operations with -;; CHECK-NEXT: js semantics -;; CHECK-NEXT: -;; CHECK-NEXT: --type-refining apply more specific subtypes to -;; CHECK-NEXT: type fields where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --untee removes local.tees, replacing -;; CHECK-NEXT: them with sets and gets -;; CHECK-NEXT: -;; CHECK-NEXT: --vacuum removes obviously unneeded code -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Optimization options: -;; CHECK-NEXT: --------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: -O execute default optimization -;; CHECK-NEXT: passes (equivalent to -Os) -;; CHECK-NEXT: -;; CHECK-NEXT: -O0 execute no optimization passes -;; CHECK-NEXT: -;; CHECK-NEXT: -O1 execute -O1 optimization passes -;; CHECK-NEXT: (quick&useful opts, useful for -;; CHECK-NEXT: iteration builds) -;; CHECK-NEXT: -;; CHECK-NEXT: -O2 execute -O2 optimization passes -;; CHECK-NEXT: (most opts, generally gets most -;; CHECK-NEXT: perf) -;; CHECK-NEXT: -;; CHECK-NEXT: -O3 execute -O3 optimization passes -;; CHECK-NEXT: (spends potentially a lot of -;; CHECK-NEXT: time optimizing) -;; CHECK-NEXT: -;; CHECK-NEXT: -O4 execute -O4 optimization passes -;; CHECK-NEXT: (also flatten the IR, which can -;; CHECK-NEXT: take a lot more time and memory, -;; CHECK-NEXT: but is useful on more nested / -;; CHECK-NEXT: complex / less-optimized input) -;; CHECK-NEXT: -;; CHECK-NEXT: -Os execute default optimization -;; CHECK-NEXT: passes, focusing on code size -;; CHECK-NEXT: -;; CHECK-NEXT: -Oz execute default optimization -;; CHECK-NEXT: passes, super-focusing on code -;; CHECK-NEXT: size -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-level,-ol How much to focus on optimizing -;; CHECK-NEXT: code -;; CHECK-NEXT: -;; CHECK-NEXT: --shrink-level,-s How much to focus on shrinking -;; CHECK-NEXT: code size -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g Emit names section in wasm -;; CHECK-NEXT: binary (or full debuginfo in -;; CHECK-NEXT: wast) -;; CHECK-NEXT: -;; CHECK-NEXT: --always-inline-max-function-size,-aimfs Max size of functions that are -;; CHECK-NEXT: always inlined (default 2, which -;; CHECK-NEXT: is safe for use with -Os builds) -;; CHECK-NEXT: -;; CHECK-NEXT: --flexible-inline-max-function-size,-fimfs Max size of functions that are -;; CHECK-NEXT: inlined when lightweight (no -;; CHECK-NEXT: loops or function calls) when -;; CHECK-NEXT: optimizing aggressively for -;; CHECK-NEXT: speed (-O3). Default: 20 -;; CHECK-NEXT: -;; CHECK-NEXT: --one-caller-inline-max-function-size,-ocimfs Max size of functions that are -;; CHECK-NEXT: inlined when there is only one -;; CHECK-NEXT: caller (default -1, which means -;; CHECK-NEXT: all such functions are inlined) -;; CHECK-NEXT: -;; CHECK-NEXT: --inline-functions-with-loops,-ifwl Allow inlining functions with -;; CHECK-NEXT: loops -;; CHECK-NEXT: -;; CHECK-NEXT: --partial-inlining-ifs,-pii Number of ifs allowed in partial -;; CHECK-NEXT: inlining (zero means partial -;; CHECK-NEXT: inlining is disabled) (default: -;; CHECK-NEXT: 0) -;; CHECK-NEXT: -;; CHECK-NEXT: --ignore-implicit-traps,-iit Optimize under the helpful -;; CHECK-NEXT: assumption that no surprising -;; CHECK-NEXT: traps occur (from load, div/mod, -;; CHECK-NEXT: etc.) -;; CHECK-NEXT: -;; CHECK-NEXT: --traps-never-happen,-tnh Optimize under the helpful -;; CHECK-NEXT: assumption that no trap is -;; CHECK-NEXT: reached at runtime (from load, -;; CHECK-NEXT: div/mod, etc.) -;; CHECK-NEXT: -;; CHECK-NEXT: --low-memory-unused,-lmu Optimize under the helpful -;; CHECK-NEXT: assumption that the low 1K of -;; CHECK-NEXT: memory is not used by the -;; CHECK-NEXT: application -;; CHECK-NEXT: -;; CHECK-NEXT: --fast-math,-ffm Optimize floats without handling -;; CHECK-NEXT: corner cases of NaNs and -;; CHECK-NEXT: rounding -;; CHECK-NEXT: -;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory -;; CHECK-NEXT: will be zero-initialized -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does -;; CHECK-NEXT: nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and -;; CHECK-NEXT: hide trivial warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for -;; CHECK-NEXT: testing purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and -;; CHECK-NEXT: types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function -;; CHECK-NEXT: references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const -;; CHECK-NEXT: expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const -;; CHECK-NEXT: expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes -;; CHECK-NEXT: inputs are correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to -;; CHECK-NEXT: optimization passes being run. -;; CHECK-NEXT: Must be in the form KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to -;; CHECK-NEXT: be parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to -;; CHECK-NEXT: be parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the -;; CHECK-NEXT: default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to -;; CHECK-NEXT: be parsed using the isorecursive -;; CHECK-NEXT: hybrid type system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and -;; CHECK-NEXT: exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to -;; CHECK-NEXT: stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-as.test binaryen-99/test/lit/help/wasm-as.test --- binaryen-108/test/lit/help/wasm-as.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-as.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -;; RUN: wasm-as --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-as INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Assemble a .wat (WebAssembly text format) into a .wasm (WebAssembly binary -;; CHECK-NEXT: format) -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-as options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file (stdout if not specified) -;; CHECK-NEXT: -;; CHECK-NEXT: --validate,-v Control validation of the output module -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g Emit names section and debug info -;; CHECK-NEXT: -;; CHECK-NEXT: --source-map,-sm Emit source map to the specified file -;; CHECK-NEXT: -;; CHECK-NEXT: --source-map-url,-su Use specified string as source map URL -;; CHECK-NEXT: -;; CHECK-NEXT: --symbolmap,-s Emit a symbol map (indexes => names) -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-ctor-eval.test binaryen-99/test/lit/help/wasm-ctor-eval.test --- binaryen-108/test/lit/help/wasm-ctor-eval.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-ctor-eval.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -;; RUN: wasm-ctor-eval --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-ctor-eval INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Execute code at compile time -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-ctor-eval options: -;; CHECK-NEXT: ----------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file (stdout if not specified) -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-text,-S Emit text instead of binary for the -;; CHECK-NEXT: output file -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g Emit names section and debug info -;; CHECK-NEXT: -;; CHECK-NEXT: --ctors,-c Comma-separated list of global -;; CHECK-NEXT: constructor functions to evaluate -;; CHECK-NEXT: -;; CHECK-NEXT: --kept-exports,-ke Comma-separated list of ctors whose -;; CHECK-NEXT: exports we keep around even if we eval -;; CHECK-NEXT: those ctors -;; CHECK-NEXT: -;; CHECK-NEXT: --ignore-external-input,-ipi Assumes no env vars are to be read, stdin -;; CHECK-NEXT: is empty, etc. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-dis.test binaryen-99/test/lit/help/wasm-dis.test --- binaryen-108/test/lit/help/wasm-dis.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-dis.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,127 +0,0 @@ -;; RUN: wasm-dis --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-dis INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Un-assemble a .wasm (WebAssembly binary format) into a .wat (WebAssembly text -;; CHECK-NEXT: format) -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-dis options: -;; CHECK-NEXT: ----------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file (stdout if not specified) -;; CHECK-NEXT: -;; CHECK-NEXT: --source-map,-sm Consume source map from the specified -;; CHECK-NEXT: file to add location information -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-emscripten-finalize.test binaryen-99/test/lit/help/wasm-emscripten-finalize.test --- binaryen-108/test/lit/help/wasm-emscripten-finalize.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-emscripten-finalize.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,177 +0,0 @@ -;; RUN: wasm-emscripten-finalize --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-emscripten-finalize INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Performs Emscripten-specific transforms on .wasm files -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-emscripten-finalize options: -;; CHECK-NEXT: --------------------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g Emit names section in wasm binary (or -;; CHECK-NEXT: full debuginfo in wast) -;; CHECK-NEXT: -;; CHECK-NEXT: --dwarf Update DWARF debug info -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-text,-S Emit text instead of binary for the -;; CHECK-NEXT: output file. In this mode if no output -;; CHECK-NEXT: file is specified, we write to stdout. -;; CHECK-NEXT: -;; CHECK-NEXT: --no-emit-metadata,-n Skip the writing to emscripten metadata -;; CHECK-NEXT: JSON to stdout. -;; CHECK-NEXT: -;; CHECK-NEXT: --global-base The address at which static globals were -;; CHECK-NEXT: placed -;; CHECK-NEXT: -;; CHECK-NEXT: --side-module Input is an emscripten side module -;; CHECK-NEXT: -;; CHECK-NEXT: --input-source-map,-ism Consume source map from the specified -;; CHECK-NEXT: file -;; CHECK-NEXT: -;; CHECK-NEXT: --no-legalize-javascript-ffi,-nj Do not fully legalize (i64->i32, -;; CHECK-NEXT: f32->f64) the imports and exports for -;; CHECK-NEXT: interfacing with JS -;; CHECK-NEXT: -;; CHECK-NEXT: --bigint,-bi Assume JS will use wasm/JS BigInt -;; CHECK-NEXT: integration, so wasm i64s will turn into -;; CHECK-NEXT: JS BigInts, and there is no need for any -;; CHECK-NEXT: legalization at all (not even minimal -;; CHECK-NEXT: legalization of dynCalls) -;; CHECK-NEXT: -;; CHECK-NEXT: --output-source-map,-osm Emit source map to the specified file -;; CHECK-NEXT: -;; CHECK-NEXT: --output-source-map-url,-osu Emit specified string as source map URL -;; CHECK-NEXT: -;; CHECK-NEXT: --separate-data-segments Separate data segments to a file -;; CHECK-NEXT: -;; CHECK-NEXT: --check-stack-overflow Check for stack overflows every time the -;; CHECK-NEXT: stack is extended -;; CHECK-NEXT: -;; CHECK-NEXT: --standalone-wasm Emit a wasm file that does not depend on -;; CHECK-NEXT: JS, as much as possible, using wasi and -;; CHECK-NEXT: other standard conventions etc. where -;; CHECK-NEXT: possible -;; CHECK-NEXT: -;; CHECK-NEXT: --minimize-wasm-changes Modify the wasm as little as possible. -;; CHECK-NEXT: This is useful during development as we -;; CHECK-NEXT: reduce the number of changes to the wasm, -;; CHECK-NEXT: as it lets emscripten control how much -;; CHECK-NEXT: modifications to do. -;; CHECK-NEXT: -;; CHECK-NEXT: --no-dyncalls -;; CHECK-NEXT: -;; CHECK-NEXT: --dyncalls-i64 -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-fuzz-types.test binaryen-99/test/lit/help/wasm-fuzz-types.test --- binaryen-108/test/lit/help/wasm-fuzz-types.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-fuzz-types.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -;; RUN: wasm-fuzz-types --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-fuzz-types -;; CHECK-NEXT: -;; CHECK-NEXT: Fuzz type construction, canonicalization, and operations -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-fuzz-types options: -;; CHECK-NEXT: ------------------------ -;; CHECK-NEXT: -;; CHECK-NEXT: --seed Run a single workload generated by the given seed -;; CHECK-NEXT: -;; CHECK-NEXT: --verbose,-v Print extra information -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Use the nominal type system (default) -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Use the equirecursive type system -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Use the isorecursive hybrid type system -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-metadce.test binaryen-99/test/lit/help/wasm-metadce.test --- binaryen-108/test/lit/help/wasm-metadce.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-metadce.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,175 +0,0 @@ -;; RUN: wasm-metadce --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-metadce INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: This tool performs dead code elimination (DCE) on a larger space that the wasm -;; CHECK-NEXT: module is just a part of. For example, if you have JS and wasm that are -;; CHECK-NEXT: connected, this can DCE the combined graph. By doing so, it is able to eliminate -;; CHECK-NEXT: wasm module exports, which otherwise regular optimizations cannot. -;; CHECK-NEXT: -;; CHECK-NEXT: This tool receives a representation of the reachability graph that the wasm -;; CHECK-NEXT: module resides in, which contains abstract nodes and connections showing what -;; CHECK-NEXT: they reach. Some of those nodes can represent the wasm module's imports and -;; CHECK-NEXT: exports. The tool then completes the graph by adding the internal parts of the -;; CHECK-NEXT: module, and does DCE on the entire thing. -;; CHECK-NEXT: -;; CHECK-NEXT: This tool will output a wasm module with dead code eliminated, and metadata -;; CHECK-NEXT: describing the things in the rest of the graph that can be eliminated as well. -;; CHECK-NEXT: -;; CHECK-NEXT: The graph description file should represent the graph in the following JSON-like -;; CHECK-NEXT: notation (note, this is not true JSON, things like comments, escaping, -;; CHECK-NEXT: single-quotes, etc. are not supported): -;; CHECK-NEXT: -;; CHECK-NEXT: [ -;; CHECK-NEXT: { -;; CHECK-NEXT: "name": "entity1", -;; CHECK-NEXT: "reaches": ["entity2, "entity3"], -;; CHECK-NEXT: "root": true -;; CHECK-NEXT: }, -;; CHECK-NEXT: { -;; CHECK-NEXT: "name": "entity2", -;; CHECK-NEXT: "reaches": ["entity1, "entity4"] -;; CHECK-NEXT: }, -;; CHECK-NEXT: { -;; CHECK-NEXT: "name": "entity3", -;; CHECK-NEXT: "reaches": ["entity1"], -;; CHECK-NEXT: "export": "export1" -;; CHECK-NEXT: }, -;; CHECK-NEXT: { -;; CHECK-NEXT: "name": "entity4", -;; CHECK-NEXT: "import": ["module", "import1"] -;; CHECK-NEXT: }, -;; CHECK-NEXT: ] -;; CHECK-NEXT: -;; CHECK-NEXT: Each entity has a name and an optional list of the other entities it reaches. It -;; CHECK-NEXT: can also be marked as a root, export (with the export string), or import (with -;; CHECK-NEXT: the module and import strings). DCE then computes what is reachable from the -;; CHECK-NEXT: roots. -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-opt options: -;; CHECK-NEXT: ----------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file (stdout if not specified) -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-text,-S Emit text instead of binary for the -;; CHECK-NEXT: output file -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g Emit names section and debug info -;; CHECK-NEXT: -;; CHECK-NEXT: --graph-file,-f Filename of the graph description file -;; CHECK-NEXT: -;; CHECK-NEXT: --dump,-d Dump the combined graph file (useful for -;; CHECK-NEXT: debugging) -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-opt.test binaryen-99/test/lit/help/wasm-opt.test --- binaryen-108/test/lit/help/wasm-opt.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-opt.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,635 +0,0 @@ -;; RUN: wasm-opt --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-opt INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Read, write, and optimize files -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-opt options: -;; CHECK-NEXT: ----------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o Output file (stdout if not -;; CHECK-NEXT: specified) -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-text,-S Emit text instead of binary for -;; CHECK-NEXT: the output file -;; CHECK-NEXT: -;; CHECK-NEXT: --converge,-c Run passes to convergence, -;; CHECK-NEXT: continuing while binary size -;; CHECK-NEXT: decreases -;; CHECK-NEXT: -;; CHECK-NEXT: --fuzz-exec-before,-feh Execute functions before -;; CHECK-NEXT: optimization, helping fuzzing -;; CHECK-NEXT: find bugs -;; CHECK-NEXT: -;; CHECK-NEXT: --fuzz-exec,-fe Execute functions before and -;; CHECK-NEXT: after optimization, helping -;; CHECK-NEXT: fuzzing find bugs -;; CHECK-NEXT: -;; CHECK-NEXT: --extra-fuzz-command,-efc An extra command to run on the -;; CHECK-NEXT: output before and after -;; CHECK-NEXT: optimizing. The output is -;; CHECK-NEXT: compared between the two, and an -;; CHECK-NEXT: error occurs if they are not -;; CHECK-NEXT: equal -;; CHECK-NEXT: -;; CHECK-NEXT: --translate-to-fuzz,-ttf Translate the input into a valid -;; CHECK-NEXT: wasm module *somehow*, useful -;; CHECK-NEXT: for fuzzing -;; CHECK-NEXT: -;; CHECK-NEXT: --initial-fuzz,-if Initial wasm content in -;; CHECK-NEXT: translate-to-fuzz (-ttf) mode -;; CHECK-NEXT: -;; CHECK-NEXT: --fuzz-passes,-fp Pick a random set of passes to -;; CHECK-NEXT: run, useful for fuzzing. this -;; CHECK-NEXT: depends on translate-to-fuzz (it -;; CHECK-NEXT: picks the passes from the input) -;; CHECK-NEXT: -;; CHECK-NEXT: --no-fuzz-memory don't emit memory ops when -;; CHECK-NEXT: fuzzing -;; CHECK-NEXT: -;; CHECK-NEXT: --no-fuzz-oob don't emit out-of-bounds -;; CHECK-NEXT: loads/stores/indirect calls when -;; CHECK-NEXT: fuzzing -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-js-wrapper,-ejw Emit a JavaScript wrapper file -;; CHECK-NEXT: that can run the wasm with some -;; CHECK-NEXT: test values, useful for fuzzing -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-spec-wrapper,-esw Emit a wasm spec interpreter -;; CHECK-NEXT: wrapper file that can run the -;; CHECK-NEXT: wasm with some test values, -;; CHECK-NEXT: useful for fuzzing -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-wasm2c-wrapper,-esw Emit a C wrapper file that can -;; CHECK-NEXT: run the wasm after it is -;; CHECK-NEXT: compiled with wasm2c, useful for -;; CHECK-NEXT: fuzzing -;; CHECK-NEXT: -;; CHECK-NEXT: --input-source-map,-ism Consume source map from the -;; CHECK-NEXT: specified file -;; CHECK-NEXT: -;; CHECK-NEXT: --output-source-map,-osm Emit source map to the specified -;; CHECK-NEXT: file -;; CHECK-NEXT: -;; CHECK-NEXT: --output-source-map-url,-osu Emit specified string as source -;; CHECK-NEXT: map URL -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Optimization passes: -;; CHECK-NEXT: -------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --alignment-lowering lower unaligned loads and stores -;; CHECK-NEXT: to smaller aligned ones -;; CHECK-NEXT: -;; CHECK-NEXT: --asyncify async/await style transform, -;; CHECK-NEXT: allowing pausing and resuming -;; CHECK-NEXT: -;; CHECK-NEXT: --avoid-reinterprets Tries to avoid reinterpret -;; CHECK-NEXT: operations via more loads -;; CHECK-NEXT: -;; CHECK-NEXT: --cfp propagate constant struct field -;; CHECK-NEXT: values -;; CHECK-NEXT: -;; CHECK-NEXT: --coalesce-locals reduce # of locals by coalescing -;; CHECK-NEXT: -;; CHECK-NEXT: --coalesce-locals-learning reduce # of locals by coalescing -;; CHECK-NEXT: and learning -;; CHECK-NEXT: -;; CHECK-NEXT: --code-folding fold code, merging duplicates -;; CHECK-NEXT: -;; CHECK-NEXT: --code-pushing push code forward, potentially -;; CHECK-NEXT: making it not always execute -;; CHECK-NEXT: -;; CHECK-NEXT: --const-hoisting hoist repeated constants to a -;; CHECK-NEXT: local -;; CHECK-NEXT: -;; CHECK-NEXT: --dae removes arguments to calls in an -;; CHECK-NEXT: lto-like manner -;; CHECK-NEXT: -;; CHECK-NEXT: --dae-optimizing removes arguments to calls in an -;; CHECK-NEXT: lto-like manner, and optimizes -;; CHECK-NEXT: where we removed -;; CHECK-NEXT: -;; CHECK-NEXT: --dce removes unreachable code -;; CHECK-NEXT: -;; CHECK-NEXT: --dealign forces all loads and stores to -;; CHECK-NEXT: have alignment 1 -;; CHECK-NEXT: -;; CHECK-NEXT: --denan instrument the wasm to convert -;; CHECK-NEXT: NaNs into 0 at runtime -;; CHECK-NEXT: -;; CHECK-NEXT: --dfo optimizes using the DataFlow SSA -;; CHECK-NEXT: IR -;; CHECK-NEXT: -;; CHECK-NEXT: --directize turns indirect calls into direct -;; CHECK-NEXT: ones -;; CHECK-NEXT: -;; CHECK-NEXT: --duplicate-function-elimination removes duplicate functions -;; CHECK-NEXT: -;; CHECK-NEXT: --duplicate-import-elimination removes duplicate imports -;; CHECK-NEXT: -;; CHECK-NEXT: --dwarfdump dump DWARF debug info sections -;; CHECK-NEXT: from the read binary -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-target-features emit the target features section -;; CHECK-NEXT: in the output -;; CHECK-NEXT: -;; CHECK-NEXT: --extract-function leaves just one function (useful -;; CHECK-NEXT: for debugging) -;; CHECK-NEXT: -;; CHECK-NEXT: --extract-function-index leaves just one function -;; CHECK-NEXT: selected by index -;; CHECK-NEXT: -;; CHECK-NEXT: --flatten flattens out code, removing -;; CHECK-NEXT: nesting -;; CHECK-NEXT: -;; CHECK-NEXT: --fpcast-emu emulates function pointer casts, -;; CHECK-NEXT: allowing incorrect indirect -;; CHECK-NEXT: calls to (sometimes) work -;; CHECK-NEXT: -;; CHECK-NEXT: --func-metrics reports function metrics -;; CHECK-NEXT: -;; CHECK-NEXT: --generate-dyncalls generate dynCall fuctions used -;; CHECK-NEXT: by emscripten ABI -;; CHECK-NEXT: -;; CHECK-NEXT: --generate-i64-dyncalls generate dynCall functions used -;; CHECK-NEXT: by emscripten ABI, but only for -;; CHECK-NEXT: functions with i64 in their -;; CHECK-NEXT: signature (which cannot be -;; CHECK-NEXT: invoked via the wasm table -;; CHECK-NEXT: without JavaScript BigInt -;; CHECK-NEXT: support). -;; CHECK-NEXT: -;; CHECK-NEXT: --generate-stack-ir generate Stack IR -;; CHECK-NEXT: -;; CHECK-NEXT: --global-refining refine the types of globals -;; CHECK-NEXT: -;; CHECK-NEXT: --gto globally optimize GC types -;; CHECK-NEXT: -;; CHECK-NEXT: --heap2local replace GC allocations with -;; CHECK-NEXT: locals -;; CHECK-NEXT: -;; CHECK-NEXT: --i64-to-i32-lowering lower all uses of i64s to use -;; CHECK-NEXT: i32s instead -;; CHECK-NEXT: -;; CHECK-NEXT: --inline-main inline __original_main into main -;; CHECK-NEXT: -;; CHECK-NEXT: --inlining inline functions (you probably -;; CHECK-NEXT: want inlining-optimizing) -;; CHECK-NEXT: -;; CHECK-NEXT: --inlining-optimizing inline functions and optimizes -;; CHECK-NEXT: where we inlined -;; CHECK-NEXT: -;; CHECK-NEXT: --instrument-locals instrument the build with code -;; CHECK-NEXT: to intercept all loads and -;; CHECK-NEXT: stores -;; CHECK-NEXT: -;; CHECK-NEXT: --instrument-memory instrument the build with code -;; CHECK-NEXT: to intercept all loads and -;; CHECK-NEXT: stores -;; CHECK-NEXT: -;; CHECK-NEXT: --intrinsic-lowering lower away binaryen intrinsics -;; CHECK-NEXT: -;; CHECK-NEXT: --legalize-js-interface legalizes i64 types on the -;; CHECK-NEXT: import/export boundary -;; CHECK-NEXT: -;; CHECK-NEXT: --legalize-js-interface-minimally legalizes i64 types on the -;; CHECK-NEXT: import/export boundary in a -;; CHECK-NEXT: minimal manner, only on things -;; CHECK-NEXT: only JS will call -;; CHECK-NEXT: -;; CHECK-NEXT: --licm loop invariant code motion -;; CHECK-NEXT: -;; CHECK-NEXT: --limit-segments attempt to merge segments to fit -;; CHECK-NEXT: within web limits -;; CHECK-NEXT: -;; CHECK-NEXT: --local-cse common subexpression elimination -;; CHECK-NEXT: inside basic blocks -;; CHECK-NEXT: -;; CHECK-NEXT: --local-subtyping apply more specific subtypes to -;; CHECK-NEXT: locals where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --log-execution instrument the build with -;; CHECK-NEXT: logging of where execution goes -;; CHECK-NEXT: -;; CHECK-NEXT: --memory-packing packs memory into separate -;; CHECK-NEXT: segments, skipping zeros -;; CHECK-NEXT: -;; CHECK-NEXT: --memory64-lowering lower loads and stores to a -;; CHECK-NEXT: 64-bit memory to instead use a -;; CHECK-NEXT: 32-bit one -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-blocks merges blocks to their parents -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-locals merges locals when beneficial -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-similar-functions merges similar functions when -;; CHECK-NEXT: benefical -;; CHECK-NEXT: -;; CHECK-NEXT: --metrics reports metrics -;; CHECK-NEXT: -;; CHECK-NEXT: --minify-imports minifies import names (only -;; CHECK-NEXT: those, and not export names), -;; CHECK-NEXT: and emits a mapping to the -;; CHECK-NEXT: minified ones -;; CHECK-NEXT: -;; CHECK-NEXT: --minify-imports-and-exports minifies both import and export -;; CHECK-NEXT: names, and emits a mapping to -;; CHECK-NEXT: the minified ones -;; CHECK-NEXT: -;; CHECK-NEXT: --minify-imports-and-exports-and-modules minifies both import and export -;; CHECK-NEXT: names, and emits a mapping to -;; CHECK-NEXT: the minified ones, and minifies -;; CHECK-NEXT: the modules as well -;; CHECK-NEXT: -;; CHECK-NEXT: --mod-asyncify-always-and-only-unwind apply the assumption that -;; CHECK-NEXT: asyncify imports always unwind, -;; CHECK-NEXT: and we never rewind -;; CHECK-NEXT: -;; CHECK-NEXT: --mod-asyncify-never-unwind apply the assumption that -;; CHECK-NEXT: asyncify never unwinds -;; CHECK-NEXT: -;; CHECK-NEXT: --name-types (re)name all heap types -;; CHECK-NEXT: -;; CHECK-NEXT: --nm name list -;; CHECK-NEXT: -;; CHECK-NEXT: --once-reduction reduces calls to code that only -;; CHECK-NEXT: runs once -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-added-constants optimizes added constants into -;; CHECK-NEXT: load/store offsets -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-added-constants-propagate optimizes added constants into -;; CHECK-NEXT: load/store offsets, propagating -;; CHECK-NEXT: them across locals too -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-for-js early optimize of the -;; CHECK-NEXT: instruction combinations for js -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-instructions optimizes instruction -;; CHECK-NEXT: combinations -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-stack-ir optimize Stack IR -;; CHECK-NEXT: -;; CHECK-NEXT: --pick-load-signs pick load signs based on their -;; CHECK-NEXT: uses -;; CHECK-NEXT: -;; CHECK-NEXT: --poppify Tranform Binaryen IR into Poppy -;; CHECK-NEXT: IR -;; CHECK-NEXT: -;; CHECK-NEXT: --post-emscripten miscellaneous optimizations for -;; CHECK-NEXT: Emscripten-generated code -;; CHECK-NEXT: -;; CHECK-NEXT: --precompute computes compile-time -;; CHECK-NEXT: evaluatable expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --precompute-propagate computes compile-time -;; CHECK-NEXT: evaluatable expressions and -;; CHECK-NEXT: propagates them through locals -;; CHECK-NEXT: -;; CHECK-NEXT: --print print in s-expression format -;; CHECK-NEXT: -;; CHECK-NEXT: --print-call-graph print call graph -;; CHECK-NEXT: -;; CHECK-NEXT: --print-features print options for enabled -;; CHECK-NEXT: features -;; CHECK-NEXT: -;; CHECK-NEXT: --print-full print in full s-expression -;; CHECK-NEXT: format -;; CHECK-NEXT: -;; CHECK-NEXT: --print-function-map print a map of function indexes -;; CHECK-NEXT: to names -;; CHECK-NEXT: -;; CHECK-NEXT: --print-minified print in minified s-expression -;; CHECK-NEXT: format -;; CHECK-NEXT: -;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for -;; CHECK-NEXT: internal debugging) -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-imports removes imports and replaces -;; CHECK-NEXT: them with nops -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-memory removes memory segments -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-non-js-ops removes operations incompatible -;; CHECK-NEXT: with js -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-brs removes breaks from locations -;; CHECK-NEXT: that are not needed -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-module-elements removes unused module elements -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-names removes names from locations -;; CHECK-NEXT: that are never branched to -;; CHECK-NEXT: -;; CHECK-NEXT: --remove-unused-nonfunction-module-elements removes unused module elements -;; CHECK-NEXT: that are not functions -;; CHECK-NEXT: -;; CHECK-NEXT: --reorder-functions sorts functions by access -;; CHECK-NEXT: frequency -;; CHECK-NEXT: -;; CHECK-NEXT: --reorder-locals sorts locals by access frequency -;; CHECK-NEXT: -;; CHECK-NEXT: --rereloop re-optimize control flow using -;; CHECK-NEXT: the relooper algorithm -;; CHECK-NEXT: -;; CHECK-NEXT: --roundtrip write the module to binary, then -;; CHECK-NEXT: read it -;; CHECK-NEXT: -;; CHECK-NEXT: --rse remove redundant local.sets -;; CHECK-NEXT: -;; CHECK-NEXT: --safe-heap instrument loads and stores to -;; CHECK-NEXT: check for invalid behavior -;; CHECK-NEXT: -;; CHECK-NEXT: --set-globals sets specified globals to -;; CHECK-NEXT: specified values -;; CHECK-NEXT: -;; CHECK-NEXT: --signature-pruning remove params from function -;; CHECK-NEXT: signature types where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --signature-refining apply more specific subtypes to -;; CHECK-NEXT: signature types where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-globals miscellaneous globals-related -;; CHECK-NEXT: optimizations -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-globals-optimizing miscellaneous globals-related -;; CHECK-NEXT: optimizations, and optimizes -;; CHECK-NEXT: where we replaced global.gets -;; CHECK-NEXT: with constants -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals miscellaneous locals-related -;; CHECK-NEXT: optimizations -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-nonesting miscellaneous locals-related -;; CHECK-NEXT: optimizations (no nesting at -;; CHECK-NEXT: all; preserves flatness) -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-nostructure miscellaneous locals-related -;; CHECK-NEXT: optimizations (no structure) -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-notee miscellaneous locals-related -;; CHECK-NEXT: optimizations (no tees) -;; CHECK-NEXT: -;; CHECK-NEXT: --simplify-locals-notee-nostructure miscellaneous locals-related -;; CHECK-NEXT: optimizations (no tees or -;; CHECK-NEXT: structure) -;; CHECK-NEXT: -;; CHECK-NEXT: --souperify emit Souper IR in text form -;; CHECK-NEXT: -;; CHECK-NEXT: --souperify-single-use emit Souper IR in text form -;; CHECK-NEXT: (single-use nodes only) -;; CHECK-NEXT: -;; CHECK-NEXT: --ssa ssa-ify variables so that they -;; CHECK-NEXT: have a single assignment -;; CHECK-NEXT: -;; CHECK-NEXT: --ssa-nomerge ssa-ify variables so that they -;; CHECK-NEXT: have a single assignment, -;; CHECK-NEXT: ignoring merges -;; CHECK-NEXT: -;; CHECK-NEXT: --stack-check enforce limits on llvm's -;; CHECK-NEXT: __stack_pointer global -;; CHECK-NEXT: -;; CHECK-NEXT: --strip deprecated; same as strip-debug -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-debug strip debug info (including the -;; CHECK-NEXT: names section) -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-dwarf strip dwarf debug info -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-producers strip the wasm producers section -;; CHECK-NEXT: -;; CHECK-NEXT: --strip-target-features strip the wasm target features -;; CHECK-NEXT: section -;; CHECK-NEXT: -;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --symbolmap (alias for print-function-map) -;; CHECK-NEXT: -;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with -;; CHECK-NEXT: clamping semantics -;; CHECK-NEXT: -;; CHECK-NEXT: --trap-mode-js replace trapping operations with -;; CHECK-NEXT: js semantics -;; CHECK-NEXT: -;; CHECK-NEXT: --type-refining apply more specific subtypes to -;; CHECK-NEXT: type fields where possible -;; CHECK-NEXT: -;; CHECK-NEXT: --untee removes local.tees, replacing -;; CHECK-NEXT: them with sets and gets -;; CHECK-NEXT: -;; CHECK-NEXT: --vacuum removes obviously unneeded code -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Optimization options: -;; CHECK-NEXT: --------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: -O execute default optimization -;; CHECK-NEXT: passes (equivalent to -Os) -;; CHECK-NEXT: -;; CHECK-NEXT: -O0 execute no optimization passes -;; CHECK-NEXT: -;; CHECK-NEXT: -O1 execute -O1 optimization passes -;; CHECK-NEXT: (quick&useful opts, useful for -;; CHECK-NEXT: iteration builds) -;; CHECK-NEXT: -;; CHECK-NEXT: -O2 execute -O2 optimization passes -;; CHECK-NEXT: (most opts, generally gets most -;; CHECK-NEXT: perf) -;; CHECK-NEXT: -;; CHECK-NEXT: -O3 execute -O3 optimization passes -;; CHECK-NEXT: (spends potentially a lot of -;; CHECK-NEXT: time optimizing) -;; CHECK-NEXT: -;; CHECK-NEXT: -O4 execute -O4 optimization passes -;; CHECK-NEXT: (also flatten the IR, which can -;; CHECK-NEXT: take a lot more time and memory, -;; CHECK-NEXT: but is useful on more nested / -;; CHECK-NEXT: complex / less-optimized input) -;; CHECK-NEXT: -;; CHECK-NEXT: -Os execute default optimization -;; CHECK-NEXT: passes, focusing on code size -;; CHECK-NEXT: -;; CHECK-NEXT: -Oz execute default optimization -;; CHECK-NEXT: passes, super-focusing on code -;; CHECK-NEXT: size -;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-level,-ol How much to focus on optimizing -;; CHECK-NEXT: code -;; CHECK-NEXT: -;; CHECK-NEXT: --shrink-level,-s How much to focus on shrinking -;; CHECK-NEXT: code size -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g Emit names section in wasm -;; CHECK-NEXT: binary (or full debuginfo in -;; CHECK-NEXT: wast) -;; CHECK-NEXT: -;; CHECK-NEXT: --always-inline-max-function-size,-aimfs Max size of functions that are -;; CHECK-NEXT: always inlined (default 2, which -;; CHECK-NEXT: is safe for use with -Os builds) -;; CHECK-NEXT: -;; CHECK-NEXT: --flexible-inline-max-function-size,-fimfs Max size of functions that are -;; CHECK-NEXT: inlined when lightweight (no -;; CHECK-NEXT: loops or function calls) when -;; CHECK-NEXT: optimizing aggressively for -;; CHECK-NEXT: speed (-O3). Default: 20 -;; CHECK-NEXT: -;; CHECK-NEXT: --one-caller-inline-max-function-size,-ocimfs Max size of functions that are -;; CHECK-NEXT: inlined when there is only one -;; CHECK-NEXT: caller (default -1, which means -;; CHECK-NEXT: all such functions are inlined) -;; CHECK-NEXT: -;; CHECK-NEXT: --inline-functions-with-loops,-ifwl Allow inlining functions with -;; CHECK-NEXT: loops -;; CHECK-NEXT: -;; CHECK-NEXT: --partial-inlining-ifs,-pii Number of ifs allowed in partial -;; CHECK-NEXT: inlining (zero means partial -;; CHECK-NEXT: inlining is disabled) (default: -;; CHECK-NEXT: 0) -;; CHECK-NEXT: -;; CHECK-NEXT: --ignore-implicit-traps,-iit Optimize under the helpful -;; CHECK-NEXT: assumption that no surprising -;; CHECK-NEXT: traps occur (from load, div/mod, -;; CHECK-NEXT: etc.) -;; CHECK-NEXT: -;; CHECK-NEXT: --traps-never-happen,-tnh Optimize under the helpful -;; CHECK-NEXT: assumption that no trap is -;; CHECK-NEXT: reached at runtime (from load, -;; CHECK-NEXT: div/mod, etc.) -;; CHECK-NEXT: -;; CHECK-NEXT: --low-memory-unused,-lmu Optimize under the helpful -;; CHECK-NEXT: assumption that the low 1K of -;; CHECK-NEXT: memory is not used by the -;; CHECK-NEXT: application -;; CHECK-NEXT: -;; CHECK-NEXT: --fast-math,-ffm Optimize floats without handling -;; CHECK-NEXT: corner cases of NaNs and -;; CHECK-NEXT: rounding -;; CHECK-NEXT: -;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory -;; CHECK-NEXT: will be zero-initialized -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does -;; CHECK-NEXT: nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and -;; CHECK-NEXT: hide trivial warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for -;; CHECK-NEXT: testing purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and -;; CHECK-NEXT: types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function -;; CHECK-NEXT: references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const -;; CHECK-NEXT: expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const -;; CHECK-NEXT: expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes -;; CHECK-NEXT: inputs are correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to -;; CHECK-NEXT: optimization passes being run. -;; CHECK-NEXT: Must be in the form KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to -;; CHECK-NEXT: be parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to -;; CHECK-NEXT: be parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the -;; CHECK-NEXT: default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to -;; CHECK-NEXT: be parsed using the isorecursive -;; CHECK-NEXT: hybrid type system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and -;; CHECK-NEXT: exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to -;; CHECK-NEXT: stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-reduce.test binaryen-99/test/lit/help/wasm-reduce.test --- binaryen-108/test/lit/help/wasm-reduce.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-reduce.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,163 +0,0 @@ -;; RUN: wasm-reduce --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-reduce INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Reduce a wasm file to a smaller one that has the same behavior on a given -;; CHECK-NEXT: command -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-reduce options: -;; CHECK-NEXT: -------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --command,-cmd The command to run on the test, that we -;; CHECK-NEXT: want to reduce while keeping the -;; CHECK-NEXT: command's output identical. We look at -;; CHECK-NEXT: the command's return code and stdout here -;; CHECK-NEXT: (TODO: stderr), and we reduce while -;; CHECK-NEXT: keeping those unchanged. -;; CHECK-NEXT: -;; CHECK-NEXT: --test,-t Test file (this will be written to to -;; CHECK-NEXT: test, the given command should read it -;; CHECK-NEXT: when we call it) -;; CHECK-NEXT: -;; CHECK-NEXT: --working,-w Working file (this will contain the -;; CHECK-NEXT: current good state while doing temporary -;; CHECK-NEXT: computations, and will contain the final -;; CHECK-NEXT: best result at the end) -;; CHECK-NEXT: -;; CHECK-NEXT: --binaries,-b binaryen binaries location (bin/ -;; CHECK-NEXT: directory) -;; CHECK-NEXT: -;; CHECK-NEXT: --text,-S Emit intermediate files as text, instead -;; CHECK-NEXT: of binary (also make sure the test and -;; CHECK-NEXT: working files have a .wat or .wast -;; CHECK-NEXT: suffix) -;; CHECK-NEXT: -;; CHECK-NEXT: --denan Avoid nans when reducing -;; CHECK-NEXT: -;; CHECK-NEXT: --verbose,-v Verbose output mode -;; CHECK-NEXT: -;; CHECK-NEXT: --debugInfo,-g Keep debug info in binaries -;; CHECK-NEXT: -;; CHECK-NEXT: --force,-f Force the reduction attempt, ignoring -;; CHECK-NEXT: problems that imply it is unlikely to -;; CHECK-NEXT: succeed -;; CHECK-NEXT: -;; CHECK-NEXT: --timeout,-to A timeout to apply to each execution of -;; CHECK-NEXT: the command, in seconds (default: 2) -;; CHECK-NEXT: -;; CHECK-NEXT: --extra-flags,-ef Extra commandline flags to pass to -;; CHECK-NEXT: wasm-opt while reducing. (default: -;; CHECK-NEXT: --enable-all) -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-shell.test binaryen-99/test/lit/help/wasm-shell.test --- binaryen-108/test/lit/help/wasm-shell.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-shell.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -;; RUN: wasm-shell --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-shell INFILE -;; CHECK-NEXT: -;; CHECK-NEXT: Execute .wast files -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-shell options: -;; CHECK-NEXT: ------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --entry,-e Call the entry point after parsing the module -;; CHECK-NEXT: -;; CHECK-NEXT: --skip,-s Skip input on certain lines (comma-separated-list) -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/help/wasm-split.test binaryen-99/test/lit/help/wasm-split.test --- binaryen-108/test/lit/help/wasm-split.test 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/help/wasm-split.test 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -;; RUN: wasm-split --help | filecheck %s -;; CHECK: ================================================================================ -;; CHECK-NEXT: wasm-split INFILES -;; CHECK-NEXT: -;; CHECK-NEXT: Split a module into a primary module and a secondary module, or instrument a -;; CHECK-NEXT: module to gather a profile that can inform future splitting, or manage such -;; CHECK-NEXT: profiles. Options that are only accepted in particular modes are marked with the -;; CHECK-NEXT: accepted "[]" in their descriptions. -;; CHECK-NEXT: ================================================================================ -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: wasm-split options: -;; CHECK-NEXT: ------------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --split Split an input module into two output -;; CHECK-NEXT: modules. The default mode. -;; CHECK-NEXT: -;; CHECK-NEXT: --instrument Instrument an input module to allow it to -;; CHECK-NEXT: generate a profile that can be used to -;; CHECK-NEXT: guide splitting. -;; CHECK-NEXT: -;; CHECK-NEXT: --merge-profiles Merge multiple profiles for the same -;; CHECK-NEXT: module into a single profile. -;; CHECK-NEXT: -;; CHECK-NEXT: --profile [split] The profile to use to guide -;; CHECK-NEXT: splitting. -;; CHECK-NEXT: -;; CHECK-NEXT: --keep-funcs [split] Comma-separated list of functions -;; CHECK-NEXT: to keep in the primary module. The rest -;; CHECK-NEXT: will be split out. Cannot be used with -;; CHECK-NEXT: --profile or --split-funcs. You can also -;; CHECK-NEXT: pass a file with one function per line by -;; CHECK-NEXT: passing @filename. -;; CHECK-NEXT: -;; CHECK-NEXT: --split-funcs [split] Comma-separated list of functions -;; CHECK-NEXT: to split out to the secondary module. The -;; CHECK-NEXT: rest will be kept. Cannot be used with -;; CHECK-NEXT: --profile or --keep-funcs. You can also -;; CHECK-NEXT: pass a file with one function per line by -;; CHECK-NEXT: passing @filename. -;; CHECK-NEXT: -;; CHECK-NEXT: --primary-output,-o1 [split] Output file for the primary -;; CHECK-NEXT: module. -;; CHECK-NEXT: -;; CHECK-NEXT: --secondary-output,-o2 [split] Output file for the secondary -;; CHECK-NEXT: module. -;; CHECK-NEXT: -;; CHECK-NEXT: --symbolmap [split] Write a symbol map file for each -;; CHECK-NEXT: of the output modules. -;; CHECK-NEXT: -;; CHECK-NEXT: --placeholdermap [split] Write a file mapping placeholder -;; CHECK-NEXT: indices to the function names. -;; CHECK-NEXT: -;; CHECK-NEXT: --import-namespace [split] The namespace from which to -;; CHECK-NEXT: import objects from the primary module -;; CHECK-NEXT: into the secondary module. -;; CHECK-NEXT: -;; CHECK-NEXT: --placeholder-namespace [split] The namespace from which to -;; CHECK-NEXT: import placeholder functions into the -;; CHECK-NEXT: primary module. -;; CHECK-NEXT: -;; CHECK-NEXT: --asyncify [split] Transform the module to support -;; CHECK-NEXT: unwinding the stack from placeholder -;; CHECK-NEXT: functions and rewinding it once the -;; CHECK-NEXT: secondary module has been loaded. -;; CHECK-NEXT: -;; CHECK-NEXT: --export-prefix [split] An identifying prefix to prepend -;; CHECK-NEXT: to new export names created by module -;; CHECK-NEXT: splitting. -;; CHECK-NEXT: -;; CHECK-NEXT: --profile-export [instrument] The export name of the -;; CHECK-NEXT: function the embedder calls to write the -;; CHECK-NEXT: profile into memory. Defaults to -;; CHECK-NEXT: `__write_profile`. -;; CHECK-NEXT: -;; CHECK-NEXT: --in-memory [instrument] Store profile information in -;; CHECK-NEXT: memory (starting at address 0 and taking -;; CHECK-NEXT: one byte per function) rather than -;; CHECK-NEXT: globals (the default) so that it can be -;; CHECK-NEXT: shared between multiple threads. Users -;; CHECK-NEXT: are responsible for ensuring that the -;; CHECK-NEXT: module does not use the initial memory -;; CHECK-NEXT: region for anything else. -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-module-names [split, instrument] Emit module names, -;; CHECK-NEXT: even if not emitting the rest of the -;; CHECK-NEXT: names section. Can help differentiate the -;; CHECK-NEXT: modules in stack traces. This option will -;; CHECK-NEXT: be removed once simpler ways of naming -;; CHECK-NEXT: modules are widely available. See -;; CHECK-NEXT: https://bugs.chromium.org/p/v8/issues/detail?id=11808. -;; CHECK-NEXT: -;; CHECK-NEXT: --initial-table [split, instrument] A hack to ensure the -;; CHECK-NEXT: split and instrumented modules have the -;; CHECK-NEXT: same table size when using Emscripten's -;; CHECK-NEXT: SPLIT_MODULE mode with dynamic linking. -;; CHECK-NEXT: TODO: Figure out a more elegant solution -;; CHECK-NEXT: for that use case and remove this. -;; CHECK-NEXT: -;; CHECK-NEXT: --emit-text,-S [split, instrument] Emit text instead of -;; CHECK-NEXT: binary for the output file or files. -;; CHECK-NEXT: -;; CHECK-NEXT: --debuginfo,-g [split, instrument] Emit names section in -;; CHECK-NEXT: wasm binary (or full debuginfo in wast) -;; CHECK-NEXT: -;; CHECK-NEXT: --output,-o [instrument, merge-profiles] Output file. -;; CHECK-NEXT: -;; CHECK-NEXT: --verbose,-v Verbose output mode. Prints the functions -;; CHECK-NEXT: that will be kept and split out when -;; CHECK-NEXT: splitting a module. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: Tool options: -;; CHECK-NEXT: ------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features -;; CHECK-NEXT: -;; CHECK-NEXT: --all-features,-all Enable all features -;; CHECK-NEXT: -;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing) -;; CHECK-NEXT: -;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial -;; CHECK-NEXT: warnings. -;; CHECK-NEXT: -;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing -;; CHECK-NEXT: purposes. -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-threads Enable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-threads Disable atomic operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int -;; CHECK-NEXT: operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-simd Enable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-simd Disable SIMD operations and types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-tail-call Enable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-tail-call Disable tail call operations -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-reference-types Enable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-reference-types Disable reference types -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-multivalue Enable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-multivalue Disable multivalue functions -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc Enable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc Disable garbage collection -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-memory64 Enable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-memory64 Disable memory64 -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-typed-function-references Enable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-typed-function-references Disable typed function references -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD -;; CHECK-NEXT: -;; CHECK-NEXT: --enable-extended-const Enable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-extended-const Disable extended const expressions -;; CHECK-NEXT: -;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are -;; CHECK-NEXT: correct -;; CHECK-NEXT: -;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization -;; CHECK-NEXT: passes being run. Must be in the form -;; CHECK-NEXT: KEY@VALUE -;; CHECK-NEXT: -;; CHECK-NEXT: --nominal Force all GC type definitions to be -;; CHECK-NEXT: parsed as nominal. -;; CHECK-NEXT: -;; CHECK-NEXT: --structural Force all GC type definitions to be -;; CHECK-NEXT: parsed as structural (i.e. -;; CHECK-NEXT: equirecursive). This is the default. -;; CHECK-NEXT: -;; CHECK-NEXT: --hybrid Force all GC type definitions to be -;; CHECK-NEXT: parsed using the isorecursive hybrid type -;; CHECK-NEXT: system. -;; CHECK-NEXT: -;; CHECK-NEXT: -;; CHECK-NEXT: General options: -;; CHECK-NEXT: ---------------- -;; CHECK-NEXT: -;; CHECK-NEXT: --version Output version information and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --help,-h Show this help message and exit -;; CHECK-NEXT: -;; CHECK-NEXT: --debug,-d Print debug information to stderr -;; CHECK-NEXT: diff -Nru binaryen-108/test/lit/isorecursive-good.wast binaryen-99/test/lit/isorecursive-good.wast --- binaryen-108/test/lit/isorecursive-good.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/isorecursive-good.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -;; TODO: Autogenerate these checks! The current script cannot handle `rec`. - -;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s --check-prefix HYBRID -;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s --check-prefix HYBRID -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s --check-prefix NOMINAL - -(module - -;; HYBRID: (rec -;; HYBRID-NEXT: (type $super-struct (struct_subtype (field i32) data)) -;; HYBRID-NEXT: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) -;; HYBRID-NEXT: ) - -;; HYBRID: (rec -;; HYBRID-NEXT: (type $super-array (array_subtype (ref $super-struct) data)) -;; HYBRID-NEXT: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) -;; HYBRID-NEXT: ) - -;; NOMINAL-NOT: rec - -;; NOMINAL: (type $super-struct (struct_subtype (field i32) data)) -;; NOMINAL-NEXT: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) - -;; NOMINAL: (type $super-array (array_subtype (ref $super-struct) data)) -;; NOMINAL-NEXT: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - - (rec - (type $super-struct (struct i32)) - (type $sub-struct (struct_subtype i32 i64 $super-struct)) - ) - - (rec - (type $super-array (array (ref $super-struct))) - (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - ) - - (func $make-super-struct (result (ref $super-struct)) - (call $make-sub-struct) - ) - - (func $make-sub-struct (result (ref $sub-struct)) - (unreachable) - ) - - (func $make-super-array (result (ref $super-array)) - (call $make-sub-array) - ) - - (func $make-sub-array (result (ref $sub-array)) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/isorecursive-output-ordering.wast binaryen-99/test/lit/isorecursive-output-ordering.wast --- binaryen-108/test/lit/isorecursive-output-ordering.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/isorecursive-output-ordering.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -;; TODO: Autogenerate these checks! The current script cannot handle `rec`. - -;; RUN: foreach %s %t wasm-opt -all --hybrid -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt -all --hybrid --roundtrip -S -o - | filecheck %s - -(module - ;; Test that we order groups by average uses. - - ;; CHECK: (rec - ;; CHECK-NEXT: (type $unused-6 (struct_subtype data)) - ;; CHECK-NEXT: (type $used-a-bit (struct_subtype data)) - ;; CHECK-NEXT: ) - - ;; CHECK-NEXT: (rec - ;; CHECK-NEXT: (type $unused-1 (struct_subtype data)) - ;; CHECK-NEXT: (type $unused-2 (struct_subtype data)) - ;; CHECK-NEXT: (type $unused-3 (struct_subtype data)) - ;; CHECK-NEXT: (type $unused-4 (struct_subtype data)) - ;; CHECK-NEXT: (type $used-a-lot (struct_subtype data)) - ;; CHECK-NEXT: (type $unused-5 (struct_subtype data)) - ;; CHECK-NEXT: ) - - (rec - (type $unused-1 (struct_subtype data)) - (type $unused-2 (struct_subtype data)) - (type $unused-3 (struct_subtype data)) - (type $unused-4 (struct_subtype data)) - (type $used-a-lot (struct_subtype data)) - (type $unused-5 (struct_subtype data)) - ) - - (rec - (type $unused-6 (struct_subtype data)) - (type $used-a-bit (struct_subtype data)) - ) - - (func $use (param (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot)) (result (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit)) - (unreachable) - ) -) - -(module - ;; Test that we respect dependencies between groups before considering counts. - - ;; CHECK: (rec - ;; CHECK-NEXT: (type $leaf (struct_subtype data)) - ;; CHECK-NEXT: (type $unused (struct_subtype data)) - ;; CHECK-NEXT: ) - - ;; CHECK-NEXT: (rec - ;; CHECK-NEXT: (type $shrub (struct_subtype $leaf)) - ;; CHECK-NEXT: (type $used-a-ton (struct_subtype data)) - ;; CHECK-NEXT: ) - - ;; CHECK-NEXT: (rec - ;; CHECK-NEXT: (type $twig (struct_subtype data)) - ;; CHECK-NEXT: (type $used-a-bit (struct_subtype (field (ref $leaf)) data)) - ;; CHECK-NEXT: ) - - ;; CHECK-NEXT: (rec - ;; CHECK-NEXT: (type $root (struct_subtype data)) - ;; CHECK-NEXT: (type $used-a-lot (struct_subtype $twig)) - ;; CHECK-NEXT: ) - - (rec - (type $leaf (struct_subtype data)) - (type $unused (struct_subtype data)) - ) - - (rec - (type $twig (struct_subtype data)) - (type $used-a-bit (struct_subtype (ref $leaf) data)) - ) - - (rec - (type $shrub (struct_subtype $leaf)) - (type $used-a-ton (struct_subtype data)) - ) - - (rec - (type $root (struct_subtype data)) - (type $used-a-lot (struct_subtype $twig)) - ) - - (func $use (param (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot) (ref $used-a-lot)) (result (ref $used-a-bit) (ref $used-a-bit) (ref $used-a-bit)) - (local (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton) (ref null $used-a-ton)) - (unreachable) - ) -) - -(module - ;; Test that basic heap type children do not trigger assertions. - - (rec - (type $contains-basic (struct_subtype (ref any) data)) - ) - - (func $use (param (ref $contains-basic)) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/isorecursive-singleton-group.wast binaryen-99/test/lit/isorecursive-singleton-group.wast --- binaryen-108/test/lit/isorecursive-singleton-group.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/isorecursive-singleton-group.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -;; TODO: Autogenerate these checks! The current script cannot handle `rec`. - -;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s - -;; Check that everything works correctly when a recursion group has only a -;; single member. The rec group is implicit, so does not need to be printed. - -(module - -;; CHECK-NOT: rec -;; CHECK: (type $singleton (struct_subtype data)) - - (rec - (type $singleton (struct_subtype data)) - ) - - ;; Use the type so it appears in the output. - (global $g (ref null $singleton) (ref.null $singleton)) -) diff -Nru binaryen-108/test/lit/isorecursive-whole-group.wast binaryen-99/test/lit/isorecursive-whole-group.wast --- binaryen-108/test/lit/isorecursive-whole-group.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/isorecursive-whole-group.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -;; TODO: Autogenerate these checks! The current script cannot handle `rec`. - -;; RUN: wasm-opt %s -all --hybrid -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --hybrid --roundtrip -S -o - | filecheck %s - -;; Check that unused types are still included in the output when they are part -;; of a recursion group with used types. - -(module - -;; CHECK: (rec -;; CHECK-NEXT: (type $used (struct_subtype data)) -;; CHECK-NEXT: (type $unused (struct_subtype data)) -;; CHECK-NEXT: ) - - (rec - (type $used (struct_subtype data)) - (type $unused (struct_subtype data)) - ) - - (global $g (ref null $used) (ref.null $used)) -) diff -Nru binaryen-108/test/lit/lit.cfg.py binaryen-99/test/lit/lit.cfg.py --- binaryen-108/test/lit/lit.cfg.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/lit.cfg.py 2021-01-07 20:01:06.000000000 +0000 @@ -1,27 +1,21 @@ -import os import lit.formats config.name = "Binaryen lit tests" -config.test_format = lit.formats.ShTest() +config.test_format = lit.formats.ShTest(True) -config.suffixes = ['.wat', '.wast', '.test'] +config.suffixes = ['.wat', '.wast'] config.test_source_root = os.path.dirname(__file__) config.test_exec_root = os.path.join(config.binaryen_build_root, 'test') -config.environment = dict(os.environ) - # Replace all Binaryen tools with their absolute paths bin_dir = os.path.join(config.binaryen_build_root, 'bin') -assert(os.path.isdir(bin_dir)) - for tool_file in os.listdir(bin_dir): tool_path = config.binaryen_build_root + '/bin/' + tool_file tool = tool_file[:-4] if tool_file.endswith('.exe') else tool_file config.substitutions.append((tool, tool_path)) -# Also make the `not` and `foreach` commands available -for tool in ('not', 'foreach'): - tool_file = config.binaryen_src_root + '/scripts/' + tool + '.py' - python = sys.executable.replace('\\', '/') - config.substitutions.append((tool, python + ' ' + tool_file)) +# Also make the `not` command available +not_file = config.binaryen_src_root + '/scripts/not.py' +python = sys.executable.replace('\\', '/') +config.substitutions.append(('not', python + ' ' + not_file)) diff -Nru binaryen-108/test/lit/lub-bug-3843.wast binaryen-99/test/lit/lub-bug-3843.wast --- binaryen-108/test/lit/lub-bug-3843.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/lub-bug-3843.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --precompute -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --precompute --nominal -S -o - | filecheck %s --check-prefix NOMNL - -;; Regression test for a bug (#3843) in which the LUB calculation done during -;; the refinalization of the select incorrectly produced a new type rather than -;; returning (ref null $A). - -(module - ;; CHECK: (type $A (struct (field (ref null $C)))) - ;; NOMNL: (type $A (struct_subtype (field (ref null $C)) data)) - (type $A (struct (field (ref null $C)))) - - ;; CHECK: (type $B (struct (field (ref null $D)))) - ;; NOMNL: (type $B (struct_subtype (field (ref null $D)) $A)) - (type $B (struct_subtype (field (ref null $D)) $A)) - - ;; CHECK: (type $D (struct (field (mut (ref $A))) (field (mut (ref $A))))) - ;; NOMNL: (type $C (struct_subtype (field (mut (ref $A))) data)) - - ;; NOMNL: (type $D (struct_subtype (field (mut (ref $A))) (field (mut (ref $A))) $C)) - (type $D (struct_subtype (field (mut (ref $A))) (field (mut (ref $A))) $C)) - - ;; CHECK: (type $C (struct (field (mut (ref $A))))) - (type $C (struct (field (mut (ref $A))))) - - - ;; CHECK: (func $foo (param $a (ref null $A)) (result (ref null $A)) - ;; CHECK-NEXT: (select (result (ref null $A)) - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $ref?|$A|_=>_ref?|$A|) (param $a (ref null $A)) (result (ref null $A)) - ;; NOMNL-NEXT: (select (result (ref null $A)) - ;; NOMNL-NEXT: (local.get $a) - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $foo (param $a (ref null $A)) (result (ref null $A)) - ;; the select should have type $A - (select (result (ref null $A)) - ;; one arm has type $A - (local.get $a) - ;; one arm has type $B (a subtype of $A) - (ref.null $B) - (i32.const 0) - ) - ) -) diff -Nru binaryen-108/test/lit/memory64-limits.wast binaryen-99/test/lit/memory64-limits.wast --- binaryen-108/test/lit/memory64-limits.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/memory64-limits.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s - -(module - (memory $0 i64 1 4294967296) -) - -;; CHECK: (module -;; CHECK-NEXT: (memory $0 i64 1 4294967296) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/nominal-bad.wast binaryen-99/test/lit/nominal-bad.wast --- binaryen-108/test/lit/nominal-bad.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/nominal-bad.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -;; RUN: not wasm-opt %s -all --nominal -S -o - 2>&1 | filecheck %s - -;; CHECK: [wasm-validator error in function make-super-struct] function body type must match -;; CHECK: [wasm-validator error in function make-super-array] function body type must match - -(module - - (type $sub-struct (struct i32 i64)) - (type $super-struct (struct i32)) - - (type $sub-array (array (ref $sub-struct))) - (type $super-array (array (ref $super-struct))) - - (func $make-sub-struct (result (ref $sub-struct)) - (unreachable) - ) - - (func $make-super-struct (result (ref $super-struct)) - (call $make-sub-struct) - ) - - (func $make-sub-array (result (ref $sub-array)) - (unreachable) - ) - - (func $make-super-array (result (ref $super-array)) - (call $make-sub-array) - ) -) diff -Nru binaryen-108/test/lit/nominal-chain.wast binaryen-99/test/lit/nominal-chain.wast --- binaryen-108/test/lit/nominal-chain.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/nominal-chain.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s - -;; Check that intermediate types in subtype chains are also included in the -;; output module, even if there are no other references to those intermediate -;; types. - -(module - ;; CHECK: (type $root (struct_subtype data)) - - ;; CHECK: (type $trunk (struct_subtype (field i32) $root)) - - ;; CHECK: (type $branch (struct_subtype (field i32) (field i64) $trunk)) - - ;; CHECK: (type $twig (struct_subtype (field i32) (field i64) (field f32) $branch)) - - ;; CHECK: (type $leaf (struct_subtype (field i32) (field i64) (field f32) (field f64) $twig)) - (type $leaf (struct_subtype i32 i64 f32 f64 $twig)) - - (type $twig (struct_subtype i32 i64 f32 $branch)) - - (type $branch (struct_subtype i32 i64 $trunk)) - - (type $trunk (struct_subtype i32 $root)) - - (type $root (struct)) - - ;; CHECK: (func $make-root (type $none_=>_ref?|$root|) (result (ref null $root)) - ;; CHECK-NEXT: (ref.null $leaf) - ;; CHECK-NEXT: ) - (func $make-root (result (ref null $root)) - (ref.null $leaf) - ) -) diff -Nru binaryen-108/test/lit/nominal-func.wast binaryen-99/test/lit/nominal-func.wast --- binaryen-108/test/lit/nominal-func.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/nominal-func.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s - -(module - ;; This will be the "canonical" function type rather than $foo_t - (type $bad_t (func)) - - ;; CHECK: (type $foo_t (func_subtype func)) - (type $foo_t (func)) - - ;; CHECK: (func $foo (type $foo_t) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (type $foo_t) - (unreachable) - ) - - ;; $foo needs to be assigned type foo_t rather than bad_t for this to validate. - ;; CHECK: (func $make-ref (type $none_=>_ref|$foo_t|) (result (ref $foo_t)) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - (func $make-ref (result (ref $foo_t)) - (ref.func $foo) - ) -) diff -Nru binaryen-108/test/lit/nominal-good.wast binaryen-99/test/lit/nominal-good.wast --- binaryen-108/test/lit/nominal-good.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/nominal-good.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s --check-prefix NOMINAL -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s --check-prefix NOMINAL -;; RUN: wasm-opt %s -all -S -o - | filecheck %s --check-prefix EQUIREC -;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s --check-prefix EQUIREC -;; RUN: wasm-opt %s -all --structural -S -o - | filecheck %s --check-prefix EQUIREC -;; RUN: wasm-opt %s -all --structural --roundtrip -S -o - | filecheck %s --check-prefix EQUIREC - -(module - - ;; NOMINAL: (type $super-struct (struct_subtype (field i32) data)) - ;; EQUIREC: (type $super-struct (struct (field i32))) - (type $super-struct (struct i32)) - - ;; NOMINAL: (type $sub-struct (struct_subtype (field i32) (field i64) $super-struct)) - ;; EQUIREC: (type $sub-struct (struct (field i32) (field i64))) - (type $sub-struct (struct_subtype i32 i64 $super-struct)) - - ;; NOMINAL: (type $super-array (array_subtype (ref $super-struct) data)) - ;; EQUIREC: (type $super-array (array (ref $super-struct))) - (type $super-array (array (ref $super-struct))) - - ;; NOMINAL: (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - ;; EQUIREC: (type $sub-array (array (ref $sub-struct))) - (type $sub-array (array_subtype (ref $sub-struct) $super-array)) - - ;; TODO: signature types as well, once functions store their HeapTypes. - - ;; NOMINAL: (func $make-super-struct (type $none_=>_ref|$super-struct|) (result (ref $super-struct)) - ;; NOMINAL-NEXT: (call $make-sub-struct) - ;; NOMINAL-NEXT: ) - ;; EQUIREC: (func $make-super-struct (result (ref $super-struct)) - ;; EQUIREC-NEXT: (call $make-sub-struct) - ;; EQUIREC-NEXT: ) - (func $make-super-struct (result (ref $super-struct)) - (call $make-sub-struct) - ) - - ;; NOMINAL: (func $make-sub-struct (type $none_=>_ref|$sub-struct|) (result (ref $sub-struct)) - ;; NOMINAL-NEXT: (unreachable) - ;; NOMINAL-NEXT: ) - ;; EQUIREC: (func $make-sub-struct (result (ref $sub-struct)) - ;; EQUIREC-NEXT: (unreachable) - ;; EQUIREC-NEXT: ) - (func $make-sub-struct (result (ref $sub-struct)) - (unreachable) - ) - - ;; NOMINAL: (func $make-super-array (type $none_=>_ref|$super-array|) (result (ref $super-array)) - ;; NOMINAL-NEXT: (call $make-sub-array) - ;; NOMINAL-NEXT: ) - ;; EQUIREC: (func $make-super-array (result (ref $super-array)) - ;; EQUIREC-NEXT: (call $make-sub-array) - ;; EQUIREC-NEXT: ) - (func $make-super-array (result (ref $super-array)) - (call $make-sub-array) - ) - - ;; NOMINAL: (func $make-sub-array (type $none_=>_ref|$sub-array|) (result (ref $sub-array)) - ;; NOMINAL-NEXT: (unreachable) - ;; NOMINAL-NEXT: ) - ;; EQUIREC: (func $make-sub-array (result (ref $sub-array)) - ;; EQUIREC-NEXT: (unreachable) - ;; EQUIREC-NEXT: ) - (func $make-sub-array (result (ref $sub-array)) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/nominal-named-field.wast binaryen-99/test/lit/nominal-named-field.wast --- binaryen-108/test/lit/nominal-named-field.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/nominal-named-field.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; Regression test for a bug in which field names were not printed in nominal mode. - -;; RUN: wasm-opt %s -all --nominal -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --nominal --roundtrip -S -o - | filecheck %s - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) (field f32) (field $named f64) data)) - (type $struct (struct - (field (mut i32)) - (field f32) - (field $named f64) - )) - - ;; CHECK: (func $foo (type $ref|$struct|_=>_none) (param $0 (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct $named - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (param (ref $struct)) - (drop - (struct.get $struct $named - (local.get 0) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/nominal-to-isorecursive.wast binaryen-99/test/lit/nominal-to-isorecursive.wast --- binaryen-108/test/lit/nominal-to-isorecursive.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/nominal-to-isorecursive.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -;; TODO: Autogenerate these checks! The current script cannot handle `rec`. - -;; RUN: wasm-as %s -all --nominal -g -o %t.wasm -;; RUN: wasm-dis %t.wasm -all --hybrid -o - | filecheck %s - -;; Check that the nominal binary format is parseable as isorecursive with a -;; single recursion group. - -;; CHECK: (module -;; CHECK-NEXT: (rec -;; CHECK-NEXT: (type $make-super-t (func_subtype (result (ref $super)) func)) -;; CHECK-NEXT: (type $make-sub-t (func_subtype (result (ref $sub)) func)) -;; CHECK-NEXT: (type $super (struct_subtype (field i32) data)) -;; CHECK-NEXT: (type $sub (struct_subtype (field i32) $super)) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (func $make-super (type $make-super-t) (result (ref $super)) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (func $make-sub (type $make-sub-t) (result (ref $sub)) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - (type $super (struct i32)) - (type $sub (struct_subtype i32 $super)) - (type $make-super-t (func (result (ref $super)))) - (type $make-sub-t (func (result (ref $sub)))) - - (func $make-super (type $make-super-t) - (unreachable) - ) - - (func $make-sub (type $make-sub-t) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/parse-bad-nominal-types.wast binaryen-99/test/lit/parse-bad-nominal-types.wast --- binaryen-108/test/lit/parse-bad-nominal-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/parse-bad-nominal-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -;; Test that incorrect nominal types result in the expected parse errors - -;; RUN: foreach %s %t not wasm-opt -all 2>&1 | filecheck %s - -;; CHECK: [parse exception: unknown supertype (at 2:35)] -(module - (type $bad-func (func) (extends $bad)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:39)] -(module - (type $bad-struct (struct) (extends $bad)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:41)] -(module - (type $bad-array (array i32) (extends $bad)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:33)] -(module - (type $bad-func (func_subtype $bad)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:37)] -(module - (type $bad-struct (struct_subtype $bad)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:39)] -(module - (type $bad-array (array_subtype i32 $bad)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:32)] -(module - (type $bad-func (func_subtype any)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:36)] -(module - (type $bad-struct (struct_subtype any)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:38)] -(module - (type $bad-array (array_subtype i32 any)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:32)] -(module - (type $bad-func (func_subtype data)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:36)] -(module - (type $bad-struct (struct_subtype func)) -) - -;; CHECK: [parse exception: unknown supertype (at 2:38)] -(module - (type $bad-array (array_subtype i32 func)) -) diff -Nru binaryen-108/test/lit/parse-bad-supertype.wast binaryen-99/test/lit/parse-bad-supertype.wast --- binaryen-108/test/lit/parse-bad-supertype.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/parse-bad-supertype.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -;; Test that an invalid supertype results in a useful error message - -;; RUN: not wasm-opt %s -all --nominal 2>&1 | filecheck %s - -;; CHECK: Fatal: Invalid type: Heap type has an invalid supertype at type $sub -(module - (type $super (struct_subtype i32 data)) - (type $sub (struct_subtype i64 $super)) -) \ No newline at end of file diff -Nru binaryen-108/test/lit/parse-bad-tuple-extract-index.wast binaryen-99/test/lit/parse-bad-tuple-extract-index.wast --- binaryen-108/test/lit/parse-bad-tuple-extract-index.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/parse-bad-tuple-extract-index.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -;; Test that out-of-bounds tuple.extract indices produce parse errors. - -;; RUN: not wasm-opt %s 2>&1 | filecheck %s - -;; CHECK: [parse exception: Bad index on tuple.extract (at 9:17)] - -(module - (func - (tuple.extract 2 - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/parse-nominal-types-extends.wast binaryen-99/test/lit/parse-nominal-types-extends.wast --- binaryen-108/test/lit/parse-nominal-types-extends.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/parse-nominal-types-extends.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; Test that new-style nominal types are parsed correctly. -;; TODO: Remove --nominal below once nominal types are parsed as nominal by default. - -;; RUN: foreach %s %t wasm-opt --nominal -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --nominal -all --roundtrip -S -o - | filecheck %s - -;; void function type -(module - ;; CHECK: (type $super (func_subtype func)) - - ;; CHECK: (type $sub (func_subtype $super)) - (type $sub (func) (extends $super)) - - (type $super (func)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; function type with params and results -(module - ;; CHECK: (type $super (func_subtype (param i32) (result i32) func)) - - ;; CHECK: (type $sub (func_subtype (param i32) (result i32) $super)) - (type $sub (func (param i32) (result i32)) (extends $super)) - - (type $super (func (param i32) (result i32))) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; empty struct type -(module - ;; CHECK: (type $super (struct_subtype data)) - - ;; CHECK: (type $sub (struct_subtype $super)) - (type $sub (struct) (extends $super)) - - (type $super (struct)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; struct type with fields -(module - ;; CHECK: (type $super (struct_subtype (field i32) (field i64) data)) - - ;; CHECK: (type $sub (struct_subtype (field i32) (field i64) $super)) - (type $sub (struct i32 (field i64)) (extends $super)) - - (type $super (struct (field i32) i64)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; array type -(module - ;; CHECK: (type $super (array_subtype i8 data)) - - ;; CHECK: (type $sub (array_subtype i8 $super)) - (type $sub (array i8) (extends $super)) - - (type $super (array i8)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) diff -Nru binaryen-108/test/lit/parse-nominal-types.wast binaryen-99/test/lit/parse-nominal-types.wast --- binaryen-108/test/lit/parse-nominal-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/parse-nominal-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; Test that new-style nominal types are parsed correctly. -;; TODO: Remove --nominal below once nominal types are parsed as nominal by default. - -;; RUN: foreach %s %t wasm-opt --nominal -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --nominal -all --roundtrip -S -o - | filecheck %s - -;; void function type -(module - ;; CHECK: (type $super (func_subtype func)) - - ;; CHECK: (type $sub (func_subtype $super)) - (type $sub (func_subtype $super)) - - (type $super (func_subtype func)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; function type with params and results -(module - ;; CHECK: (type $super (func_subtype (param i32) (result i32) func)) - - ;; CHECK: (type $sub (func_subtype (param i32) (result i32) $super)) - (type $sub (func_subtype (param i32) (result i32) $super)) - - (type $super (func_subtype (param i32) (result i32) func)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; empty struct type -(module - ;; CHECK: (type $super (struct_subtype data)) - - ;; CHECK: (type $sub (struct_subtype $super)) - (type $sub (struct_subtype $super)) - - (type $super (struct_subtype data)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; struct type with fields -(module - ;; CHECK: (type $super (struct_subtype (field i32) (field i64) data)) - - ;; CHECK: (type $sub (struct_subtype (field i32) (field i64) $super)) - (type $sub (struct_subtype i32 (field i64) $super)) - - (type $super (struct_subtype (field i32) i64 data)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) - -;; array type -(module - ;; CHECK: (type $super (array_subtype i8 data)) - - ;; CHECK: (type $sub (array_subtype i8 $super)) - (type $sub (array_subtype i8 $super)) - - (type $super (array_subtype i8 data)) - - ;; CHECK: (global $g (ref null $super) (ref.null $sub)) - (global $g (ref null $super) (ref.null $sub)) -) diff -Nru binaryen-108/test/lit/passes/alignment-lowering64.wast binaryen-99/test/lit/passes/alignment-lowering64.wast --- binaryen-108/test/lit/passes/alignment-lowering64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/alignment-lowering64.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,2055 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --alignment-lowering --enable-memory64 -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 i64 1 1) - (memory $0 i64 1 1) - ;; CHECK: (func $func_4 - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=101 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=102 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=103 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u offset=100 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=102 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=101 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=102 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=103 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=100 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=102 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_4 - (drop (i32.load (i64.const 4))) - (drop (i32.load align=1 (i64.const 4))) - (drop (i32.load align=2 (i64.const 4))) - (drop (i32.load align=4 (i64.const 4))) - (drop (i32.load offset=100 (i64.const 4))) - (drop (i32.load offset=100 align=1 (i64.const 4))) - (drop (i32.load offset=100 align=2 (i64.const 4))) - (drop (i32.load offset=100 align=4 (i64.const 4))) - (drop (i32.load offset=100 align=1 (unreachable))) - (i32.store (i64.const 4) (i32.const 8)) - (i32.store align=1 (i64.const 4) (i32.const 8)) - (i32.store align=2 (i64.const 4) (i32.const 8)) - (i32.store align=4 (i64.const 4) (i32.const 8)) - (i32.store offset=100 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=1 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=2 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=4 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store offset=100 align=1 (i64.const 4) (unreachable)) - ) - ;; CHECK: (func $func_2 - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=101 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=101 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_2 - (drop (i32.load16_u (i64.const 4))) - (drop (i32.load16_u align=1 (i64.const 4))) - (drop (i32.load16_u align=2 (i64.const 4))) - (drop (i32.load16_u offset=100 (i64.const 4))) - (drop (i32.load16_u offset=100 align=1 (i64.const 4))) - (drop (i32.load16_u offset=100 align=2 (i64.const 4))) - (drop (i32.load16_u offset=100 align=1 (unreachable))) - (i32.store16 (i64.const 4) (i32.const 8)) - (i32.store16 align=1 (i64.const 4) (i32.const 8)) - (i32.store16 align=2 (i64.const 4) (i32.const 8)) - (i32.store16 offset=100 (i64.const 4) (i32.const 8)) - (i32.store16 offset=100 align=1 (i64.const 4) (i32.const 8)) - (i32.store16 offset=100 align=2 (i64.const 4) (i32.const 8)) - (i32.store16 offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store16 offset=100 align=1 (i64.const 4) (unreachable)) - ) - ;; CHECK: (func $func_1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_1 - (drop (i32.load8_u (i64.const 4))) - (drop (i32.load8_u align=1 (i64.const 4))) - (drop (i32.load8_u offset=100 (i64.const 4))) - (drop (i32.load8_u offset=100 align=1 (i64.const 4))) - (drop (i32.load8_u offset=100 align=1 (unreachable))) - (i32.store8 (i64.const 4) (i32.const 8)) - (i32.store8 align=1 (i64.const 4) (i32.const 8)) - (i32.store8 offset=100 (i64.const 4) (i32.const 8)) - (i32.store8 offset=100 align=1 (i64.const 4) (i32.const 8)) - (i32.store8 offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store8 offset=100 align=1 (i64.const 4) (unreachable)) - ) - ;; CHECK: (func $func_signed - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=101 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s offset=100 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_signed - (drop (i32.load16_s (i64.const 4))) - (drop (i32.load16_s align=1 (i64.const 4))) - (drop (i32.load16_s align=2 (i64.const 4))) - (drop (i32.load16_s offset=100 (i64.const 4))) - (drop (i32.load16_s offset=100 align=1 (i64.const 4))) - (drop (i32.load16_s offset=100 align=2 (i64.const 4))) - (drop (i32.load16_s offset=100 align=1 (unreachable))) - ) - ;; CHECK: (func $i64-load - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i64) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i64) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=9 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=10 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i64.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i64.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $i64-load - (drop (i64.load align=1 (i64.const 12))) - (drop (i64.load align=2 (i64.const 16))) - (drop (i64.load align=4 (i64.const 20))) - (drop (i64.load align=1 offset=3 (i64.const 20))) - (drop (i64.load16_s align=1 (i64.const 28))) - (drop (i64.load32_s align=1 (i64.const 32))) - (drop (i64.load16_u align=1 (i64.const 40))) - (drop (i64.load32_u align=1 (i64.const 44))) - ) - ;; CHECK: (func $f32-load - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f32-load - (drop (f32.load align=1 (i64.const 12))) - (drop (f32.load align=2 (i64.const 16))) - (drop (f32.load align=1 offset=3 (i64.const 20))) - ) - ;; CHECK: (func $f64-load - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i64) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=9 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=10 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f64-load - (drop (f64.load align=1 (i64.const 12))) - (drop (f64.load align=2 (i64.const 16))) - (drop (f64.load align=4 (i64.const 20))) - (drop (f64.load align=1 offset=3 (i64.const 20))) - ) - ;; CHECK: (func $i64-store - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i64) - ;; CHECK-NEXT: (local $15 i64) - ;; CHECK-NEXT: (local $16 i64) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i64) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i64) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i64) - ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=6 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i64.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.const 400) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=8 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=9 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=10 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $21 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 600) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $22 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $23 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 700) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $i64-store - (i64.store align=1 (i64.const 12) (i64.const 100)) - (i64.store align=2 (i64.const 16) (i64.const 200)) - (i64.store align=4 (i64.const 20) (i64.const 300)) - (i64.store align=1 offset=3 (i64.const 24) (i64.const 400)) - (i64.store16 align=1 (i64.const 20) (i64.const 600)) - (i64.store32 align=1 (i64.const 20) (i64.const 700)) - ) - ;; CHECK: (func $f32-store - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i64.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 400) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f32-store - (f32.store align=1 (i64.const 12) (f32.const 100)) - (f32.store align=2 (i64.const 16) (f32.const 200)) - (f32.store align=1 offset=3 (i64.const 24) (f32.const 400)) - ) - ;; CHECK: (func $f64-store - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i64) - ;; CHECK-NEXT: (local $15 i64) - ;; CHECK-NEXT: (local $16 i64) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i64) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=6 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i64.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 400) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=8 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=9 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=10 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f64-store - (f64.store align=1 (i64.const 12) (f64.const 100)) - (f64.store align=2 (i64.const 16) (f64.const 200)) - (f64.store align=4 (i64.const 20) (f64.const 300)) - (f64.store align=1 offset=3 (i64.const 24) (f64.const 400)) - ) -) diff -Nru binaryen-108/test/lit/passes/alignment-lowering.wast binaryen-99/test/lit/passes/alignment-lowering.wast --- binaryen-108/test/lit/passes/alignment-lowering.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/alignment-lowering.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,2055 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --alignment-lowering -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - ;; CHECK: (func $func_4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=101 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=102 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=103 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u offset=100 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=102 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=101 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=102 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=103 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=100 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=102 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_4 - (drop (i32.load (i32.const 4))) - (drop (i32.load align=1 (i32.const 4))) - (drop (i32.load align=2 (i32.const 4))) - (drop (i32.load align=4 (i32.const 4))) - (drop (i32.load offset=100 (i32.const 4))) - (drop (i32.load offset=100 align=1 (i32.const 4))) - (drop (i32.load offset=100 align=2 (i32.const 4))) - (drop (i32.load offset=100 align=4 (i32.const 4))) - (drop (i32.load offset=100 align=1 (unreachable))) - (i32.store (i32.const 4) (i32.const 8)) - (i32.store align=1 (i32.const 4) (i32.const 8)) - (i32.store align=2 (i32.const 4) (i32.const 8)) - (i32.store align=4 (i32.const 4) (i32.const 8)) - (i32.store offset=100 (i32.const 4) (i32.const 8)) - (i32.store offset=100 align=1 (i32.const 4) (i32.const 8)) - (i32.store offset=100 align=2 (i32.const 4) (i32.const 8)) - (i32.store offset=100 align=4 (i32.const 4) (i32.const 8)) - (i32.store offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store offset=100 align=1 (i32.const 4) (unreachable)) - ) - ;; CHECK: (func $func_2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=101 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_u offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=101 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_2 - (drop (i32.load16_u (i32.const 4))) - (drop (i32.load16_u align=1 (i32.const 4))) - (drop (i32.load16_u align=2 (i32.const 4))) - (drop (i32.load16_u offset=100 (i32.const 4))) - (drop (i32.load16_u offset=100 align=1 (i32.const 4))) - (drop (i32.load16_u offset=100 align=2 (i32.const 4))) - (drop (i32.load16_u offset=100 align=1 (unreachable))) - (i32.store16 (i32.const 4) (i32.const 8)) - (i32.store16 align=1 (i32.const 4) (i32.const 8)) - (i32.store16 align=2 (i32.const 4) (i32.const 8)) - (i32.store16 offset=100 (i32.const 4) (i32.const 8)) - (i32.store16 offset=100 align=1 (i32.const 4) (i32.const 8)) - (i32.store16 offset=100 align=2 (i32.const 4) (i32.const 8)) - (i32.store16 offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store16 offset=100 align=1 (i32.const 4) (unreachable)) - ) - ;; CHECK: (func $func_1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_1 - (drop (i32.load8_u (i32.const 4))) - (drop (i32.load8_u align=1 (i32.const 4))) - (drop (i32.load8_u offset=100 (i32.const 4))) - (drop (i32.load8_u offset=100 align=1 (i32.const 4))) - (drop (i32.load8_u offset=100 align=1 (unreachable))) - (i32.store8 (i32.const 4) (i32.const 8)) - (i32.store8 align=1 (i32.const 4) (i32.const 8)) - (i32.store8 offset=100 (i32.const 4) (i32.const 8)) - (i32.store8 offset=100 align=1 (i32.const 4) (i32.const 8)) - (i32.store8 offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store8 offset=100 align=1 (i32.const 4) (unreachable)) - ) - ;; CHECK: (func $func_signed - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=100 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=101 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s offset=100 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_signed - (drop (i32.load16_s (i32.const 4))) - (drop (i32.load16_s align=1 (i32.const 4))) - (drop (i32.load16_s align=2 (i32.const 4))) - (drop (i32.load16_s offset=100 (i32.const 4))) - (drop (i32.load16_s offset=100 align=1 (i32.const 4))) - (drop (i32.load16_s offset=100 align=2 (i32.const 4))) - (drop (i32.load16_s offset=100 align=1 (unreachable))) - ) - ;; CHECK: (func $i64-load - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=9 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=10 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $i64-load - (drop (i64.load align=1 (i32.const 12))) - (drop (i64.load align=2 (i32.const 16))) - (drop (i64.load align=4 (i32.const 20))) - (drop (i64.load align=1 offset=3 (i32.const 20))) - (drop (i64.load16_s align=1 (i32.const 28))) - (drop (i64.load32_s align=1 (i32.const 32))) - (drop (i64.load16_u align=1 (i32.const 40))) - (drop (i64.load32_u align=1 (i32.const 44))) - ) - ;; CHECK: (func $f32-load - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f32-load - (drop (f32.load align=1 (i32.const 12))) - (drop (f32.load align=2 (i32.const 16))) - (drop (f32.load align=1 offset=3 (i32.const 20))) - ) - ;; CHECK: (func $f64-load - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load16_u offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u offset=6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=6 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u offset=7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=9 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load8_u offset=10 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f64-load - (drop (f64.load align=1 (i32.const 12))) - (drop (f64.load align=2 (i32.const 16))) - (drop (f64.load align=4 (i32.const 20))) - (drop (f64.load align=1 offset=3 (i32.const 20))) - ) - ;; CHECK: (func $i64-store - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i64) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i32) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i32) - ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=6 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.const 400) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=8 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=9 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=10 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $21 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 600) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $22 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $23 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 700) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $i64-store - (i64.store align=1 (i32.const 12) (i64.const 100)) - (i64.store align=2 (i32.const 16) (i64.const 200)) - (i64.store align=4 (i32.const 20) (i64.const 300)) - (i64.store align=1 offset=3 (i32.const 24) (i64.const 400)) - (i64.store16 align=1 (i32.const 20) (i64.const 600)) - (i64.store32 align=1 (i32.const 20) (i64.const 700)) - ) - ;; CHECK: (func $f32-store - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 400) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f32-store - (f32.store align=1 (i32.const 12) (f32.const 100)) - (f32.store align=2 (i32.const 16) (f32.const 200)) - (f32.store align=1 offset=3 (i32.const 24) (f32.const 400)) - ) - ;; CHECK: (func $f64-store - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i64) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=6 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 400) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=4 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=5 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=6 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=7 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=8 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=9 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=10 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $f64-store - (f64.store align=1 (i32.const 12) (f64.const 100)) - (f64.store align=2 (i32.const 16) (f64.const 200)) - (f64.store align=4 (i32.const 20) (f64.const 300)) - (f64.store align=1 offset=3 (i32.const 24) (f64.const 400)) - ) -) diff -Nru binaryen-108/test/lit/passes/asyncify_enable-multivalue.wast binaryen-99/test/lit/passes/asyncify_enable-multivalue.wast --- binaryen-108/test/lit/passes/asyncify_enable-multivalue.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_enable-multivalue.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,2795 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --enable-multivalue -S -o - | filecheck %s - -;; Pre-existing imports that the pass turns into the implementations. -(module - (memory 1 2) - (import "asyncify" "start_unwind" (func $asyncify_start_unwind (param i32))) - (import "asyncify" "stop_unwind" (func $asyncify_stop_unwind)) - (import "asyncify" "start_rewind" (func $asyncify_start_rewind (param i32))) - (import "asyncify" "stop_rewind" (func $asyncify_stop_rewind)) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (global $sleeping (mut i32) (i32.const 0)) - (global $sleeping (mut i32) (i32.const 0)) - ;; do a sleep operation: start a sleep if running, or resume after a sleep - ;; if we just rewound. - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $do_sleep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $sleeping) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (global.set $sleeping - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $asyncify_start_unwind - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (global.set $sleeping - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $asyncify_stop_rewind) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $do_sleep - (if - (i32.eqz (global.get $sleeping)) - (block - (global.set $sleeping (i32.const 1)) - ;; we should set up the data at address 4 around here - (call $asyncify_start_unwind (i32.const 4)) - ) - (block - (global.set $sleeping (i32.const 0)) - (call $asyncify_stop_rewind) - ) - ) - ) - ;; a function that does some work and has a sleep (async pause/resume) in the middle - ;; CHECK: (func $work - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $do_sleep) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $work - (call $stuff) ;; do some work - (call $do_sleep) ;; take a break - (call $stuff) ;; do some more work - ) - ;; CHECK: (func $stuff - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $stuff) - ;; the first event called from the main event loop: just call into $work - ;; CHECK: (func $first_event - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $work) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $first_event - (call $work) - ;; work will sleep, so we exit through here while it is paused - ) - ;; the second event called from the main event loop: to resume $work, - ;; stop the unwind, then prepare a rewind, and initiate it by doing - ;; the call to rewind the call stack back up to where it was - ;; CHECK: (func $second_event - ;; CHECK-NEXT: (call $asyncify_stop_unwind) - ;; CHECK-NEXT: (call $asyncify_start_rewind - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $work) - ;; CHECK-NEXT: ) - (func $second_event - (call $asyncify_stop_unwind) - (call $asyncify_start_rewind (i32.const 4)) - (call $work) - ) - ;; a function that can't do a sleep - ;; CHECK: (func $never_sleep - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: ) - (func $never_sleep - (call $stuff) - (call $stuff) - (call $stuff) - ) -) -;; Calls to imports that will call into asyncify themselves. -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_i32_i64 (func (result i32 i64))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (import "env" "import-mv" (func $import-mv (result i32 i64))) - (import "env" "import-mv" (func $import-mv (result i32 i64))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2 (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-nothing - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) - ;; CHECK: (func $many-locals (param $x i32) (result i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $z (f32 i64)) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $many-locals (param $x i32) (result i32) - (local $y i32) - (local $z (f32 i64)) - (loop $l - (local.set $x - (i32.add (local.get $y) (i32.const 1)) - ) - (local.set $y - (i32.div_s (local.get $x) (i32.const 3)) - ) - (br_if $l (local.get $y)) - ) - (call $import) - (return (local.get $y)) - ) - ;; CHECK: (func $calls-import2-if (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import2-if (param $x i32) - (if (local.get $x) - (call $import) - ) - ) - ;; CHECK: (func $calls-import2-if-else (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else (param $x i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (call $import3 (i32.const 2)) - ) - ) - ;; CHECK: (func $calls-import2-if-else-oneside (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else-oneside (param $x i32) (result i32) - (if (local.get $x) - (return (i32.const 1)) - (call $import3 (i32.const 2)) - ) - (return (i32.const 3)) - ) - ;; CHECK: (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (return (i32.const 2)) - ) - (return (i32.const 3)) - ) - ;; CHECK: (func $calls-mv - ;; CHECK-NEXT: (local $x (i32 i64)) - ;; CHECK-NEXT: (local $1 (i32 i64)) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 (i32 i64)) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.load offset=4 align=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (call $import-mv) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store offset=4 align=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (tuple.extract 1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-mv - (local $x (i32 i64)) - (local.set $x (call $import-mv)) - ) - ;; CHECK: (func $calls-loop (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-loop (param $x i32) - (loop $l - (call $import3 (i32.const 1)) - (local.set $x - (i32.add (local.get $x) (i32.const 1)) - ) - (br_if $l - (local.get $x) - ) - ) - ) - ;; CHECK: (func $calls-loop2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-loop2 - (loop $l - (br_if $l - (call $import2) - ) - ) - ) - ;; CHECK: (func $calls-mix - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-mix - (call $boring) - (call $import) - (call $boring) - (call $import) - ) - ;; CHECK: (func $boring - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $boring) - ;; CHECK: (func $calls-mix-deep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring-deep) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import-deep) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-mix-deep - (call $boring-deep) - (call $import-deep) - (call $boring) - (call $import) - ) - ;; CHECK: (func $boring-deep - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - (func $boring-deep - (call $boring) - ) - ;; CHECK: (func $import-deep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $import-deep - (call $import) - ) -) -;; empty module, in particular with no memory -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) -(module -) -;; CHECK: (type $i32_=>_none (func (param i32))) - -;; CHECK: (type $none_=>_none (func)) - -;; CHECK: (type $none_=>_i32 (func (result i32))) - -;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - -;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - -;; CHECK: (memory $0 1 1) - -;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - -;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - -;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - -;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - -;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast binaryen-99/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast --- binaryen-108/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --mod-asyncify-always-and-only-unwind -O -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - (import "env" "import2" (func $import2 (result i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "calls-import" (func $calls-import)) - (export "calls-import" (func $calls-import)) - ;; CHECK: (export "calls-import2" (func $calls-import)) - (export "calls-import2" (func $calls-import)) - ;; CHECK: (export "calls-import2-drop" (func $calls-import)) - (export "calls-import2-drop" (func $calls-import)) - ;; CHECK: (export "calls-nothing" (func $calls-import)) - (export "calls-nothing" (func $calls-import)) - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import (; has Stack IR ;) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - (func $calls-import2-drop - (drop (call $import2)) - ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) -) -;; CHECK: (func $asyncify_start_unwind (; has Stack IR ;) (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind (; has Stack IR ;) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (; has Stack IR ;) (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (; has Stack IR ;) (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind.wast binaryen-99/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind.wast --- binaryen-108/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,508 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --mod-asyncify-always-and-only-unwind -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2 (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-nothing - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) -) -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast binaryen-99/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast --- binaryen-108/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --mod-asyncify-never-unwind -O -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - (import "env" "import2" (func $import2 (result i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "calls-import" (func $calls-import)) - (export "calls-import" (func $calls-import)) - ;; CHECK: (export "calls-import2" (func $calls-import)) - (export "calls-import2" (func $calls-import)) - ;; CHECK: (export "calls-import2-drop" (func $calls-import)) - (export "calls-import2-drop" (func $calls-import)) - ;; CHECK: (export "calls-nothing" (func $calls-import)) - (export "calls-nothing" (func $calls-import)) - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import (; has Stack IR ;) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - (func $calls-import2-drop - (drop (call $import2)) - ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) -) -;; CHECK: (func $asyncify_start_unwind (; has Stack IR ;) (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind (; has Stack IR ;) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (; has Stack IR ;) (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (; has Stack IR ;) (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_mod-asyncify-never-unwind.wast binaryen-99/test/lit/passes/asyncify_mod-asyncify-never-unwind.wast --- binaryen-108/test/lit/passes/asyncify_mod-asyncify-never-unwind.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_mod-asyncify-never-unwind.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,526 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --mod-asyncify-never-unwind -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2 (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-nothing - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) -) -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_optimize-level=1.wast binaryen-99/test/lit/passes/asyncify_optimize-level=1.wast --- binaryen-108/test/lit/passes/asyncify_optimize-level=1.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_optimize-level=1.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1616 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --optimize-level=1 -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) - ;; CHECK: (func $many-locals (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $many-locals (param $x i32) (result i32) - (local $y i32) - (loop $l - (local.set $x - (i32.add (local.get $y) (i32.const 1)) - ) - (local.set $y - (i32.div_s (local.get $x) (i32.const 3)) - ) - (br_if $l (local.get $y)) - ) - (call $import) - (return (local.get $y)) - ) - ;; CHECK: (func $calls-import2-if (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if (param $x i32) - (if (local.get $x) - (call $import) - ) - ) - ;; CHECK: (func $calls-import2-if-else (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else (param $x i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (call $import3 (i32.const 2)) - ) - ) - ;; CHECK: (func $calls-import2-if-else-oneside (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else-oneside (param $x i32) (result i32) - (if (local.get $x) - (return (i32.const 1)) - (call $import3 (i32.const 2)) - ) - (return (i32.const 3)) - ) - ;; CHECK: (func $calls-import2-if-else-oneside2 (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (return (i32.const 2)) - ) - (return (i32.const 3)) - ) - ;; CHECK: (func $calls-loop (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-loop (param $x i32) - (loop $l - (call $import3 (i32.const 1)) - (local.set $x - (i32.add (local.get $x) (i32.const 1)) - ) - (br_if $l - (local.get $x) - ) - ) - ) - ;; CHECK: (func $calls-loop2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-loop2 - (loop $l - (br_if $l - (call $import2) - ) - ) - ) - ;; CHECK: (func $calls-mix - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-mix - (call $boring) - (call $import) - (call $boring) - (call $import) - ) - ;; CHECK: (func $boring - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $boring) - ;; CHECK: (func $calls-mix-deep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring-deep) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import-deep) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-mix-deep - (call $boring-deep) - (call $import-deep) - (call $boring) - (call $import) - ) - ;; CHECK: (func $boring-deep - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - (func $boring-deep - (call $boring) - ) - ;; CHECK: (func $import-deep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $import-deep - (call $import) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-addlist@foo --pass-arg=asyncify-ignore-indirect -S -o - | filecheck %s - -(module - ;; CHECK: (type $t (func)) - (type $t (func)) - (memory 1 2) - (table 1 funcref) - (elem (i32.const 0)) - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (table $0 1 funcref) - - ;; CHECK: (elem (i32.const 0)) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call_indirect (type $t) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo ;; doesn't look like it needs instrumentation, but in add list - (call $nothing) - (call_indirect (type $t) (i32.const 0)) - ) - ;; CHECK: (func $bar - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (call_indirect (type $t) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar ;; doesn't look like it needs instrumentation, and not in add list - (call $nothing) - (call_indirect (type $t) (i32.const 0)) - ) - ;; CHECK: (func $nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nothing - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-addlist@foo.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-addlist@foo -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (block $__asyncify_unwind - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo ;; doesn't look like it needs instrumentation, but in add list - (call $nothing) - ) - ;; CHECK: (func $bar - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: ) - (func $bar ;; doesn't look like it needs instrumentation, and not in add list - (call $nothing) - ) - ;; CHECK: (func $nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nothing - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,249 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-asserts --pass-arg=asyncify-onlylist@waka -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $f (func)) - (type $f (func)) - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - (table funcref (elem $calls-import2-drop $calls-import2-drop)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $calls-import2-drop $calls-import2-drop) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $returns (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $returns (result i32) - (local $x i32) - (local.set $x (call $import2)) - (local.get $x) - ) - ;; CHECK: (func $calls-indirect (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call_indirect (type $f) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-indirect (param $x i32) - (call_indirect (type $f) - (local.get $x) - ) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,308 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-blacklist@foo,bar -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - (func $foo - (call $import) - ) - ;; CHECK: (func $bar - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - (func $bar - (call $import) - ) - ;; CHECK: (func $baz - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $baz - (call $import) - ) - ;; CHECK: (func $other1 - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $other1 - (call $foo) - ) - ;; CHECK: (func $other2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $baz) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $other2 - (call $baz) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-ignore-imports.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-ignore-imports.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-ignore-imports.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-ignore-imports.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,305 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-ignore-imports -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $f (func)) - (type $f (func)) - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - (table funcref (elem $calls-import2-drop $calls-import2-drop)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $calls-import2-drop $calls-import2-drop) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-import2-if-else (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else (param $x i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (call $import3 (i32.const 2)) - ) - ) - ;; CHECK: (func $calls-indirect (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call_indirect (type $f) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-indirect (param $x i32) - (call_indirect (type $f) - (local.get $x) - ) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,579 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-ignore-indirect -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $f (func)) - (type $f (func)) - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - (table funcref (elem $calls-import2-drop $calls-import2-drop)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $calls-import2-drop $calls-import2-drop) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-import2-if-else (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else (param $x i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (call $import3 (i32.const 2)) - ) - ) - ;; CHECK: (func $calls-indirect (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_indirect (type $f) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-indirect (param $x i32) - (call_indirect (type $f) - (local.get $x) - ) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1886 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-imports@env.import,env.import2 -S -o - | filecheck %s - -;; Pre-existing imports that the pass turns into the implementations. -(module - (memory 1 2) - (import "asyncify" "start_unwind" (func $asyncify_start_unwind (param i32))) - (import "asyncify" "start_rewind" (func $asyncify_start_rewind (param i32))) - (import "asyncify" "stop_rewind" (func $asyncify_stop_rewind)) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (global $sleeping (mut i32) (i32.const 0)) - (global $sleeping (mut i32) (i32.const 0)) - ;; do a sleep operation: start a sleep if running, or resume after a sleep - ;; if we just rewound. - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $do_sleep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $sleeping) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (global.set $sleeping - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $asyncify_start_unwind - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (global.set $sleeping - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $asyncify_stop_rewind) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $do_sleep - (if - (i32.eqz (global.get $sleeping)) - (block - (global.set $sleeping (i32.const 1)) - ;; we should set up the data at address 4 around here - (call $asyncify_start_unwind (i32.const 4)) - ) - (block - (global.set $sleeping (i32.const 0)) - (call $asyncify_stop_rewind) - ) - ) - ) - ;; a function that does some work and has a sleep (async pause/resume) in the middle - ;; CHECK: (func $work - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $do_sleep) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $work - (call $stuff) ;; do some work - (call $do_sleep) ;; take a break - (call $stuff) ;; do some more work - ) - ;; CHECK: (func $stuff - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $stuff) - ;; the first event called from the main event loop: just call into $work - ;; CHECK: (func $first_event - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $work) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $first_event - (call $work) - ;; work will sleep, so we exit through here while it is paused - ) - ;; the second event called from the main event loop: to resume $work, - ;; initiate a rewind, and then do the call to start things back up - ;; CHECK: (func $second_event - ;; CHECK-NEXT: (call $asyncify_start_rewind - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $work) - ;; CHECK-NEXT: ) - (func $second_event - (call $asyncify_start_rewind (i32.const 4)) - (call $work) - ) - ;; a function that can't do a sleep - ;; CHECK: (func $never_sleep - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: (call $stuff) - ;; CHECK-NEXT: ) - (func $never_sleep - (call $stuff) - (call $stuff) - (call $stuff) - ) -) -;; Calls to imports that will call into asyncify themselves. -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (result i32))) - (import "env" "import2" (func $import2 (result i32))) - ;; CHECK: (import "env" "import3" (func $import3 (param i32))) - (import "env" "import3" (func $import3 (param i32))) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-import2 (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $calls-import2 (result i32) - (local $temp i32) - (local.set $temp (call $import2)) - (return (local.get $temp)) - ) - ;; CHECK: (func $calls-import2-drop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-drop - (drop (call $import2)) - ) - ;; CHECK: (func $calls-nothing - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-nothing - (drop (i32.eqz (i32.const 17))) - ) - ;; CHECK: (func $many-locals (param $x i32) (result i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $many-locals (param $x i32) (result i32) - (local $y i32) - (loop $l - (local.set $x - (i32.add (local.get $y) (i32.const 1)) - ) - (local.set $y - (i32.div_s (local.get $x) (i32.const 3)) - ) - (br_if $l (local.get $y)) - ) - (call $import) - (return (local.get $y)) - ) - ;; CHECK: (func $calls-import2-if (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import2-if (param $x i32) - (if (local.get $x) - (call $import) - ) - ) - ;; CHECK: (func $calls-import2-if-else (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else (param $x i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (call $import3 (i32.const 2)) - ) - ) - ;; CHECK: (func $calls-import2-if-else-oneside (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else-oneside (param $x i32) (result i32) - (if (local.get $x) - (return (i32.const 1)) - (call $import3 (i32.const 2)) - ) - (return (i32.const 3)) - ) - ;; CHECK: (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) - (if (local.get $x) - (call $import3 (i32.const 1)) - (return (i32.const 2)) - ) - (return (i32.const 3)) - ) - ;; CHECK: (func $calls-loop (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-loop (param $x i32) - (loop $l - (call $import3 (i32.const 1)) - (local.set $x - (i32.add (local.get $x) (i32.const 1)) - ) - (br_if $l - (local.get $x) - ) - ) - ) - ;; CHECK: (func $calls-loop2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $import2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $l - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $calls-loop2 - (loop $l - (br_if $l - (call $import2) - ) - ) - ) - ;; CHECK: (func $calls-mix - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-mix - (call $boring) - (call $import) - (call $boring) - (call $import) - ) - ;; CHECK: (func $boring - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $boring) - ;; CHECK: (func $calls-mix-deep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring-deep) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import-deep) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-mix-deep - (call $boring-deep) - (call $import-deep) - (call $boring) - (call $import) - ) - ;; CHECK: (func $boring-deep - ;; CHECK-NEXT: (call $boring) - ;; CHECK-NEXT: ) - (func $boring-deep - (call $boring) - ) - ;; CHECK: (func $import-deep - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $import-deep - (call $import) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,308 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-onlylist@foo,bar -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo - (call $import) - ) - ;; CHECK: (func $bar - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $bar - (call $import) - ) - ;; CHECK: (func $baz - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - (func $baz - (call $import) - ) - ;; CHECK: (func $other1 - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $other1 - (call $foo) ;; even though we call foo, we are not in the only list, so do not instrument us - ) - ;; CHECK: (func $other2 - ;; CHECK-NEXT: (call $baz) - ;; CHECK-NEXT: ) - (func $other2 - (call $baz) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-side-module.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-side-module.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-side-module.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-side-module.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --enable-mutable-globals --asyncify --pass-arg=asyncify-relocatable -S -o - | filecheck %s - -(module -) -;; CHECK: (type $i32_=>_none (func (param i32))) - -;; CHECK: (type $none_=>_none (func)) - -;; CHECK: (type $none_=>_i32 (func (result i32))) - -;; CHECK: (import "env" "__asyncify_state" (global $__asyncify_state (mut i32))) - -;; CHECK: (import "env" "__asyncify_data" (global $__asyncify_data (mut i32))) - -;; CHECK: (memory $0 1 1) - -;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - -;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - -;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - -;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - -;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-verbose.wast binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-verbose.wast --- binaryen-108/test/lit/passes/asyncify_pass-arg=asyncify-verbose.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify_pass-arg=asyncify-verbose.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,386 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify --pass-arg=asyncify-verbose -S -o - | filecheck %s - -(module - (memory 1 2) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-import - (call $import) - ) - ;; CHECK: (func $calls-calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $calls-import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-calls-import - (call $calls-import) - ) - ;; CHECK: (func $calls-calls-calls-import - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $calls-calls-import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $calls-calls-calls-import - (call $calls-calls-import) - ) - ;; CHECK: (func $nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nothing - (nop) - ) -) - -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/asyncify.wast binaryen-99/test/lit/passes/asyncify.wast --- binaryen-108/test/lit/passes/asyncify.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/asyncify.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1334 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --asyncify -S -o - | filecheck %s - -(module - ;; CHECK: (type $f (func (param i32))) - (type $f (func (param i32))) - (memory 1 2) - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "import" (func $import)) - (import "env" "import" (func $import)) - ;; CHECK: (import "env" "import2" (func $import2 (param i32))) - (import "env" "import2" (func $import2 (param i32))) - (table funcref (elem $liveness2 $liveness2)) - ;; CHECK: (global $__asyncify_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__asyncify_data (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 2) - - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $liveness2 $liveness2) - - ;; CHECK: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) - - ;; CHECK: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) - - ;; CHECK: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) - - ;; CHECK: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) - - ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - - ;; CHECK: (func $liveness1 (param $live0 i32) (param $dead0 i32) - ;; CHECK-NEXT: (local $live1 i32) - ;; CHECK-NEXT: (local $dead1 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live1 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $dead0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $dead1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $liveness1 (param $live0 i32) (param $dead0 i32) - (local $live1 i32) - (local $dead1 i32) - (drop (local.get $dead0)) - (drop (local.get $dead1)) - (call $import) - (drop (local.get $live0)) - (drop (local.get $live1)) - ) - ;; CHECK: (func $liveness2 (param $live0 i32) (param $dead0 i32) - ;; CHECK-NEXT: (local $live1 i32) - ;; CHECK-NEXT: (local $dead1 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live1 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $dead0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $dead1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $liveness2 (param $live0 i32) (param $dead0 i32) - (local $live1 i32) - (local $dead1 i32) - (drop (local.get $dead0)) - (drop (local.get $dead1)) - (call $import) - (drop (local.get $live0)) - (drop (local.get $live1)) - ) - ;; CHECK: (func $liveness3 (param $live0 i32) (param $dead0 i32) - ;; CHECK-NEXT: (local $live1 i32) - ;; CHECK-NEXT: (local $dead1 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live1 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $liveness3 (param $live0 i32) (param $dead0 i32) - (local $live1 i32) - (local $dead1 i32) - (call $import) - (drop (local.get $live0)) - (call $import) - (drop (local.get $live1)) - ) - ;; CHECK: (func $liveness4 (param $live0 i32) (param $dead0 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $live0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $liveness4 (param $live0 i32) (param $dead0 i32) - (if (i32.const 0) - (call $import) - ) - (drop (local.get $live0)) - ) - ;; CHECK: (func $liveness5 (param $dead0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $dead0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $dead0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $dead0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $liveness5 (param $dead0 i32) - (drop (local.get $dead0)) - (if (i32.const 0) - (call $import) ;; live before and after call, but not during - ) - (local.set $dead0 (i32.const 1)) - (drop (local.get $dead0)) - ) - ;; CHECK: (func $liveness-call-kills (param $live i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $live) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $import2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $liveness-call-kills (param $live i32) - (call $import2 (local.get $live)) - ) - ;; CHECK: (func $liveness-indirect-kills (param $live0 i32) (param $live1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (block $__asyncify_unwind (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $live0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $live1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call_indirect (type $f) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $__asyncify_state) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__asyncify_unwind - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $__asyncify_data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $liveness-indirect-kills (param $live0 i32) (param $live1 i32) - (call_indirect (type $f) (local.get $live0) (local.get $live1)) - ) -) -;; CHECK: (func $asyncify_start_unwind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_unwind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_start_rewind (param $0 i32) -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__asyncify_data -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_stop_rewind -;; CHECK-NEXT: (global.set $__asyncify_state -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.gt_u -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load offset=4 -;; CHECK-NEXT: (global.get $__asyncify_data) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $asyncify_get_state (result i32) -;; CHECK-NEXT: (global.get $__asyncify_state) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/avoid-reinterprets64.wast binaryen-99/test/lit/passes/avoid-reinterprets64.wast --- binaryen-108/test/lit/passes/avoid-reinterprets64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/avoid-reinterprets64.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --avoid-reinterprets --enable-memory64 -S -o - | filecheck %s - -(module - (memory i64 1) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_f32 (func (result f32))) - - ;; CHECK: (memory $0 i64 1) - - ;; CHECK: (func $simple - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $simple - (drop (f32.reinterpret_i32 (i32.load (i64.const 1024)))) - (drop (i32.reinterpret_f32 (f32.load (i64.const 1024)))) - (drop (f64.reinterpret_i64 (i64.load (i64.const 1024)))) - (drop (i64.reinterpret_f64 (f64.load (i64.const 1024)))) - ) - ;; CHECK: (func $one - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $one - (local $x i32) - (local.set $x (i32.load (i64.const 1024))) - (drop (f32.reinterpret_i32 (local.get $x))) - ) - ;; CHECK: (func $one-b - ;; CHECK-NEXT: (local $x f32) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result f32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $one-b - (local $x f32) - (local.set $x (f32.load (i64.const 1024))) - (drop (i32.reinterpret_f32 (local.get $x))) - ) - ;; CHECK: (func $both - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $both - (local $x i32) - (local.set $x (i32.load (i64.const 1024))) - (drop (f32.reinterpret_i32 (local.get $x))) - (drop (f32.reinterpret_i32 (local.get $x))) - ) - ;; CHECK: (func $half - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $half - (local $x i32) - (local.set $x (i32.load (i64.const 1024))) - (drop (local.get $x)) - (drop (f32.reinterpret_i32 (local.get $x))) - ) - ;; CHECK: (func $copy - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $copy - (local $x i32) - (local $y i32) - (local.set $x (i32.load (i64.const 1024))) - (local.set $y (local.get $x)) - (drop (f32.reinterpret_i32 (local.get $y))) - ) - ;; CHECK: (func $partial1 (result f32) - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial1 (result f32) - (f32.reinterpret_i32 - (i32.load16_u - (i64.const 3) - ) - ) - ) - ;; CHECK: (func $partial2 (result f32) - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial2 (result f32) - (f32.reinterpret_i32 - (i32.load8_u - (i64.const 3) - ) - ) - ) - ;; CHECK: (func $nofallthrough - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i64.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nofallthrough - (local $x i32) - (local.set $x - (i32.load - (i64.const 1024) - ) - ) - (drop - (f32.reinterpret_i32 - (block (result i32) - (nop) ;; this would be removed by other opts, but in general, we can't - ;; just look at the fallthrough, as we can't just remove code here - (local.get $x) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/avoid-reinterprets.wast binaryen-99/test/lit/passes/avoid-reinterprets.wast --- binaryen-108/test/lit/passes/avoid-reinterprets.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/avoid-reinterprets.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --avoid-reinterprets -S -o - | filecheck %s - -(module - (memory 1) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_f32 (func (result f32))) - - ;; CHECK: (memory $0 1) - - ;; CHECK: (func $simple - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $simple - (drop (f32.reinterpret_i32 (i32.load (i32.const 1024)))) - (drop (i32.reinterpret_f32 (f32.load (i32.const 1024)))) - (drop (f64.reinterpret_i64 (i64.load (i32.const 1024)))) - (drop (i64.reinterpret_f64 (f64.load (i32.const 1024)))) - ) - ;; CHECK: (func $one - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $one - (local $x i32) - (local.set $x (i32.load (i32.const 1024))) - (drop (f32.reinterpret_i32 (local.get $x))) - ) - ;; CHECK: (func $one-b - ;; CHECK-NEXT: (local $x f32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result f32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $one-b - (local $x f32) - (local.set $x (f32.load (i32.const 1024))) - (drop (i32.reinterpret_f32 (local.get $x))) - ) - ;; CHECK: (func $both - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $both - (local $x i32) - (local.set $x (i32.load (i32.const 1024))) - (drop (f32.reinterpret_i32 (local.get $x))) - (drop (f32.reinterpret_i32 (local.get $x))) - ) - ;; CHECK: (func $half - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $half - (local $x i32) - (local.set $x (i32.load (i32.const 1024))) - (drop (local.get $x)) - (drop (f32.reinterpret_i32 (local.get $x))) - ) - ;; CHECK: (func $copy - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $copy - (local $x i32) - (local $y i32) - (local.set $x (i32.load (i32.const 1024))) - (local.set $y (local.get $x)) - (drop (f32.reinterpret_i32 (local.get $y))) - ) - ;; CHECK: (func $partial1 (result f32) - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial1 (result f32) - (f32.reinterpret_i32 - (i32.load16_u - (i32.const 3) - ) - ) - ) - ;; CHECK: (func $partial2 (result f32) - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial2 (result f32) - (f32.reinterpret_i32 - (i32.load8_u - (i32.const 3) - ) - ) - ) - ;; CHECK: (func $nofallthrough - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nofallthrough - (local $x i32) - (local.set $x - (i32.load - (i32.const 1024) - ) - ) - (drop - (f32.reinterpret_i32 - (block (result i32) - (nop) ;; this would be removed by other opts, but in general, we can't - ;; just look at the fallthrough, as we can't just remove code here - (local.get $x) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/catch-pop-fixup-eh.wast binaryen-99/test/lit/passes/catch-pop-fixup-eh.wast --- binaryen-108/test/lit/passes/catch-pop-fixup-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/catch-pop-fixup-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,396 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; We run wasm-opt with --no-validation because functions in this file contain -;; 'pop's in invalid positions and the objective of this test is to fix them. -;; But wasm-opt runs validation after reading functions, so we need to disable -;; it to proceed. -;; RUN: wasm-opt %s --catch-pop-fixup --no-validation -all -S -o - | filecheck %s - -(module - ;; CHECK: (type $struct.A (struct (field i32))) - - ;; CHECK: (tag $e-i32 (param i32)) - (tag $e-i32 (param i32)) - ;; CHECK: (tag $e-i32-f32 (param i32 f32)) - (tag $e-i32-f32 (param i32 f32)) - - (type $struct.A (struct i32)) - ;; CHECK: (tag $e-struct.A (param (ref $struct.A))) - (tag $e-struct.A (param (ref $struct.A))) - - ;; CHECK: (func $pop-within-block1 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (throw $e-i32 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-block1 - (try - (do) - (catch $e-i32 - (throw $e-i32 - ;; The pop is within a block, so it will be handled - (block (result i32) - (pop i32) - ) - ) - ) - ) - ) - - ;; CHECK: (func $pop-within-block2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (throw $e-i32 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (block $block0 (result i32) - ;; CHECK-NEXT: (block $block1 (result i32) - ;; CHECK-NEXT: (block $block2 (result i32) - ;; CHECK-NEXT: (block $block3 (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-block2 - (try - (do) - (catch $e-i32 - (throw $e-i32 - ;; More nesting of blocks can be handled too - (block (result i32) - (block (result i32) - (block (result i32) - (block (result i32) - (block (result i32) - (pop i32) - ) - ) - ) - ) - ) - ) - ) - ) - ) - - ;; CHECK: (func $pop-within-block3 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $l0 (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $l0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-block3 (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch $e-i32 - ;; This block cannot be deleted when written back because there is a - ;; branch targeting this block. So the pop inside will be handled. - (block $l0 (result i32) - (drop - (pop i32) - ) - (br $l0 - (i32.const 0) - ) - ) - ) - ) - ) - - ;; CHECK: (func $helper - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper) - ;; CHECK: (func $pop-within-implicit-block1 - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-implicit-block1 - (try - (do) - (catch $e-i32 - ;; Because this catch contains multiple instructions, an implicit - ;; block will be created within the catch when parsed. But that block - ;; will be deleted when written back, so this pop is not considered - ;; nested in a block. - (drop - (pop i32) - ) - (call $helper) - ) - ) - ) - - ;; CHECK: (func $pop-within-implicit-block2 - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-implicit-block2 - (try - (do) - (catch $e-i32 - ;; In this case we explicitly wrap the pop with a 'block', but this - ;; block doesn't have any targeting branches, it will be also deleted - ;; when written back to binary. So this pop is fine and not considered - ;; nested in a block. - (block - (drop - (pop i32) - ) - (call $helper) - ) - ) - ) - ) - - ;; CHECK: (func $pop-within-try (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (try $try4 (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-try (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch $e-i32 - ;; The pop is wihtin a try, so it will be handled - (try (result i32) - (do - (pop i32) - ) - (catch_all - (i32.const 0) - ) - ) - ) - ) - ) - - ;; CHECK: (func $pop-within-if-condition (result i32) - ;; CHECK-NEXT: (try $try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-if-condition (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch $e-i32 - ;; The pop is wihtin an if condition, which is considered not nested. - ;; This will be not handled. - (if (result i32) - (pop i32) - (then (i32.const 1)) - (else (i32.const 0)) - ) - ) - ) - ) - - ;; CHECK: (func $pop-within-block-within-if-condition - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $l0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-block-within-if-condition - (try - (do) - (catch $e-i32 - ;; This block cannot be removed because there is a branch targeting - ;; this. This pop should be handled because the whole 'if' is nested - ;; within the block. - (block $l0 - (drop - (if (result i32) - (pop i32) - (then (i32.const 1)) - (else (i32.const 0)) - ) - ) - (br $l0) - ) - ) - ) - ) - - ;; CHECK: (func $pop-tuple-within-block - ;; CHECK-NEXT: (local $x (i32 f32)) - ;; CHECK-NEXT: (local $1 (i32 f32)) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32-f32 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop i32 f32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (throw $e-i32 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-tuple-within-block (local $x (i32 f32)) - (try - (do) - (catch $e-i32-f32 - (throw $e-i32 - ;; This tests a pop taking a tuple type. - (block (result i32) - (local.set $x (pop i32 f32)) - (i32.const 0) - ) - ) - ) - ) - ) - - ;; CHECK: (func $pop-non-defaultable-type-within-block - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-struct.A - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop (ref $struct.A)) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (throw $e-struct.A - ;; CHECK-NEXT: (block $block (result (ref $struct.A)) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-non-defaultable-type-within-block - (try - (do) - (catch $e-struct.A - (throw $e-struct.A - ;; The pop is within a block, so it will be handled. But because this - ;; pop is of non-defaultable type, we have to fix it up using - ;; TypeUpdating::handleNonDefaultableLocals: the new local created is - ;; converted to (ref null $struct.A) type and we read the local using - ;; 'ref.as_non_null'. - (block (result (ref $struct.A)) - (pop (ref $struct.A)) - ) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/cfp.wast binaryen-99/test/lit/passes/cfp.wast --- binaryen-108/test/lit/passes/cfp.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/cfp.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,2185 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --remove-unused-names --cfp -all -S -o - | filecheck %s -;; (remove-unused-names is added to test fallthrough values without a block -;; name getting in the way) - -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - ;; CHECK: (func $impossible-get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $impossible-get - (drop - ;; This type is never created, so a get is impossible, and we will trap - ;; anyhow. So we can turn this into an unreachable (plus a drop of the - ;; reference). - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field i64) data)) - (type $struct (struct i64)) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - ;; The only place this type is created is with a default value, and so we - ;; can optimize the later get into a constant (plus a drop of the ref). - ;; - ;; (Note that the allocated reference is dropped here, so it is not actually - ;; used anywhere, but this pass does not attempt to trace the paths of - ;; references escaping and being stored etc. - it just thinks at the type - ;; level.) - (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field f32) data)) - (type $struct (struct f32)) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - ;; The only place this type is created is with a constant value, and so we - ;; can optimize the later get into a constant (plus a drop of the ref). - (drop - (struct.new_with_rtt $struct - (f32.const 42) - (rtt.canon $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field f32) data)) - (type $struct (struct f32)) - ;; CHECK: (type $f32_=>_none (func_subtype (param f32) func)) - - ;; CHECK: (func $test (type $f32_=>_none) (param $f f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test (param $f f32) - ;; The value given is not a constant, and so we cannot optimize. - (drop - (struct.new_with_rtt $struct - (local.get $f) - (rtt.canon $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Create in one function, get in another. The 10 should be forwarded to the -;; get. -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; As before, but with the order of functions reversed to check for any ordering -;; issues. -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - ) -) - -;; Different values assigned in the same function, in different struct.news, -;; so we cannot optimize the struct.get away. -(module - ;; CHECK: (type $struct (struct_subtype (field f32) data)) - (type $struct (struct f32)) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (f32.const 1337) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new_with_rtt $struct - (f32.const 42) - (rtt.canon $struct) - ) - ) - (drop - (struct.new_with_rtt $struct - (f32.const 1337) - (rtt.canon $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Different values assigned in different functions, and one is a struct.set. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut f32)) data)) - (type $struct (struct (mut f32))) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (f32.const 42) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $set (type $none_=>_none) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (f32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set - (struct.set $struct 0 - (ref.null $struct) - (f32.const 1337) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; As the last testcase, but the values happen to coincide, so we can optimize -;; the get into a constant. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut f32)) data)) - (type $struct (struct (mut f32))) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (f32.const 42) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $set (type $none_=>_none) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set - (struct.set $struct 0 - (ref.null $struct) - (f32.const 42) ;; The last testcase had 1337 here. - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Check that we look into the fallthrough value that is assigned. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut f32)) data)) - (type $struct (struct (mut f32))) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (block (result f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - ;; Fall though a 42 via a block. - (block (result f32) - (nop) - (f32.const 42) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $set (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (if (result f32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set (param $x i32) - (struct.set $struct 0 - (ref.null $struct) - ;; Fall though a 42 via an if. - (if (result f32) - (local.get $x) - (unreachable) - (f32.const 42) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Test a function reference instead of a number. -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field funcref) data)) - (type $struct (struct funcref)) - ;; CHECK: (elem declare func $test) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (ref.func $test) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $none_=>_none)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $test) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new_with_rtt $struct - (ref.func $test) - (rtt.canon $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Test for unreachable creations, sets, and gets. -(module - (type $struct (struct (mut i32))) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (unreachable) - ) - ) - (drop - (struct.get $struct 0 - (unreachable) - ) - ) - (struct.set $struct 0 - (unreachable) - (i32.const 20) - ) - ) -) - -;; Subtyping: Create a supertype and get a subtype. As we never create a -;; subtype, the get must trap anyhow (the reference it receives can -;; only be null in this closed world). -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - ;; CHECK: (type $substruct (struct_subtype (field i32) $struct)) - (type $substruct (struct_subtype i32 $struct)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $substruct 0 - (ref.null $substruct) - ) - ) - ) -) - -;; As above, but in addition to a new of $struct also add a set. The set could -;; in principle be relevant for the get as far as this pass knows, and so we -;; will optimize the result to the only possible value. (In practice, though, -;; it will trap anyhow.) -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $substruct (struct_subtype (field (mut i32)) $struct)) - (type $substruct (struct_subtype (mut i32) $struct)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - (struct.set $struct 0 - (ref.null $struct) - (i32.const 10) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $substruct 0 - (ref.null $substruct) - ) - ) - ) -) - -;; Subtyping: Create a subtype and get a supertype. The get must receive a -;; reference to the subtype (we never create a supertype) and so we -;; can optimize. -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - - ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) - (type $substruct (struct_subtype i32 f64 $struct)) - - (type $struct (struct i32)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $substruct - (i32.const 10) - (f64.const 3.14159) - (rtt.canon $substruct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Subtyping: Create both a subtype and a supertype, with identical constants -;; for the shared field, and get the supertype. -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) - (type $substruct (struct_subtype i32 f64 $struct)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - (drop - (struct.new_with_rtt $substruct - (i32.const 10) - (f64.const 3.14159) - (rtt.canon $substruct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Subtyping: Create both a subtype and a supertype, with different constants -;; for the shared field, preventing optimization, as a get of the -;; supertype may receive an instance of the subtype. -(module - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) - (type $substruct (struct_subtype i32 f64 $struct)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - (drop - (struct.new_with_rtt $substruct - (i32.const 20) - (f64.const 3.14159) - (rtt.canon $substruct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Subtyping: Create both a subtype and a supertype, with different constants -;; for the shared field, but get from the subtype. The field is -;; shared between the types, but we only create the substruct with -;; one value, so we can optimize. -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - - ;; CHECK: (type $substruct (struct_subtype (field i32) (field f64) $struct)) - (type $substruct (struct_subtype i32 f64 $struct)) - - (type $struct (struct i32)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - (drop - (struct.new_with_rtt $substruct - (i32.const 20) - (f64.const 3.14159) - (rtt.canon $substruct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $substruct 0 - (ref.null $substruct) - ) - ) - ) -) - -;; As above, but add a set of $struct. The set prevents the optimization. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - - ;; CHECK: (type $substruct (struct_subtype (field (mut i32)) (field f64) $struct)) - (type $substruct (struct_subtype (mut i32) f64 $struct)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $substruct - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (rtt.canon $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.const 10) - (rtt.canon $struct) - ) - ) - (struct.set $struct 0 - (ref.null $struct) - (i32.const 10) - ) - (drop - (struct.new_with_rtt $substruct - (i32.const 20) - (f64.const 3.14159) - (rtt.canon $substruct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $substruct 0 - ;; CHECK-NEXT: (ref.null $substruct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $substruct 0 - (ref.null $substruct) - ) - ) - ) -) - -;; Multi-level subtyping, check that we propagate not just to the immediate -;; supertype but all the way as needed. -(module - ;; CHECK: (type $struct1 (struct_subtype (field i32) data)) - - ;; CHECK: (type $struct2 (struct_subtype (field i32) (field f64) $struct1)) - - ;; CHECK: (type $struct3 (struct_subtype (field i32) (field f64) (field anyref) $struct2)) - (type $struct3 (struct_subtype i32 f64 anyref $struct2)) - - (type $struct2 (struct_subtype i32 f64 $struct1)) - - (type $struct1 (struct i32)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct3 - (i32.const 20) - (f64.const 3.14159) - (ref.null any) - (rtt.canon $struct3) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - ;; Get field 0 from the $struct1. This can be optimized to a constant - ;; since we only ever created an instance of struct3 with a constant there. - (drop - (struct.get $struct1 0 - (ref.null $struct1) - ) - ) - ;; Get both fields of $struct2. - (drop - (struct.get $struct2 0 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct2 1 - (ref.null $struct2) - ) - ) - ;; Get all 3 fields of $struct3 - (drop - (struct.get $struct3 0 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 1 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 2 - (ref.null $struct3) - ) - ) - ) -) - -;; Multi-level subtyping with conflicts. The even-numbered fields will get -;; different values in the sub-most type. Create the top and bottom types, but -;; not the middle one. -(module - ;; CHECK: (type $struct1 (struct_subtype (field i32) (field i32) data)) - - ;; CHECK: (type $struct2 (struct_subtype (field i32) (field i32) (field f64) (field f64) $struct1)) - - ;; CHECK: (type $struct3 (struct_subtype (field i32) (field i32) (field f64) (field f64) (field anyref) (field anyref) $struct2)) - (type $struct3 (struct_subtype i32 i32 f64 f64 anyref anyref $struct2)) - - (type $struct1 (struct i32 i32)) - - (type $struct2 (struct_subtype i32 i32 f64 f64 $struct1)) - - ;; CHECK: (type $anyref_=>_none (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $anyref_=>_none) (param $any anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (rtt.canon $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 999) - ;; CHECK-NEXT: (f64.const 2.71828) - ;; CHECK-NEXT: (f64.const 9.9999999) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: (rtt.canon $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create (param $any anyref) - (drop - (struct.new_with_rtt $struct1 - (i32.const 10) - (i32.const 20) - (rtt.canon $struct1) - ) - ) - (drop - (struct.new_with_rtt $struct3 - (i32.const 10) - (i32.const 999) ;; use a different value here - (f64.const 2.71828) - (f64.const 9.9999999) - (ref.null any) - (local.get $any) ;; use a non-constant value here, which can never be - ;; optimized. - (rtt.canon $struct3) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct1 1 - ;; CHECK-NEXT: (ref.null $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 2.71828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 9.9999999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 2.71828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 9.9999999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct3 5 - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - ;; Get all the fields of all the structs. - (drop - (struct.get $struct1 0 - (ref.null $struct1) - ) - ) - (drop - (struct.get $struct1 1 - (ref.null $struct1) - ) - ) - (drop - (struct.get $struct2 0 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct2 1 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct2 2 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct2 3 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct3 0 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 1 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 2 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 3 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 4 - (ref.null $struct3) - ) - ) - (drop - (struct.get $struct3 5 - (ref.null $struct3) - ) - ) - ) -) - -;; Multi-level subtyping with a different value in the middle of the chain. We -;; can only optimize $struct3. -(module - ;; CHECK: (type $struct1 (struct_subtype (field (mut i32)) data)) - (type $struct1 (struct (mut i32))) - ;; CHECK: (type $struct2 (struct_subtype (field (mut i32)) (field f64) $struct1)) - (type $struct2 (struct_subtype (mut i32) f64 $struct1)) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct3 (struct_subtype (field (mut i32)) (field f64) (field anyref) $struct2)) - (type $struct3 (struct_subtype (mut i32) f64 anyref $struct2)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 - ;; CHECK-NEXT: (i32.const 9999) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct1 - (i32.const 10) - (rtt.canon $struct1) - ) - ) - (drop - (struct.new_with_rtt $struct2 - (i32.const 9999) ;; use a different value here - (f64.const 0) - (rtt.canon $struct2) - ) - ) - (drop - (struct.new_with_rtt $struct3 - (i32.const 10) - (f64.const 0) - (ref.null any) - (rtt.canon $struct3) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct1 0 - ;; CHECK-NEXT: (ref.null $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct2 0 - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - ;; Get field 0 in all the types. - (drop - (struct.get $struct1 0 - (ref.null $struct1) - ) - ) - (drop - (struct.get $struct2 0 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct3 0 - (ref.null $struct3) - ) - ) - ) -) - -;; As above, but add not just a new of the middle class with a different value -;; but also a set. That prevents all optimizations. -(module - ;; CHECK: (type $struct1 (struct_subtype (field (mut i32)) data)) - - ;; CHECK: (type $struct2 (struct_subtype (field (mut i32)) (field f64) $struct1)) - (type $struct2 (struct_subtype (mut i32) f64 $struct1)) - - (type $struct1 (struct (mut i32))) - - ;; CHECK: (type $struct3 (struct_subtype (field (mut i32)) (field f64) (field anyref) $struct2)) - (type $struct3 (struct_subtype (mut i32) f64 anyref $struct2)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct1 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct2 - ;; CHECK-NEXT: (i32.const 9999) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (rtt.canon $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct2 0 - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: (i32.const 9999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct3 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (rtt.canon $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct1 - (i32.const 10) - (rtt.canon $struct1) - ) - ) - (drop - (struct.new_with_rtt $struct2 - (i32.const 9999) ;; use a different value here - (f64.const 0) - (rtt.canon $struct2) - ) - ) - (struct.set $struct2 0 - (ref.null $struct2) - (i32.const 9999) ;; use a different value here - (f64.const 0) - ) - (drop - (struct.new_with_rtt $struct3 - (i32.const 10) - (f64.const 0) - (ref.null any) - (rtt.canon $struct3) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct1 0 - ;; CHECK-NEXT: (ref.null $struct1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct2 0 - ;; CHECK-NEXT: (ref.null $struct2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct3 0 - ;; CHECK-NEXT: (ref.null $struct3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - ;; Get field 0 in all the types. - (drop - (struct.get $struct1 0 - (ref.null $struct1) - ) - ) - (drop - (struct.get $struct2 0 - (ref.null $struct2) - ) - ) - (drop - (struct.get $struct3 0 - (ref.null $struct3) - ) - ) - ) -) - -;; Test for a struct with multiple fields, some of which are constant and hence -;; optimizable, and some not. Also test that some have the same type. -(module - ;; CHECK: (type $struct (struct_subtype (field i32) (field f64) (field i32) (field f64) (field i32) data)) - (type $struct (struct i32 f64 i32 f64 i32)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.const 2.71828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $struct - (i32.eqz (i32.const 10)) ;; not a constant (as far as this pass knows) - (f64.const 3.14159) - (i32.const 20) - (f64.abs (f64.const 2.71828)) ;; not a constant - (i32.const 30) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $get (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 3 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 1 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 2 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 3 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 4 - (ref.null $struct) - ) - ) - ;; Also test for multiple gets of the same field. - (drop - (struct.get $struct 4 - (ref.null $struct) - ) - ) - ) -) - -;; Never create A, but have a set to its field. A subtype B has no creates nor -;; sets, and the final subtype C has a create and a get. The set to A should -;; apply to it, preventing optimization. -(module - ;; CHECK: (type $A (struct_subtype (field (mut i32)) data)) - - ;; CHECK: (type $B (struct_subtype (field (mut i32)) $A)) - - ;; CHECK: (type $C (struct_subtype (field (mut i32)) $B)) - (type $C (struct_subtype (mut i32) $B)) - - (type $A (struct (mut i32))) - - (type $B (struct_subtype (mut i32) $A)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $ref|$A|_=>_none (func_subtype (param (ref $A)) func)) - - ;; CHECK: (type $ref|$C|_=>_none (func_subtype (param (ref $C)) func)) - - ;; CHECK: (func $create (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $C - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (rtt.canon $C) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $create - (drop - (struct.new_with_rtt $C - (i32.const 10) - (rtt.canon $C) - ) - ) - ) - ;; CHECK: (func $set (type $ref|$A|_=>_none) (param $a (ref $A)) - ;; CHECK-NEXT: (struct.set $A 0 - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set (param $a (ref $A)) - (struct.set $A 0 - (local.get $a) - (i32.const 20) - ) - ) - ;; CHECK: (func $get (type $ref|$C|_=>_none) (param $c (ref $C)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $C 0 - ;; CHECK-NEXT: (local.get $c) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $get (param $c (ref $C)) - (drop - (struct.get $C 0 - (local.get $c) - ) - ) - ) -) - -;; Copies of a field to itself can be ignored. As a result, we can optimize both -;; of the gets here. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ;; This copy does not actually introduce any new possible values, and so it - ;; remains true that the only possible value is the default. - (struct.set $struct 0 - (ref.null $struct) - (struct.get $struct 0 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -;; Test of a near-copy, of a similar looking field (same index, and same field -;; type) but in a different struct. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut f32)) (field (mut i32)) data)) - (type $struct (struct (mut f32) (mut i32))) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $other (struct_subtype (field (mut f64)) (field (mut i32)) data)) - (type $other (struct (mut f64) (mut i32))) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 1 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $other) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 1 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ;; As this is not a copy, we cannot optimize struct.1's get lower down. - (struct.set $struct 1 - (ref.null $struct) - (struct.get $other 1 - (ref.null $other) - ) - ) - (drop - (struct.get $struct 1 - (ref.null $struct) - ) - ) - ) -) - -;; Test of a near-copy, of a different index. -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) (field (mut i32)) data)) - (type $struct (struct (mut i32) (mut i32))) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ;; As this is not a copy, we cannot optimize struct.0's get lower down. - (struct.set $struct 0 - (ref.null $struct) - (struct.get $struct 1 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $global i32 (i32.const 42)) - (global $global i32 (i32.const 42)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - ;; An immutable global is the only thing written to this field, so we can - ;; propagate the value to the struct.get and replace it with a global.get. - (drop - (struct.new $struct - (global.get $global) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field i32) data)) - (type $struct (struct i32)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $global (mut i32) (i32.const 42)) - (global $global (mut i32) (i32.const 42)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - ;; As above, but the global is *not* immutable, so we cannot optimize. - (drop - (struct.new $struct - (global.get $global) - ) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $global i32 (i32.const 42)) - (global $global i32 (i32.const 42)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new $struct - (global.get $global) - ) - ) - ;; As above, but there is another set of the field. It is the same, though, - ;; so that is fine. Also, the struct's field is now mutable as well to allow - ;; that, and that also does not prevent optimization. - (struct.set $struct 0 - (ref.null $struct) - (global.get $global) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $global i32 (i32.const 42)) - (global $global i32 (i32.const 42)) - ;; CHECK: (global $global-2 i32 (i32.const 1337)) - (global $global-2 i32 (i32.const 1337)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (global.get $global-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new $struct - (global.get $global) - ) - ) - ;; As above, but set a different global, which prevents optimization. - (struct.set $struct 0 - (ref.null $struct) - (global.get $global-2) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $global i32 (i32.const 42)) - (global $global i32 (i32.const 42)) - ;; CHECK: (global $global-2 i32 (i32.const 1337)) - (global $global-2 i32 (i32.const 1337)) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop - (struct.new $struct - (global.get $global) - ) - ) - ;; As above, but set a constant, which means we are mixing constants with - ;; globals, which prevents the optimization. - (struct.set $struct 0 - (ref.null $struct) - (i32.const 1337) - ) - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - ) -) - -(module - ;; Test a global type other than i32. Arrays of structs are a realistic case - ;; as they are used to implement itables. - - ;; CHECK: (type $vtable (struct_subtype (field funcref) data)) - (type $vtable (struct funcref)) - - ;; CHECK: (type $itable (array_subtype (ref $vtable) data)) - (type $itable (array (ref $vtable))) - - ;; CHECK: (type $object (struct_subtype (field $itable (ref $itable)) data)) - (type $object (struct (field $itable (ref $itable)))) - - ;; CHECK: (type $none_=>_funcref (func_subtype (result funcref) func)) - - ;; CHECK: (global $global (ref $itable) (array.init_static $itable - ;; CHECK-NEXT: (struct.new $vtable - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new $vtable - ;; CHECK-NEXT: (ref.func $test) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: )) - (global $global (ref $itable) (array.init_static $itable - (struct.new $vtable - (ref.null func) - ) - (struct.new $vtable - (ref.func $test) - ) - )) - - ;; CHECK: (func $test (type $none_=>_funcref) (result funcref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $vtable 0 - ;; CHECK-NEXT: (array.get $itable - ;; CHECK-NEXT: (block (result (ref $itable)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $object) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test (result funcref) - (drop - (struct.new $object - (global.get $global) - ) - ) - ;; Realistic usage of an itable: read an item from it, then a func from - ;; that, and return the value (all verifying that the types are correct - ;; after optimization). Note how after optimization everything is lined up - ;; so that precompute-propagate can infer from the global.get the specific - ;; object the array.get is on, allowing us to emit a constant value for the - ;; outer struct.get in principle. - (struct.get $vtable 0 - (array.get $itable - (struct.get $object $itable - (ref.null $object) - ) - (i32.const 1) - ) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/coalesce-locals-eh.wast binaryen-99/test/lit/passes/coalesce-locals-eh.wast --- binaryen-108/test/lit/passes/coalesce-locals-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/coalesce-locals-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --coalesce-locals -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e (param)) - - ;; CHECK: (func $bar (result i32) - ;; CHECK-NEXT: (i32.const 1984) - ;; CHECK-NEXT: ) - (func $bar (result i32) - (i32.const 1984) - ) - - (tag $e) - ;; CHECK: (func $bug-cfg-traversal (param $0 i32) (result i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $bug-cfg-traversal (param $0 i32) (result i32) - (local $x i32) - ;; This is a regrssion test case for a bug in cfg-traversal for EH. - ;; See https://github.com/WebAssembly/binaryen/pull/3594 - (try - (do - (local.set $x - ;; the call may or may not throw, so we may reach the get of $x - (call $bar) - ) - ) - (catch_all - (unreachable) - ) - ) - (local.get $x) - ) -) diff -Nru binaryen-108/test/lit/passes/coalesce-locals-gc-nn.wast binaryen-99/test/lit/passes/coalesce-locals-gc-nn.wast --- binaryen-108/test/lit/passes/coalesce-locals-gc-nn.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/coalesce-locals-gc-nn.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --coalesce-locals -all --enable-gc-nn-locals -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (func $nn-locals (param $0 (ref any)) - ;; CHECK-NEXT: (local $1 ((ref any) (ref any))) - ;; CHECK-NEXT: (local $2 ((ref any) (ref any))) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nn-locals - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nn-locals - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nn-locals - ;; CHECK-NEXT: (tuple.extract 1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nn-locals - ;; CHECK-NEXT: (tuple.extract 1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nn-locals (param $any (ref any)) - ;; When computing interferences, coalesce locals should not error on tuples - ;; that contain non-nullable locals. - (local $x ((ref any) (ref any))) - (local $y ((ref any) (ref any))) - ;; Set values into the tuple locals and use them. - ;; Note that while the values are the same, we do not optimize them because - ;; of current limitations on tuple handling in this pass, so we are mainly - ;; testing for not crashing here. - (local.set $x - (tuple.make - (local.get $any) - (local.get $any) - ) - ) - (local.set $y - (tuple.make - (local.get $any) - (local.get $any) - ) - ) - (call $nn-locals - (tuple.extract 0 - (local.get $x) - ) - ) - (call $nn-locals - (tuple.extract 0 - (local.get $y) - ) - ) - (call $nn-locals - (tuple.extract 1 - (local.get $x) - ) - ) - (call $nn-locals - (tuple.extract 1 - (local.get $y) - ) - ) - ) - - ;; CHECK: (func $unreachable-get-of-non-nullable - ;; CHECK-NEXT: (local $0 (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-get-of-non-nullable - ;; One local is unused entirely, the other is used but only in unreachable - ;; code. It does not really matter what we do here (coalesce, or not), but we - ;; should emit valid IR. Normally we would apply a constant to replace the - ;; local.get, however, the types here are non-nullable, so we must do - ;; something else. - (local $unused (ref any)) - (local $used-in-unreachable (ref any)) - (unreachable) - (drop - (local.get $used-in-unreachable) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/coalesce-locals-gc.wast binaryen-99/test/lit/passes/coalesce-locals-gc.wast --- binaryen-108/test/lit/passes/coalesce-locals-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/coalesce-locals-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --coalesce-locals -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (type $array (array (mut i8))) - (type $array (array (mut i8))) - ;; CHECK: (global $global (ref null $array) (ref.null $array)) - (global $global (ref null $array) (ref.null $array)) - - ;; CHECK: (func $test-dead-get-non-nullable (param $0 dataref) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result dataref) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test-dead-get-non-nullable (param $func (ref data)) - (unreachable) - (drop - ;; A useless get (that does not read from any set, or from the inputs to the - ;; function). Normally we replace such gets with nops as best we can, but in - ;; this case the type is non-nullable, so we must leave it alone. - (local.get $func) - ) - ) - - ;; CHECK: (func $br_on_null (param $0 (ref null $array)) (result (ref null $array)) - ;; CHECK-NEXT: (block $label$1 (result (ref null $array)) - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (br $label$1 - ;; CHECK-NEXT: (br_on_null $label$2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_null (param $ref (ref null $array)) (result (ref null $array)) - (local $1 (ref null $array)) - (block $label$1 (result (ref null $array)) - (block $label$2 - (br $label$1 - ;; Test that we properly model the basic block connections around a - ;; BrOnNull. There should be a branch to $label$2, and also a fallthrough. - ;; As a result, the local.set below is reachable, and should not be - ;; eliminated (turned into a drop). - (br_on_null $label$2 - (local.get $ref) - ) - ) - ) - (local.set $1 - (global.get $global) - ) - (local.get $1) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/coalesce-locals-learning.wast binaryen-99/test/lit/passes/coalesce-locals-learning.wast --- binaryen-108/test/lit/passes/coalesce-locals-learning.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/coalesce-locals-learning.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1757 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --coalesce-locals-learning -S -o - | filecheck %s - -(module - (memory 10) - ;; CHECK: (type $2 (func)) - - ;; CHECK: (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - - ;; CHECK: (type $3 (func (param i32 f32))) - - ;; CHECK: (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - (type $2 (func)) - (type $3 (func (param i32 f32))) - ;; CHECK: (type $4 (func (param i32))) - (type $4 (func (param i32))) - (import $_emscripten_autodebug_i32 "env" "_emscripten_autodebug_i32" (param i32 i32) (result i32)) - ;; CHECK: (import "env" "_emscripten_autodebug_i32" (func $_emscripten_autodebug_i32 (param i32 i32) (result i32))) - - ;; CHECK: (memory $0 10) - - ;; CHECK: (func $nothing-to-do - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nothing-to-do (type $2) - (local $x i32) - (nop) - ) - ;; CHECK: (func $merge - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $merge (type $2) - (local $x i32) - (local $y i32) - (nop) - ) - ;; CHECK: (func $leave-type - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $leave-type (type $2) - (local $x i32) - (local $y f32) - (nop) - ) - ;; CHECK: (func $leave-interfere - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $leave-interfere (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $almost-interfere - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $almost-interfere (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - (local.set $y - (i32.const 0) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $redundant-copy - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $redundant-copy (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $ineffective-store - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ineffective-store (type $2) - (local $x i32) - (local.set $x - (i32.const 0) - ) - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $block - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block (type $2) - (local $x i32) - (block $block0 - (local.set $x - (i32.const 0) - ) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $see-both-sides - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $see-both-sides (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (block $block0 - (local.set $y - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $see-br-and-ignore-dead - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $see-br-and-ignore-dead (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (block $block - (br $block) - (local.set $y - (i32.const 0) - ) - (drop - (local.get $y) - ) - (local.set $x - (i32.const -1) - ) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $see-block-body - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $see-block-body (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (block $block - (local.set $y - (i32.const 1) - ) - (drop - (local.get $y) - ) - (br $block) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $zero-init - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-init (type $2) - (local $x i32) - (local $y i32) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $multi - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multi (type $2) - (local $x i32) - (local $y i32) - (local $z i32) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - ) - ;; CHECK: (func $if-else - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $if-else-parallel - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-parallel (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - ) - (block $block3 - (local.set $y - (i32.const 1) - ) - (drop - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $if-else-after - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-after (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-else-through - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-through (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - (if - (i32.const 0) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-through - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-through (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - (if - (i32.const 0) - (drop - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-through2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-through2 (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (if - (i32.const 0) - (local.set $y - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-through3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-through3 (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 1) - ) - (if - (i32.const 0) - (block $block1 - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $if2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if2 (type $2) - (local $x i32) - (local $y i32) - (if - (local.tee $x - (i32.const 1) - ) - (block $block1 - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $if3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if3 (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if4 (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - (local.set $y - (i32.const 1) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if5 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if5 (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (drop - (local.get $x) - ) - (local.set $y - (i32.const 1) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $loop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (loop $in - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop (type $2) - (local $x i32) - (local $y i32) - (block $out - (loop $in - (drop - (local.get $x) - ) - (local.set $x - (i32.const 0) - ) - (drop - (local.get $y) - ) - (br $in) - ) - ) - ) - ;; CHECK: (func $interfere-in-dead - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead (type $2) - (local $x i32) - (local $y i32) - (block $block - (br $block) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $interfere-in-dead2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead2 (type $2) - (local $x i32) - (local $y i32) - (block $block - (unreachable) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $interfere-in-dead3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead3 (type $2) - (local $x i32) - (local $y i32) - (block $block - (return) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $params (param $0 i32) (param $1 f32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $params (type $3) (param $p i32) (param $q f32) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - ) - ;; CHECK: (func $interfere-in-dead4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead4 (type $2) - (local $x i32) - (local $y i32) - (block $block - (br_if $block - (i32.const 0) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $switch - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $switch$def - ;; CHECK-NEXT: (block $switch-case$1 - ;; CHECK-NEXT: (block $switch-case$2 - ;; CHECK-NEXT: (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $switch (type $2) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (block $switch$def - (block $switch-case$1 - (block $switch-case$2 - (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def - (i32.const 100) - ) - (drop - (local.get $x) - ) - ) - (drop - (local.get $y) - ) - ) - (drop - (local.get $z) - ) - ) - (drop - (local.get $w) - ) - ) - ;; CHECK: (func $greedy-can-be-happy - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block5 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 103) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (block $block8 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 105) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block10 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 106) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 107) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (block $block13 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 108) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 109) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block15 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 110) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $greedy-can-be-happy (type $2) - (local $x1 i32) - (local $x2 i32) - (local $x3 i32) - (local $y1 i32) - (local $y2 i32) - (local $y3 i32) - (if - (i32.const 0) - (if - (i32.const 1) - (if - (i32.const 2) - (block $block3 - (local.set $x1 - (i32.const 100) - ) - (local.set $y2 - (i32.const 101) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y2) - ) - ) - (block $block5 - (local.set $x1 - (i32.const 102) - ) - (local.set $y3 - (i32.const 103) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y3) - ) - ) - ) - (if - (i32.const 3) - (block $block8 - (local.set $x2 - (i32.const 104) - ) - (local.set $y1 - (i32.const 105) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y1) - ) - ) - (block $block10 - (local.set $x2 - (i32.const 106) - ) - (local.set $y3 - (i32.const 107) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y3) - ) - ) - ) - ) - (if - (i32.const 4) - (block $block13 - (local.set $x3 - (i32.const 108) - ) - (local.set $y1 - (i32.const 109) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y1) - ) - ) - (block $block15 - (local.set $x3 - (i32.const 110) - ) - (local.set $y2 - (i32.const 111) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y2) - ) - ) - ) - ) - ) - ;; CHECK: (func $greedy-can-be-sad - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block5 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 103) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (block $block8 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 105) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block10 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 106) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 107) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (block $block13 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 108) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 109) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block15 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 110) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $greedy-can-be-sad (type $2) - (local $x1 i32) - (local $y1 i32) - (local $x2 i32) - (local $y2 i32) - (local $x3 i32) - (local $y3 i32) - (if - (i32.const 0) - (if - (i32.const 1) - (if - (i32.const 2) - (block $block3 - (local.set $x1 - (i32.const 100) - ) - (local.set $y2 - (i32.const 101) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y2) - ) - ) - (block $block5 - (local.set $x1 - (i32.const 102) - ) - (local.set $y3 - (i32.const 103) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y3) - ) - ) - ) - (if - (i32.const 3) - (block $block8 - (local.set $x2 - (i32.const 104) - ) - (local.set $y1 - (i32.const 105) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y1) - ) - ) - (block $block10 - (local.set $x2 - (i32.const 106) - ) - (local.set $y3 - (i32.const 107) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y3) - ) - ) - ) - ) - (if - (i32.const 4) - (block $block13 - (local.set $x3 - (i32.const 108) - ) - (local.set $y1 - (i32.const 109) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y1) - ) - ) - (block $block15 - (local.set $x3 - (i32.const 110) - ) - (local.set $y2 - (i32.const 111) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y2) - ) - ) - ) - ) - ) - ;; CHECK: (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4096) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block2 - ;; CHECK-NEXT: (block $while-out$0 - ;; CHECK-NEXT: (loop $while-in$1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $while-out$2 - ;; CHECK-NEXT: (loop $while-in$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block7 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $while-out$4 - ;; CHECK-NEXT: (loop $while-in$5 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block9 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_memcpy (type $FUNCSIG$iiii) (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32) - (local $i4 i32) - (if - (i32.ge_s - (local.get $i3) - (i32.const 4096) - ) - (drop - (local.get $i1) - ) - ) - (local.set $i4 - (local.get $i1) - ) - (if - (i32.eq - (i32.and - (local.get $i1) - (i32.const 3) - ) - (i32.and - (local.get $i2) - (i32.const 3) - ) - ) - (block $block2 - (block $while-out$0 - (loop $while-in$1 - (if - (i32.eqz - (i32.and - (local.get $i1) - (i32.const 3) - ) - ) - (br $while-out$0) - ) - (block $block4 - (if - (i32.eqz - (local.get $i3) - ) - (return - (local.get $i4) - ) - ) - (i32.store8 - (local.get $i1) - (i32.load8_s - (local.get $i2) - ) - ) - (local.set $i1 - (i32.add - (local.get $i1) - (i32.const 1) - ) - ) - (local.set $i2 - (i32.add - (local.get $i2) - (i32.const 1) - ) - ) - (local.set $i3 - (i32.sub - (local.get $i3) - (i32.const 1) - ) - ) - ) - (br $while-in$1) - ) - ) - (block $while-out$2 - (loop $while-in$3 - (if - (i32.eqz - (i32.ge_s - (local.get $i3) - (i32.const 4) - ) - ) - (br $while-out$2) - ) - (block $block7 - (i32.store - (local.get $i1) - (i32.load - (local.get $i2) - ) - ) - (local.set $i1 - (i32.add - (local.get $i1) - (i32.const 4) - ) - ) - (local.set $i2 - (i32.add - (local.get $i2) - (i32.const 4) - ) - ) - (local.set $i3 - (i32.sub - (local.get $i3) - (i32.const 4) - ) - ) - ) - (br $while-in$3) - ) - ) - ) - ) - (block $while-out$4 - (loop $while-in$5 - (if - (i32.eqz - (i32.gt_s - (local.get $i3) - (i32.const 0) - ) - ) - (br $while-out$4) - ) - (block $block9 - (i32.store8 - (local.get $i1) - (i32.load8_s - (local.get $i2) - ) - ) - (local.set $i1 - (i32.add - (local.get $i1) - (i32.const 1) - ) - ) - (local.set $i2 - (i32.add - (local.get $i2) - (i32.const 1) - ) - ) - (local.set $i3 - (i32.sub - (local.get $i3) - (i32.const 1) - ) - ) - ) - (br $while-in$5) - ) - ) - (return - (local.get $i4) - ) - ) - ;; CHECK: (func $this-is-effective-i-tell-you (param $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $this-is-effective-i-tell-you (type $4) (param $x i32) - (if - (i32.const -1) - (block $block1 - (if - (i32.const 0) - (nop) - ) - (local.set $x - (i32.const 1) - ) - ) - (nop) - ) - (drop - (local.get $x) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/coalesce-locals.wast binaryen-99/test/lit/passes/coalesce-locals.wast --- binaryen-108/test/lit/passes/coalesce-locals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/coalesce-locals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,3066 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --coalesce-locals -S -o - | filecheck %s - -(module - (memory 10) - ;; CHECK: (type $2 (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $4 (func (param i32))) - - ;; CHECK: (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - - ;; CHECK: (type $f64_i32_=>_i64 (func (param f64 i32) (result i64))) - - ;; CHECK: (type $3 (func (param i32 f32))) - - ;; CHECK: (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - (type $2 (func)) - (type $3 (func (param i32 f32))) - (type $4 (func (param i32))) - (import $_emscripten_autodebug_i32 "env" "_emscripten_autodebug_i32" (param i32 i32) (result i32)) - (import $get "env" "get" (result i32)) - (import $set "env" "set" (param i32)) - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $none_=>_f64 (func (result f64))) - - ;; CHECK: (import "env" "_emscripten_autodebug_i32" (func $_emscripten_autodebug_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "get" (func $get (result i32))) - - ;; CHECK: (import "env" "set" (func $set (param i32))) - - ;; CHECK: (memory $0 10) - - ;; CHECK: (func $nothing-to-do - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nothing-to-do (type $2) - (local $x i32) - (nop) - ) - ;; CHECK: (func $merge - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $merge (type $2) - (local $x i32) - (local $y i32) - (nop) - ) - ;; CHECK: (func $leave-type - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $leave-type (type $2) - (local $x i32) - (local $y f32) - (nop) - ) - ;; CHECK: (func $leave-interfere - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $leave-interfere (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $almost-interfere - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $almost-interfere (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - (local.set $y - (i32.const 0) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $redundant-copy - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $redundant-copy (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $ineffective-store - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ineffective-store (type $2) - (local $x i32) - (local.set $x - (i32.const 0) - ) - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $block - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block (type $2) - (local $x i32) - (block $block0 - (local.set $x - (i32.const 0) - ) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $see-both-sides - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $see-both-sides (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (block $block0 - (local.set $y - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $see-br-and-ignore-dead - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $see-br-and-ignore-dead (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (block $block - (br $block) - (local.set $y - (i32.const 0) - ) - (drop - (local.get $y) - ) - (local.set $x - (i32.const -1) - ) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $see-block-body - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $see-block-body (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (block $block - (local.set $y - (i32.const 1) - ) - (drop - (local.get $y) - ) - (br $block) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $zero-init - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-init (type $2) - (local $x i32) - (local $y i32) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $multi - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multi (type $2) - (local $x i32) - (local $y i32) - (local $z i32) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - ) - ;; CHECK: (func $if-else - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $if-else-parallel - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-parallel (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - ) - (block $block3 - (local.set $y - (i32.const 1) - ) - (drop - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $if-else-after - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-after (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-else-through - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-through (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - (if - (i32.const 0) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-through - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-through (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (i32.const 1) - ) - (if - (i32.const 0) - (drop - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-through2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-through2 (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 0) - ) - (if - (i32.const 0) - (local.set $y - (i32.const 1) - ) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if-through3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-through3 (type $2) - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 1) - ) - (if - (i32.const 0) - (block $block1 - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $if2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if2 (type $2) - (local $x i32) - (local $y i32) - (if - (local.tee $x - (i32.const 1) - ) - (block $block1 - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $if3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if3 (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if4 (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - (local.set $y - (i32.const 1) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if5 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if5 (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - ;; These locals can be coalesced together: $x's live range ends here, - ;; and $y's begins right after it, so they do not have an overlap with - ;; a different value. - (drop - (local.get $x) - ) - (local.set $y - (i32.const 1) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $if5-flip - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if5-flip (type $2) - (local $x i32) - (local $y i32) - (if - (i32.const 0) - (block $block1 - ;; As above, but flipping these two instructions causes a conflict. - (local.set $y - (i32.const 1) - ) - (drop - (local.get $x) - ) - ) - ) - (drop - (local.get $y) - ) - ) - ;; CHECK: (func $loop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (loop $in - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop (type $2) - (local $x i32) - (local $y i32) - (loop $in - (drop - (local.get $x) - ) - (local.set $x - (i32.const 0) - ) - (drop - (local.get $y) - ) - (br $in) - ) - ) - ;; CHECK: (func $interfere-in-dead - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead (type $2) - (local $x i32) - (local $y i32) - (block $block - (br $block) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $interfere-in-dead2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead2 (type $2) - (local $x i32) - (local $y i32) - (block $block - (unreachable) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $interfere-in-dead3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead3 (type $2) - (local $x i32) - (local $y i32) - (block $block - (return) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $params (param $0 i32) (param $1 f32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $params (type $3) (param $p i32) (param $q f32) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - ) - ;; CHECK: (func $interfere-in-dead4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $interfere-in-dead4 (type $2) - (local $x i32) - (local $y i32) - (block $block - (br_if $block - (i32.const 0) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - ) - ;; CHECK: (func $switch - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $switch$def - ;; CHECK-NEXT: (block $switch-case$1 - ;; CHECK-NEXT: (block $switch-case$2 - ;; CHECK-NEXT: (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $switch (type $2) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (block $switch$def - (block $switch-case$1 - (block $switch-case$2 - (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def - (i32.const 100) - ) - (drop - (local.get $x) - ) - ) - (drop - (local.get $y) - ) - ) - (drop - (local.get $z) - ) - ) - (drop - (local.get $w) - ) - ) - ;; CHECK: (func $greedy-can-be-happy - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block5 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 103) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (block $block8 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 105) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block10 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 106) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 107) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (block $block13 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 108) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 109) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block15 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 110) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $greedy-can-be-happy (type $2) - (local $x1 i32) - (local $x2 i32) - (local $x3 i32) - (local $y1 i32) - (local $y2 i32) - (local $y3 i32) - (if - (i32.const 0) - (if - (i32.const 1) - (if - (i32.const 2) - (block $block3 - (local.set $x1 - (i32.const 100) - ) - (local.set $y2 - (i32.const 101) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y2) - ) - ) - (block $block5 - (local.set $x1 - (i32.const 102) - ) - (local.set $y3 - (i32.const 103) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y3) - ) - ) - ) - (if - (i32.const 3) - (block $block8 - (local.set $x2 - (i32.const 104) - ) - (local.set $y1 - (i32.const 105) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y1) - ) - ) - (block $block10 - (local.set $x2 - (i32.const 106) - ) - (local.set $y3 - (i32.const 107) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y3) - ) - ) - ) - ) - (if - (i32.const 4) - (block $block13 - (local.set $x3 - (i32.const 108) - ) - (local.set $y1 - (i32.const 109) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y1) - ) - ) - (block $block15 - (local.set $x3 - (i32.const 110) - ) - (local.set $y2 - (i32.const 111) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y2) - ) - ) - ) - ) - ) - ;; CHECK: (func $greedy-can-be-sad - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block5 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 103) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (block $block8 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 105) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block10 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 106) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 107) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (block $block13 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 108) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 109) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block15 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 110) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $greedy-can-be-sad (type $2) - (local $x1 i32) - (local $y1 i32) - (local $x2 i32) - (local $y2 i32) - (local $x3 i32) - (local $y3 i32) - (if - (i32.const 0) - (if - (i32.const 1) - (if - (i32.const 2) - (block $block3 - (local.set $x1 - (i32.const 100) - ) - (local.set $y2 - (i32.const 101) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y2) - ) - ) - (block $block5 - (local.set $x1 - (i32.const 102) - ) - (local.set $y3 - (i32.const 103) - ) - (drop - (local.get $x1) - ) - (drop - (local.get $y3) - ) - ) - ) - (if - (i32.const 3) - (block $block8 - (local.set $x2 - (i32.const 104) - ) - (local.set $y1 - (i32.const 105) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y1) - ) - ) - (block $block10 - (local.set $x2 - (i32.const 106) - ) - (local.set $y3 - (i32.const 107) - ) - (drop - (local.get $x2) - ) - (drop - (local.get $y3) - ) - ) - ) - ) - (if - (i32.const 4) - (block $block13 - (local.set $x3 - (i32.const 108) - ) - (local.set $y1 - (i32.const 109) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y1) - ) - ) - (block $block15 - (local.set $x3 - (i32.const 110) - ) - (local.set $y2 - (i32.const 111) - ) - (drop - (local.get $x3) - ) - (drop - (local.get $y2) - ) - ) - ) - ) - ) - ;; CHECK: (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4096) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block2 - ;; CHECK-NEXT: (block $while-out$0 - ;; CHECK-NEXT: (loop $while-in$1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $while-out$2 - ;; CHECK-NEXT: (loop $while-in$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block7 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $while-out$4 - ;; CHECK-NEXT: (loop $while-in$5 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block9 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_memcpy (type $FUNCSIG$iiii) (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32) - (local $i4 i32) - (if - (i32.ge_s - (local.get $i3) - (i32.const 4096) - ) - (drop - (local.get $i1) - ) - ) - (local.set $i4 - (local.get $i1) - ) - (if - (i32.eq - (i32.and - (local.get $i1) - (i32.const 3) - ) - (i32.and - (local.get $i2) - (i32.const 3) - ) - ) - (block $block2 - (block $while-out$0 - (loop $while-in$1 - (if - (i32.eqz - (i32.and - (local.get $i1) - (i32.const 3) - ) - ) - (br $while-out$0) - ) - (block $block4 - (if - (i32.eqz - (local.get $i3) - ) - (return - (local.get $i4) - ) - ) - (i32.store8 - (local.get $i1) - (i32.load8_s - (local.get $i2) - ) - ) - (local.set $i1 - (i32.add - (local.get $i1) - (i32.const 1) - ) - ) - (local.set $i2 - (i32.add - (local.get $i2) - (i32.const 1) - ) - ) - (local.set $i3 - (i32.sub - (local.get $i3) - (i32.const 1) - ) - ) - ) - (br $while-in$1) - ) - ) - (block $while-out$2 - (loop $while-in$3 - (if - (i32.eqz - (i32.ge_s - (local.get $i3) - (i32.const 4) - ) - ) - (br $while-out$2) - ) - (block $block7 - (i32.store - (local.get $i1) - (i32.load - (local.get $i2) - ) - ) - (local.set $i1 - (i32.add - (local.get $i1) - (i32.const 4) - ) - ) - (local.set $i2 - (i32.add - (local.get $i2) - (i32.const 4) - ) - ) - (local.set $i3 - (i32.sub - (local.get $i3) - (i32.const 4) - ) - ) - ) - (br $while-in$3) - ) - ) - ) - ) - (block $while-out$4 - (loop $while-in$5 - (if - (i32.eqz - (i32.gt_s - (local.get $i3) - (i32.const 0) - ) - ) - (br $while-out$4) - ) - (block $block9 - (i32.store8 - (local.get $i1) - (i32.load8_s - (local.get $i2) - ) - ) - (local.set $i1 - (i32.add - (local.get $i1) - (i32.const 1) - ) - ) - (local.set $i2 - (i32.add - (local.get $i2) - (i32.const 1) - ) - ) - (local.set $i3 - (i32.sub - (local.get $i3) - (i32.const 1) - ) - ) - ) - (br $while-in$5) - ) - ) - (return - (local.get $i4) - ) - ) - ;; CHECK: (func $this-is-effective-i-tell-you (param $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $this-is-effective-i-tell-you (type $4) (param $x i32) - (if - (i32.const -1) - (block $block1 - (if - (i32.const 0) - (nop) - ) - (local.set $x - (i32.const 1) - ) - ) - (nop) - ) - (drop - (local.get $x) - ) - ) - ;; CHECK: (func $prefer-remove-copies1 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $prefer-remove-copies1 (type $2) - (local $y i32) - (local $z i32) - (local $x i32) - (local.set $x - (i32.const 0) - ) - (local.set $y - (local.get $x) - ) - (local.set $z - (i32.const 1) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - ) - ;; CHECK: (func $prefer-remove-copies2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $prefer-remove-copies2 (type $2) - (local $y i32) - (local $z i32) - (local $x i32) - (local.set $x - (i32.const 0) - ) - (local.set $z - (local.get $x) - ) - (local.set $y - (i32.const 1) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - ) - ;; CHECK: (func $in-unreachable - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $x - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $y - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $z - ;; CHECK-NEXT: (br $z) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $z14 - ;; CHECK-NEXT: (br_table $z14 $z14 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable - (local $a i32) - (block $x - (return) - (local.set $a (i32.const 1)) - (drop (local.get $a)) - (local.set $a (local.get $a)) - ) - (block $y - (unreachable) - (local.set $a (i32.const 1)) - (drop (local.get $a)) - (local.set $a (local.get $a)) - ) - (block $z - (br $z) - (local.set $a (i32.const 1)) - (drop (local.get $a)) - (local.set $a (local.get $a)) - ) - (block $z - (br_table $z $z - (i32.const 100) - ) - (local.set $a (i32.const 1)) - (drop (local.get $a)) - (local.set $a (local.get $a)) - ) - ) - ;; CHECK: (func $nop-in-unreachable - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nop-in-unreachable - (local $x i32) - (block - (unreachable) - (i32.store - (local.get $x) - (local.tee $x (i32.const 0)) - ) - ) - ) - ;; CHECK: (func $loop-backedge - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (loop $while-in7 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $set - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $get) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br $while-in7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-backedge - (local $0 i32) ;; loop phi - (local $1 i32) ;; value for next loop iteration - (local $2 i32) ;; a local that might be merged with with $1, perhaps making us prefer it to removing a backedge copy - (local.set $0 - (i32.const 2) - ) - (block $out - (loop $while-in7 - (local.set $2 (i32.const 0)) ;; 2 interferes with 0 - (call $set (local.get $2)) - (local.set $1 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (if (call $get) - (local.set $2 (local.get $1)) ;; copy for 1/2 - ) - (br_if $out (local.get $2)) - (local.set $1 (i32.const 100)) - (local.set $0 (local.get $1)) ;; copy for 1/0, with extra weight should win the tie - (br $while-in7) - ) - ) - ) - ;; CHECK: (func $if-copy1 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (loop $top - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $top) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-copy1 - (local $x i32) - (local $y i32) - (loop $top - (local.set $x - (if (result i32) - (i32.const 1) - (local.get $x) - (local.get $y) - ) - ) - (drop (local.get $x)) - (drop (local.get $y)) - (br $top) - ) - ) - ;; CHECK: (func $if-copy2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (loop $top - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $top) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-copy2 - (local $x i32) - (local $y i32) - (loop $top - (local.set $x - (if (result i32) - (i32.const 1) - (local.get $y) - (local.get $x) - ) - ) - (drop (local.get $x)) - (drop (local.get $y)) - (br $top) - ) - ) - ;; CHECK: (func $if-copy3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (loop $top - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $top) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-copy3 - (local $x i32) - (local $y i32) - (loop $top - (local.set $x - (if (result i32) - (i32.const 1) - (unreachable) - (local.get $x) - ) - ) - (drop (local.get $x)) - (drop (local.get $y)) - (br $top) - ) - ) - ;; CHECK: (func $if-copy4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (loop $top - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $top) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-copy4 - (local $x i32) - (local $y i32) - (loop $top - (local.set $x - (if (result i32) - (i32.const 1) - (unreachable) - (local.get $y) - ) - ) - (drop (local.get $x)) - (drop (local.get $y)) - (br $top) - ) - ) - ;; CHECK: (func $if-copy-tee - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (loop $top - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $top) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-copy-tee - (local $x i32) - (local $y i32) - (loop $top - (drop - (local.tee $x - (if (result i32) - (i32.const 1) - (local.get $x) - (i32.const 2) - ) - ) - ) - (drop (local.get $x)) - (drop (local.get $y)) - (br $top) - ) - ) - ;; CHECK: (func $tee_br (param $0 i32) (result i32) - ;; CHECK-NEXT: (block $b - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (br $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $tee_br (param $x i32) (result i32) - (block $b - (return - (local.tee $x - (br $b) - ) - ) - ) - (i32.const 1) - ) - ;; CHECK: (func $unused-tee-with-child-if-no-else (param $0 i32) - ;; CHECK-NEXT: (loop $label$0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (br $label$0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unused-tee-with-child-if-no-else (param $0 i32) - (loop $label$0 - (drop - (local.tee $0 - (if - (br $label$0) - (nop) - ) - ) - ) - ) - ) - ;; CHECK: (func $tee_if_with_unreachable_else (param $0 f64) (param $1 i32) (result i64) - ;; CHECK-NEXT: (call $tee_if_with_unreachable_else - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (if (result f64) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.lt - ;; CHECK-NEXT: (f64.const -128) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $tee_if_with_unreachable_else (param $0 f64) (param $1 i32) (result i64) - (call $tee_if_with_unreachable_else - (local.tee $0 - (if (result f64) - (local.get $1) - (local.get $0) - (unreachable) - ) - ) - (f64.lt - (f64.const -128) - (local.get $0) - ) - ) - ) - ;; CHECK: (func $tee_if_with_unreachable_true (param $0 f64) (param $1 i32) (result i64) - ;; CHECK-NEXT: (call $tee_if_with_unreachable_else - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (if (result f64) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.lt - ;; CHECK-NEXT: (f64.const -128) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $tee_if_with_unreachable_true (param $0 f64) (param $1 i32) (result i64) - (call $tee_if_with_unreachable_else - (local.tee $0 - (if (result f64) - (local.get $1) - (unreachable) - (local.get $0) - ) - ) - (f64.lt - (f64.const -128) - (local.get $0) - ) - ) - ) - ;; CHECK: (func $pick - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $pick - (local $x i32) - (local $y i32) - (local.set $x (local.get $y)) - (if (i32.const 1) - (local.set $x (i32.const 1)) - ) - (local.set $x (local.get $y)) - (local.set $x (local.get $y)) - ) - ;; CHECK: (func $pick-2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $pick-2 - (local $x i32) - (local $y i32) - (local.set $y (local.get $x)) - (if (i32.const 1) - (local.set $y (i32.const 1)) - ) - (local.set $y (local.get $x)) - (local.set $y (local.get $x)) - ) - ;; CHECK: (func $many - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $many - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $y (local.get $x)) - (local.set $z (local.get $y)) - (local.set $w (local.get $z)) - (local.set $x (local.get $z)) - (if (i32.const 1) - (local.set $y (i32.const 1)) - ) - (local.set $x (local.get $z)) - (if (i32.const 1) - (local.set $y (i32.const 1)) - ) - (local.set $y (local.get $x)) - (local.set $z (local.get $y)) - (local.set $w (local.get $z)) - (local.set $z (i32.const 2)) - (local.set $x (local.get $z)) - (if (i32.const 1) - (local.set $y (i32.const 1)) - ) - (local.set $y (local.get $x)) - (local.set $z (local.get $y)) - (local.set $w (local.get $z)) - (local.set $z (i32.const 2)) - (local.set $x (local.get $w)) - ) - ;; CHECK: (func $loop-copies (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-copies (param $x i32) (param $y i32) - (loop $loop - (local.set $x (local.get $y)) - (local.set $y (local.get $x)) - (br_if $loop (local.get $x)) - ) - ) - ;; CHECK: (func $proper-type (result f64) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $proper-type (result f64) - (local $var$0 i32) - (local $var$2 f64) - (local.set $var$0 - (select - (i32.const 0) - (i32.const 1) - (local.get $var$0) - ) - ) - (local.tee $var$2 ;; the locals will be reordered, this should be the f64 - (local.get $var$2) - ) - ) - ;; CHECK: (func $reuse-param (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $reuse-param (param $x i32) (param $y i32) (result i32) - (local $temp i32) - (i32.add - (local.tee $temp - (i32.xor - (i32.shr_s - (i32.shl - (local.get $x) ;; $x and $temp do not interfere - (i32.const 16) - ) - (i32.const 16) - ) - (i32.shr_s - (i32.shl - (local.get $y) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ) - (local.get $temp) - ) - ) - - ;; CHECK: (func $copies-do-not-interfere (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $copies-do-not-interfere (result i32) - (local $0 i32) - (local $1 i32) - (local.set $0 - (i32.const 100) - ) - ;; The two locals are copies, and so they do not interfere, even though - ;; their live ranges overlap and there is a set of one of them in that - ;; overlap. We can coalesce them together to a single local. - (local.set $1 - (local.get $0) - ) - (drop - (local.get $0) - ) - (local.get $1) - ) - - ;; CHECK: (func $tee-copies-do-not-interfere (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $tee-copies-do-not-interfere (result i32) - (local $0 i32) - (local $1 i32) - ;; Similar to the above, but now the copying is done using a tee. - (local.set $1 - (local.tee $0 - (i32.const 100) - ) - ) - (drop - (local.get $0) - ) - (local.get $1) - ) - - ;; CHECK: (func $multiple-tee-copies-do-not-interfere (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $multiple-tee-copies-do-not-interfere (result i32) - (local $0 i32) - (local $1 i32) - (local $2 i32) - ;; Similar to the above, but a chain of 3 items. - (local.set $2 - (local.tee $1 - (local.tee $0 - (i32.const 100) - ) - ) - ) - (drop - (local.get $0) - ) - (drop - (local.get $1) - ) - (local.get $2) - ) - - ;; CHECK: (func $copies-and-then-interfere (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $copies-and-then-interfere (result i32) - (local $0 i32) - (local $1 i32) - (local.set $0 - (i32.const 100) - ) - (local.set $1 - (local.get $0) - ) - (drop - (local.get $0) - ) - (drop - (local.get $1) - ) - ;; The copy before this set should not confuse us - this set causes a - ;; divergence on the overlapping live ranges, and we cannot coalesce these - ;; two locals. - (local.set $1 - (i32.const 123) - ) - (drop - (local.get $0) - ) - (local.get $1) - ) - - ;; CHECK: (func $copies-and-then-set-without-interfering (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $copies-and-then-set-without-interfering (result i32) - (local $0 i32) - (local $1 i32) - (local.set $0 - (i32.const 100) - ) - (local.set $1 - (local.get $0) - ) - (drop - (local.get $0) - ) - (drop - (local.get $1) - ) - ;; Similar to the above, but now $0's live range has ended (there is no get - ;; of it at the point of this set), and so there is no interference, and - ;; these locals can be coalesced. - (local.set $1 - (i32.const 123) - ) - (local.get $1) - ) - - ;; CHECK: (func $copy-third-party (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $copy-third-party (result i32) - (local $0 i32) - (local $1 i32) - (local $2 i32) - ;; $2 begins with a value, which is copied to $0 and $1. None of these - ;; interfere and they can all be coalesced. - (local.set $2 - (i32.const 100) - ) - (local.set $1 - (local.get $2) - ) - (local.set $0 - (local.get $2) - ) - (drop - (local.get $0) - ) - (drop - (local.get $1) - ) - (local.get $2) - ) - - ;; CHECK: (func $ineffective-set (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - (func $ineffective-set (result i32) - (local $0 i32) - (local $1 i32) - (local $2 i32) - (local.set $0 - ;; This set of $2 is ineffective in that there are no gets of $2, but the - ;; value does flow through to the outer set, and we must notice that. In - ;; particular, we must see that $0 and $1 conflict, and cannot be coalesced - ;; together ($1 is alive from the zero init to the very end, and so $0's - ;; set means it diverges). - (local.tee $2 - (i32.const 100) - ) - ) - (drop - (local.get $0) - ) - (local.get $1) - ) - - ;; CHECK: (func $inter-block-copy (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - (func $inter-block-copy (result i32) - (local $0 i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local.set $0 - (i32.const 100) - ) - (local.set $1 - (local.get $0) - ) - (local.set $2 - (local.get $0) - ) - ;; At this point $1 is equal to $2, as they are both copies of $0. Then the - ;; if assigns one of them to $3, which means that $3 is also equal to them - ;; all. However, we only analyze copied values *inside* blocks, which means - ;; that in each of the if arms we see that $3 is assigned either the value - ;; of $1 or $2, but we don't know that those values are both equal to $0. As - ;; a result, we will infer that $3 interfers with $0, as their live ranges - ;; overlap and $3 is assigned a value that looks different than $0. This - ;; will prevent $3 being coalesced with all the others. (However, see the - ;; next testcase for more on this.) - (if - (local.get $0) - (local.set $3 - (local.get $1) - ) - (local.set $3 - (local.get $2) - ) - ) - (drop - (local.get $0) - ) - (drop - (local.get $1) - ) - (drop - (local.get $2) - ) - (local.get $3) - ) - - ;; CHECK: (func $inter-block-copy-second-pass (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $inter-block-copy-second-pass (result i32) - (local $0 i32) - (local $1 i32) - ;; This function contains the output of the previous testcase - ;; $inter-block-copy, and shows what running a second pass results in. After - ;; the first pass we have coalesced the original $0, $1, and $2 into a single - ;; local ($0), and renamed the original $3 into $1. At this point the - ;; algorithm can see that $0 and $1 do not interfere: there are no copies in - ;; the middle, and in both if arms when we assign a value to $1 it is the - ;; value already in $0, and there is no other assignment of either one that - ;; appears in their overlapping live ranges, so they will be coalesced into - ;; a single local. - (local.set $0 - (i32.const 100) - ) - (nop) - (nop) - (if - (local.get $0) - (local.set $1 - (local.get $0) - ) - (local.set $1 - (local.get $0) - ) - ) - (drop - (local.get $0) - ) - (drop - (local.get $0) - ) - (drop - (local.get $0) - ) - (local.get $1) - ) - - ;; CHECK: (func $equal-constants-zeroinit - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $equal-constants-zeroinit - (local $x i32) - (local $y i32) - ;; $x and $y both have the zero init value, which is identical, and they do - ;; not interfere. - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - - ;; CHECK: (func $equal-constants - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $equal-constants - (local $x i32) - (local $y i32) - ;; $x is written the same value as $y, so they do not interfere. - (local.set $x - (i32.const 0) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - - ;; CHECK: (func $different-constants - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $different-constants - (local $x i32) - (local $y i32) - ;; $x is written a different value, so they do interfere. - (local.set $x - (i32.const 1) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - - ;; CHECK: (func $equal-constants-nonzero - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $equal-constants-nonzero - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 42) - ) - (local.set $y - (i32.const 42) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - - ;; CHECK: (func $different-constants-nonzero - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $different-constants-nonzero - (local $x i32) - (local $y i32) - (local.set $x - (i32.const 42) - ) - (local.set $y - (i32.const 1337) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/code-folding-eh.wast binaryen-99/test/lit/passes/code-folding-eh.wast --- binaryen-108/test/lit/passes/code-folding-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/code-folding-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names --code-folding -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (tag $e-i32 (param i32)) - (tag $e-i32 (param i32)) - - ;; CHECK: (func $pop-test - ;; CHECK-NEXT: (block $folding-inner0 - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 222) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 333) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $pop-test - (try - (do - (try - (do) - (catch $e-i32 - ;; Expressions containing a pop should NOT be taken out and folded. - (drop (pop i32)) - (drop (i32.const 111)) - (drop (i32.const 222)) - (drop (i32.const 333)) - (unreachable) - ) - ) - ) - (catch $e-i32 - (drop (pop i32)) - (drop (i32.const 111)) - (drop (i32.const 222)) - (drop (i32.const 333)) - (unreachable) - ) - ) - ) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo) - - ;; CHECK: (func $try-call-optimize-terminating-tails (result i32) - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $try-call-optimize-terminating-tails (result i32) - (try - (do - ;; Expressions that can throw should NOT be taken out of 'try' scope. - (call $foo) - (call $foo) - (call $foo) - (call $foo) - (return (i32.const 0)) - ) - (catch_all - (call $foo) - (call $foo) - (call $foo) - (call $foo) - (return (i32.const 0)) - ) - ) - (i32.const 0) - ) - - ;; CHECK: (func $try-call-optimize-expression-tails - ;; CHECK-NEXT: (block $x - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (br $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (br $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-call-optimize-expression-tails - (block $x - (try - (do - ;; Expressions that can throw should NOT be taken out of 'try' scope. - (call $foo) - (call $foo) - (call $foo) - (br $x) - ) - (catch_all - (call $foo) - (call $foo) - (call $foo) - (br $x) - ) - ) - (unreachable) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/code-folding_enable-threads.wast binaryen-99/test/lit/passes/code-folding_enable-threads.wast --- binaryen-108/test/lit/passes/code-folding_enable-threads.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/code-folding_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,433 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --code-folding --enable-threads -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_f32 (func (result f32))) - - ;; CHECK: (type $13 (func (param f32))) - (type $13 (func (param f32))) - (table 282 282 funcref) - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - ;; CHECK: (table $0 282 282 funcref) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (call_indirect (type $13) - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (br $label$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 105) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (block $label$1 - (if - (i32.const 1) - (block $label$3 - (call_indirect (type $13) - (block $label$4 (result f32) ;; but this type may change dangerously - (nop) ;; fold this - (br $label$3) - ) - (i32.const 105) - ) - (nop) ;; with this - ) - ) - ) - ) - ;; CHECK: (func $negative-zero (result f32) - ;; CHECK-NEXT: (if (result f32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $label$0 (result f32) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$1 (result f32) - ;; CHECK-NEXT: (f32.const -0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $negative-zero (result f32) - (if (result f32) - (i32.const 0) - (block $label$0 (result f32) - (f32.const 0) - ) - (block $label$1 (result f32) - (f32.const -0) - ) - ) - ) - ;; CHECK: (func $negative-zero-b (result f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$0 (result f32) - ;; CHECK-NEXT: (f32.const -0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $negative-zero-b (result f32) - (if (result f32) - (i32.const 0) - (block $label$0 (result f32) - (f32.const -0) - ) - (block $label$1 (result f32) - (f32.const -0) - ) - ) - ) - ;; CHECK: (func $negative-zero-c (result f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$0 (result f32) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $negative-zero-c (result f32) - (if (result f32) - (i32.const 0) - (block $label$0 (result f32) - (f32.const 0) - ) - (block $label$1 (result f32) - (f32.const 0) - ) - ) - ) - ;; CHECK: (func $break-target-outside-of-return-merged-code - ;; CHECK-NEXT: (block $label$A - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (block $label$B - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_table $label$A $label$B - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block2 - ;; CHECK-NEXT: (block $label$C - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_table $label$A $label$C - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $break-target-outside-of-return-merged-code - (block $label$A - (if - (unreachable) - (block - (block - (block $label$B - (if - (unreachable) - (br_table $label$A $label$B - (unreachable) - ) - ) - ) - (return) - ) - ) - (block - (block $label$C - (if - (unreachable) - (br_table $label$A $label$C ;; this all looks mergeable, but $label$A is outside - (unreachable) - ) - ) - ) - (return) - ) - ) - ) - ) - ;; CHECK: (func $break-target-inside-all-good - ;; CHECK-NEXT: (block $folding-inner0 - ;; CHECK-NEXT: (block $label$A - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block $block4 - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block6 - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$B - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_table $label$B $label$B - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - (func $break-target-inside-all-good - (block $label$A - (if - (unreachable) - (block - (block - (block $label$B - (if - (unreachable) - (br_table $label$B $label$B - (unreachable) - ) - ) - ) - (return) - ) - ) - (block - (block $label$C - (if - (unreachable) - (br_table $label$C $label$C ;; this all looks mergeable, and is, B ~~ C - (unreachable) - ) - ) - ) - (return) - ) - ) - ) - ) - ;; CHECK: (func $leave-inner-block-type - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $leave-inner-block-type - (block $label$1 - (drop - (block $label$2 (result i32) ;; leave this alone (otherwise, if we make it unreachable, we need to do more updating) - (br_if $label$2 - (unreachable) - (unreachable) - ) - (drop - (i32.const 1) - ) - (br $label$1) - ) - ) - (drop - (i32.const 1) - ) - ) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (memory $0 (shared 1 1)) - (memory $0 (shared 1 1)) - ;; CHECK: (export "func_2224" (func $0)) - (export "func_2224" (func $0)) - ;; CHECK: (func $0 (result i32) - ;; CHECK-NEXT: (local $var$0 i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.load offset=22 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.atomic.load offset=22 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (result i32) - (local $var$0 i32) - (if (result i32) - (i32.const 0) - (i32.load offset=22 - (local.get $var$0) - ) - (i32.atomic.load offset=22 - (local.get $var$0) - ) - ) - ) -) -(module - ;; CHECK: (type $0 (func)) - (type $0 (func)) - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) - (global $global$0 (mut i32) (i32.const 10)) - ;; CHECK: (func $determinism - ;; CHECK-NEXT: (block $folding-inner0 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (br $folding-inner0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global$0 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $determinism (; 0 ;) (type $0) - (block $label$1 - (br_if $label$1 - (i32.const 1) - ) - (global.set $global$0 - (i32.sub - (global.get $global$0) - (i32.const 1) - ) - ) - (unreachable) - ) - (block $label$2 - (br_if $label$2 - (i32.const 0) - ) - (if - (global.get $global$0) - (block - (global.set $global$0 - (i32.sub - (global.get $global$0) - (i32.const 1) - ) - ) - (unreachable) - ) - ) - (unreachable) - ) - (if - (global.get $global$0) - (block - (global.set $global$0 - (i32.sub - (global.get $global$0) - (i32.const 1) - ) - ) - (unreachable) - ) - ) - (unreachable) - ) - ;; CHECK: (func $careful-of-the-switch (param $0 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block $label$5 - ;; CHECK-NEXT: (block $label$7 - ;; CHECK-NEXT: (br_table $label$3 $label$7 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$8 - ;; CHECK-NEXT: (br_table $label$3 $label$8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $careful-of-the-switch (param $0 i32) - (block $label$1 - (block $label$3 - (block $label$5 - (block $label$7 ;; this is block is equal to $label$8 when accounting for the internal 7/8 difference - (br_table $label$3 $label$7 ;; the reference to $label$3 must remain valid, cannot hoist out of it! - (i32.const 0) - ) - ) - (br $label$1) - ) - (block $label$8 - (br_table $label$3 $label$8 - (i32.const 0) - ) - ) - (br $label$1) - ) - (unreachable) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/code-pushing-eh.wast binaryen-99/test/lit/passes/code-pushing-eh.wast --- binaryen-108/test/lit/passes/code-pushing-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/code-pushing-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,325 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --code-pushing -all -S -o - | filecheck %s - -;; The tests in this file test EffectAnalyzer, which is used by CodePushing. - -(module - ;; CHECK: (tag $e (param i32)) - (tag $e (param i32)) - - ;; CHECK: (func $cannot-push-past-call - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $cannot-push-past-call) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $cannot-push-past-call - (local $x i32) - (block $out - ;; This local.set cannot be pushed down, because the call below can throw - (local.set $x (i32.const 1)) - (call $cannot-push-past-call) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - - ;; CHECK: (func $cannot-push-past-throw - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $cannot-push-past-throw - (local $x i32) - (block $out - ;; This local.set cannot be pushed down, because there is 'throw' below - (local.set $x (i32.const 1)) - (throw $e (i32.const 0)) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - - ;; CHECK: (func $can-push-past-try - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $can-push-past-try - (local $x i32) - (block $out - ;; This local.set can be pushed down, because the 'throw' below is going - ;; to be caught by the inner catch_all - (local.set $x (i32.const 1)) - (try - (do - (throw $e (i32.const 0)) - ) - (catch_all) - ) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo) - - ;; CHECK: (func $cannot-push-past-try - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $cannot-push-past-try - (local $x i32) - (block $out - ;; This local.set cannot be pushed down, because the exception thrown by - ;; 'call $foo' below may not be caught by 'catch $e' - (local.set $x (i32.const 1)) - (try - (do - (call $foo) - ) - (catch $e - (drop (pop i32)) - ) - ) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - - ;; CHECK: (func $cannot-push-past-rethrow-within-catch - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (rethrow $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $cannot-push-past-rethrow-within-catch - (local $x i32) - (block $out - ;; This local.set cannot be pushed down, because there is 'rethrow' within - ;; the inner catch_all - (local.set $x (i32.const 1)) - (try $l0 - (do - (throw $e (i32.const 0)) - ) - (catch_all - (rethrow $l0) - ) - ) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - - ;; CHECK: (func $can-push-past-try-delegate - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (try $l - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $can-push-past-try-delegate - (local $x i32) - (block $out - ;; This local.set can be pushed down, because the 'throw' below is going - ;; to be caught by the catch_all - (local.set $x (i32.const 1)) - (try $l - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate $l) - ) - ) - (catch_all) - ) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - - ;; CHECK: (func $cannot-push-past-try-delegate - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (try $l - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $cannot-push-past-try-delegate - (local $x i32) - (block $out - ;; This local.set cannot be pushed down, because the 'delegate' bypasses - ;; the catch_all, making the whole 'try' throwable. - (local.set $x (i32.const 1)) - (try $l - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate 2) - ) - ) - (catch_all) - ) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/code-pushing_ignore-implicit-traps.wast binaryen-99/test/lit/passes/code-pushing_ignore-implicit-traps.wast --- binaryen-108/test/lit/passes/code-pushing_ignore-implicit-traps.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/code-pushing_ignore-implicit-traps.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,715 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --code-pushing --ignore-implicit-traps -S -o - | filecheck %s - -(module - (memory 1) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (memory $0 1) - - ;; CHECK: (func $push1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push1 - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $push2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push2 - (local $x i32) - (local $y i32) - (block $out - (local.set $x (i32.const 1)) - (local.set $y (i32.const 3)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - ) - ;; CHECK: (func $push1-twice - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push1-twice - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - (br_if $out (i32.const 3)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $push1-twiceb - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push1-twiceb - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - (nop) - (br_if $out (i32.const 3)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $push2-twice - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push2-twice - (local $x i32) - (local $y i32) - (block $out - (local.set $x (i32.const 1)) - (local.set $y (i32.const 3)) - (br_if $out (i32.const 2)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - ) - ;; CHECK: (func $ignore-last - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ignore-last - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - ) - ) - ;; CHECK: (func $ignore-last2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ignore-last2 - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (nop) - (nop) - (br_if $out (i32.const 2)) - ) - ) - ;; CHECK: (func $push-if - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push-if - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (if (i32.const 2) (nop)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $push-dropped (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push-dropped (result i32) - (local $x i32) - (block $out (result i32) - (local.set $x (i32.const 1)) - (drop (br_if $out (i32.const 2) (i32.const 3))) - (drop (local.get $x)) - (i32.const 4) - ) - ) - ;; CHECK: (func $push-past-stuff - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (call $push-past-stuff) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $push-past-stuff - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (call $push-past-stuff) - (drop (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $fail-then-push - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fail-then-push - (local $x i32) - (local $y i32) - (block $out - (local.set $x (i32.const 1)) - (drop (local.get $x)) - (br_if $out (i32.const 2)) - (local.set $y (i32.const 1)) - (br_if $out (i32.const 3)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - ) - ;; and now for stuff that should *not* be pushed - ;; CHECK: (func $used - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $used - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (local.get $x)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $not-sfa - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $not-sfa - (local $x i32) - (local.set $x (i32.const 1)) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $not-sfa2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $not-sfa2 - (local $x i32) - (drop (local.get $x)) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $used-out - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $used-out - (local $x i32) - (block $out - (local.set $x (i32.const 1)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - (drop (local.get $x)) - ) - ;; CHECK: (func $value-might-interfere - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $value-might-interfere ;; but doesn't - (local $x i32) - (block $out - (local.set $x (i32.load (i32.const 0))) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $value-interferes - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $value-interferes - (local $x i32) - (block $out - (local.set $x (i32.load (i32.const 0))) - (i32.store (i32.const 1) (i32.const 3)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $value-interferes-accumulation - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $value-interferes-accumulation - (local $x i32) - (block $out - (local.set $x (i32.load (i32.const 0))) - (nop) - (i32.store (i32.const 1) (i32.const 3)) - (nop) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $value-interferes-in-pushpoint - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $value-interferes) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $value-interferes-in-pushpoint - (local $x i32) - (block $out - (local.set $x (i32.load (i32.const 0))) - (if (i32.const 1) - (call $value-interferes) - ) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $values-might-interfere - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $values-might-interfere ;; they don't, as we keep the order - but here their side effects prevent pushing - (local $x i32) - (local $y i32) - (block $out - (local.set $x (call $push-dropped)) - (local.set $y (call $push-dropped)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - ) - ;; CHECK: (func $unpushed-interferes - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unpushed-interferes - (local $x i32) - (local $y i32) - (block $out - (local.set $x (call $push-dropped)) - (local.set $y (call $push-dropped)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - (drop (local.get $y)) ;; $y can't be pushed, so x can't be - ) - ;; CHECK: (func $unpushed-ignorable - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unpushed-ignorable - (local $x i32) - (local $y i32) - (block $out - (local.set $x (i32.const 1)) - (local.set $y (i32.const 3)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - (drop (local.get $x)) ;; $x can't be pushed, but y doesn't care - ) - ;; CHECK: (func $unpushed-ignorable-side-effect - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unpushed-ignorable-side-effect - (local $x i32) - (local $y i32) - (block $out - (local.set $x (call $push-dropped)) ;; $x can't be pushed, but y doesn't care - (local.set $y (i32.const 3)) - (br_if $out (i32.const 2)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - ) - ;; CHECK: (func $unpushed-side-effect-into-drop - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unpushed-side-effect-into-drop - (local $x i32) - (block $out - (local.set $x (call $push-dropped)) - (br_if $out (i32.const 1)) - (drop (local.get $x)) - ) - ) - ;; CHECK: (func $unpushed-side-effect-into-if - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $push-dropped) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unpushed-side-effect-into-if - (local $x i32) - (block $out - (local.set $x (call $push-dropped)) - (br_if $out (i32.const 1)) - (if - (local.get $x) - (nop) - ) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/const-hoisting.wast binaryen-99/test/lit/passes/const-hoisting.wast --- binaryen-108/test/lit/passes/const-hoisting.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/const-hoisting.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,834 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --const-hoisting -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $10-of-each - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1048575) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const -8193) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const -1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const -1048577) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8191) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $10-of-each - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - (drop (i32.const 0)) ;; 1 byte - (drop (i32.const 63)) ;; 1 byte - (drop (i32.const 64)) ;; 2 bytes - (drop (i32.const 8191)) ;; 2 bytes - (drop (i32.const 8192)) ;; 3 bytes - (drop (i32.const 1048575)) ;; 3 bytes - (drop (i32.const 1048576)) ;; 4 bytes - (drop (i32.const -64)) ;; 1 byte - (drop (i32.const -65)) ;; 2 bytes - (drop (i32.const -8192)) ;; 2 bytes - (drop (i32.const -8193)) ;; 3 bytes - (drop (i32.const -1048576)) ;; 3 bytes - (drop (i32.const -1048577)) ;; 4 bytes - ) - ;; CHECK: (func $floats-10-times - ;; CHECK-NEXT: (local $0 f32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $floats-10-times - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - (drop (f32.const 0)) ;; 4 bytes - (drop (f64.const 0)) ;; 8 bytes - ) - ;; CHECK: (func $too-few - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $too-few - (drop (i32.const 8192)) ;; 3 bytes, need 6 appearances - (drop (i32.const 8192)) - (drop (i32.const 8192)) - (drop (i32.const 8192)) - (drop (i32.const 8192)) - ) - ;; CHECK: (func $just-enough - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $just-enough - (drop (i32.const 8192)) ;; 3 bytes, need 6 appearances - (drop (i32.const 8192)) - (drop (i32.const 8192)) - (drop (i32.const 8192)) - (drop (i32.const 8192)) - (drop (i32.const 8192)) - ) - ;; CHECK: (func $too-few-b - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $too-few-b - (drop (i32.const 1048576)) ;; 4 bytes, need 4 appearances - (drop (i32.const 1048576)) - (drop (i32.const 1048576)) - ) - ;; CHECK: (func $enough-b - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $enough-b - (drop (i32.const 1048576)) ;; 4 bytes, need 4 appearances - (drop (i32.const 1048576)) - (drop (i32.const 1048576)) - (drop (i32.const 1048576)) - ) - ;; CHECK: (func $too-few-c - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $too-few-c - (drop (f32.const 0)) ;; 4 bytes, need 4 appearances - (drop (f32.const 0)) - (drop (f32.const 0)) - ) - ;; CHECK: (func $enough-c - ;; CHECK-NEXT: (local $0 f32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $enough-c - (drop (f32.const 0)) ;; 4 bytes, need 4 appearances - (drop (f32.const 0)) - (drop (f32.const 0)) - (drop (f32.const 0)) - ) - ;; CHECK: (func $too-few-d - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $too-few-d - (drop (f64.const 0)) ;; 8 bytes, need 2 appearances - ) - ;; CHECK: (func $enough-d - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $enough-d - (drop (f64.const 0)) ;; 4 bytes, need 4 appearances - (drop (f64.const 0)) - ) -) - diff -Nru binaryen-108/test/lit/passes/dae_all-features.wast binaryen-99/test/lit/passes/dae_all-features.wast --- binaryen-108/test/lit/passes/dae_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dae_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,652 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --dae --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $f64_=>_none (func (param f64))) - - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $a9 $c8) - - ;; CHECK: (export "a8" (func $a8)) - (export "a8" (func $a8)) - (table 2 2 funcref) - (elem (i32.const 0) $a9 $c8) - ;; CHECK: (func $a - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $a (param $x i32)) - ;; CHECK: (func $b - ;; CHECK-NEXT: (call $a) - ;; CHECK-NEXT: ) - (func $b - (call $a (i32.const 1)) ;; best case scenario - ) - ;; CHECK: (func $a1 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $a1 (param $x i32) - (unreachable) - ) - ;; CHECK: (func $b1 - ;; CHECK-NEXT: (call $a1) - ;; CHECK-NEXT: ) - (func $b1 - (call $a1 (i32.const 2)) ;; same value in both, so works - ) - ;; CHECK: (func $b11 - ;; CHECK-NEXT: (call $a1) - ;; CHECK-NEXT: ) - (func $b11 - (call $a1 (i32.const 2)) - ) - ;; CHECK: (func $a2 (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a2 (param $x i32) - (drop (local.get $x)) - ) - ;; CHECK: (func $b2 - ;; CHECK-NEXT: (call $a2 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b2 - (call $a2 (i32.const 3)) ;; different value! - ) - ;; CHECK: (func $b22 - ;; CHECK-NEXT: (call $a2 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b22 - (call $a2 (i32.const 4)) - ) - ;; CHECK: (func $a3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a3 (param $x i32) - (drop (i32.const -1)) ;; diff value, but at least unused, so no need to send - ) - ;; CHECK: (func $b3 - ;; CHECK-NEXT: (call $a3) - ;; CHECK-NEXT: ) - (func $b3 - (call $a3 (i32.const 3)) - ) - ;; CHECK: (func $b33 - ;; CHECK-NEXT: (call $a3) - ;; CHECK-NEXT: ) - (func $b33 - (call $a3 (i32.const 4)) - ) - ;; CHECK: (func $a4 (param $x i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $a4 (param $x i32) ;; diff value, but with effects - ) - ;; CHECK: (func $b4 - ;; CHECK-NEXT: (call $a4 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b4 - (call $a4 (unreachable)) - ) - ;; CHECK: (func $b43 - ;; CHECK-NEXT: (call $a4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b43 - (call $a4 (i32.const 4)) - ) - ;; CHECK: (func $a5 - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a5 (param $x i32) (param $y f64) ;; optimize two - (drop (local.get $x)) - (drop (local.get $y)) - ) - ;; CHECK: (func $b5 - ;; CHECK-NEXT: (call $a5) - ;; CHECK-NEXT: ) - (func $b5 - (call $a5 (i32.const 1) (f64.const 3.14159)) - ) - ;; CHECK: (func $a6 (param $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a6 (param $x i32) (param $y f64) ;; optimize just one - (drop (local.get $x)) - (drop (local.get $y)) - ) - ;; CHECK: (func $b6 - ;; CHECK-NEXT: (call $a6 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b6 - (call $a6 (unreachable) (f64.const 3.14159)) - ) - ;; CHECK: (func $a7 (param $0 f64) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a7 (param $x i32) (param $y f64) ;; optimize just the other one - (drop (local.get $x)) - (drop (local.get $y)) - ) - ;; CHECK: (func $b7 - ;; CHECK-NEXT: (call $a7 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b7 - (call $a7 (i32.const 1) (unreachable)) - ) - ;; CHECK: (func $a8 (param $x i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $a8 (param $x i32)) ;; exported, do not optimize - ;; CHECK: (func $b8 - ;; CHECK-NEXT: (call $a8 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b8 - (call $a8 (i32.const 1)) - ) - ;; CHECK: (func $a9 (param $x i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $a9 (param $x i32)) ;; tabled, do not optimize - ;; CHECK: (func $b9 - ;; CHECK-NEXT: (call $a9 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b9 - (call $a9 (i32.const 1)) - ) - ;; CHECK: (func $a10 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $a10) - ;; CHECK-NEXT: (call $a10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a10 (param $x i32) ;; recursion - (call $a10 (i32.const 1)) - (call $a10 (i32.const 1)) - ) - ;; CHECK: (func $a11 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (call $a11) - ;; CHECK-NEXT: (call $a11) - ;; CHECK-NEXT: ) - (func $a11 (param $x i32) ;; partially successful recursion - (call $a11 (i32.const 1)) - (call $a11 (i32.const 2)) - ) - ;; CHECK: (func $a12 (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $a12 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $a12 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a12 (param $x i32) ;; unsuccessful recursion - (drop (local.get $x)) - (call $a12 (i32.const 1)) - (call $a12 (i32.const 2)) - ) - ;; return values - ;; CHECK: (func $c1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (call $c2) - ;; CHECK-NEXT: (call $c3) - ;; CHECK-NEXT: (call $c3) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $c4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $c4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $c5 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $c6) - ;; CHECK-NEXT: (call $c7) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $c8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $c1 - (local $x i32) - (drop (call $c2)) - (drop (call $c3)) - (drop (call $c3)) - (drop (call $c4)) - (local.set $x (call $c4)) - (drop (call $c5 (unreachable))) - (drop (call $c6)) - (drop (call $c7)) - (drop (call $c8)) - ) - ;; CHECK: (func $c2 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $c2 (result i32) - (i32.const 1) - ) - ;; CHECK: (func $c3 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $c3 (result i32) - (i32.const 2) - ) - ;; CHECK: (func $c4 (result i32) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - (func $c4 (result i32) - (i32.const 3) - ) - ;; CHECK: (func $c5 (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $c5 (param $x i32) (result i32) - (local.get $x) - ) - ;; CHECK: (func $c6 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $c6 (result i32) - (unreachable) - ) - ;; CHECK: (func $c7 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - (func $c7 (result i32) - (return (i32.const 4)) - ) - ;; CHECK: (func $c8 (result i32) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - (func $c8 (result i32) - (i32.const 5) - ) -) -(module ;; both operations at once: remove params and return value - (func "a" - (drop - (call $b - (i32.const 1) - ) - ) - ) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (export "a" (func $0)) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (call $b) - ;; CHECK-NEXT: ) - - ;; CHECK: (func $b - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b (param $x i32) (result i32) - (local.get $x) - ) -) -(module ;; tail calls inhibit dropped result removal - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (func $foo (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (return_call $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - (func $foo (param $x i32) (result i32) - (drop - (return_call $bar - (i32.const 0) - ) - ) - (i32.const 42) - ) - ;; CHECK: (func $bar (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (result i32) - (i32.const 7) - ) -) -(module ;; indirect tail calls inhibit dropped result removal - ;; CHECK: (type $T (func (result i32))) - (type $T (func (result i32))) - (table 1 1 funcref) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (table $0 1 1 funcref) - - ;; CHECK: (func $foo (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (return_call_indirect $0 (type $T) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (param $x i32) (result i32) - (drop - (return_call_indirect (type $T) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $bar - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar - (drop - (call $foo - (i32.const 42) - ) - ) - ) -) -(module - ;; CHECK: (type $funcref_i32_f64_=>_i64 (func (param funcref i32 f64) (result i64))) - - ;; CHECK: (type $f32_=>_funcref (func (param f32) (result funcref))) - - ;; CHECK: (elem declare func $0) - - ;; CHECK: (export "export" (func $1)) - - ;; CHECK: (func $0 (param $0 funcref) (param $1 i32) (param $2 f64) (result i64) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $0 (param $0 funcref) (param $1 i32) (param $2 f64) (result i64) - (nop) - (unreachable) - ) - (func "export" (param $0 f32) (result funcref) - ;; a ref.func should prevent us from changing the type of a function, as it - ;; may escape - (ref.func $0) - ) -) -;; CHECK: (func $1 (param $0 f32) (result funcref) -;; CHECK-NEXT: (ref.func $0) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i64 (func (param i64))) - (type $i64 (func (param i64))) - ;; CHECK: (global $global$0 (ref $i64) (ref.func $0)) - (global $global$0 (ref $i64) (ref.func $0)) - ;; CHECK: (export "even" (func $1)) - (export "even" (func $1)) - ;; the argument to this function cannot be removed due to the ref.func of it - ;; in a global - ;; CHECK: (func $0 (param $0 i64) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $0 (param $0 i64) - (unreachable) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $1 - (call_ref - (i64.const 0) - (global.get $global$0) - ) - ) - ;; CHECK: (func $2 - ;; CHECK-NEXT: (call $0 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $2 - (call $0 - (i64.const 0) - ) - ) -) -(module - ;; a removable non-nullable parameter - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (local $0 (ref null i31)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $0 (param $x i31ref) - (nop) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (call $0) - ;; CHECK-NEXT: ) - (func $1 - (call $0 - (i31.new (i32.const 0)) - ) - ) -) - -;; Arguments that read an immutable global can be optimized, as that is a -;; constant value. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (global $immut i32 (i32.const 42)) - (global $immut i32 (i32.const 42)) - - ;; CHECK: (global $immut2 i32 (i32.const 43)) - (global $immut2 i32 (i32.const 43)) - - ;; CHECK: (global $mut (mut i32) (i32.const 1337)) - (global $mut (mut i32) (i32.const 1337)) - - ;; CHECK: (func $foo (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (global.get $immut) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (param $x i32) (param $y i32) - ;; "Use" the params to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $y)) - ) - - ;; CHECK: (func $foo-caller - ;; CHECK-NEXT: (global.set $mut - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (global.get $mut) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $mut - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (global.get $mut) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo-caller - ;; Note how the mutable param has a different value in each call, which shows - ;; the reason that we cannot optimize in this case. But we can optimize the - ;; immutable param. - (global.set $mut (i32.const 1)) - (call $foo - (global.get $immut) - (global.get $mut) - ) - (global.set $mut (i32.const 2)) - (call $foo - (global.get $immut) - (global.get $mut) - ) - ) - - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (drop (local.get $x)) - (drop (local.get $y)) - ) - - ;; CHECK: (func $bar-caller - ;; CHECK-NEXT: (global.set $mut - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (global.get $immut) - ;; CHECK-NEXT: (global.get $immut) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $mut - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (global.get $mut) - ;; CHECK-NEXT: (global.get $immut2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar-caller - ;; Corner cases of mixing mutable with immutable and mixing two immutables. - (global.set $mut (i32.const 1)) - (call $bar - (global.get $immut) - (global.get $immut) - ) - (global.set $mut (i32.const 2)) - (call $bar - (global.get $mut) - (global.get $immut2) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/dae-gc-refine-params.wast binaryen-99/test/lit/passes/dae-gc-refine-params.wast --- binaryen-108/test/lit/passes/dae-gc-refine-params.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dae-gc-refine-params.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,622 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --dae -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --dae --nominal -S -o - | filecheck %s --check-prefix NOMNL - -(module - ;; CHECK: (type ${i32} (struct (field i32))) - ;; NOMNL: (type ${} (struct_subtype data)) - - ;; NOMNL: (type ${i32} (struct_subtype (field i32) ${})) - (type ${i32} (struct_subtype (field i32) ${})) - - ;; CHECK: (type ${} (struct )) - (type ${} (struct)) - - ;; CHECK: (type ${i32_i64} (struct (field i32) (field i64))) - ;; NOMNL: (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) - (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) - - ;; CHECK: (type ${i32_f32} (struct (field i32) (field f32))) - - ;; CHECK: (type ${f64} (struct (field f64))) - ;; NOMNL: (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) - - ;; NOMNL: (type ${f64} (struct_subtype (field f64) ${})) - (type ${f64} (struct_subtype (field f64) ${})) - - (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) - - ;; CHECK: (func $call-various-params-no - ;; CHECK-NEXT: (call $various-params-no - ;; CHECK-NEXT: (call $get_{}) - ;; CHECK-NEXT: (call $get_{i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $various-params-no - ;; CHECK-NEXT: (call $get_{i32}) - ;; CHECK-NEXT: (call $get_{f64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-various-params-no (type $none_=>_none) - ;; NOMNL-NEXT: (call $various-params-no - ;; NOMNL-NEXT: (call $get_{}) - ;; NOMNL-NEXT: (call $get_{i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $various-params-no - ;; NOMNL-NEXT: (call $get_{i32}) - ;; NOMNL-NEXT: (call $get_{f64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-various-params-no - ;; The first argument gets {} and {i32}; the second {i32} and {f64}; none of - ;; those pairs can be optimized. Note that we do not pass in all nulls, as - ;; all nulls are identical and we could do other optimization work due to - ;; that. - (call $various-params-no - (call $get_{}) - (call $get_{i32}) - ) - (call $various-params-no - (call $get_{i32}) - (call $get_{f64}) - ) - ) - ;; This function is called in ways that do not allow us to alter the types of - ;; its parameters (see last function). - ;; CHECK: (func $various-params-no (param $x (ref null ${})) (param $y (ref null ${})) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $various-params-no (type $ref?|${}|_ref?|${}|_=>_none) (param $x (ref null ${})) (param $y (ref null ${})) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $various-params-no (param $x (ref null ${})) (param $y (ref null ${})) - ;; "Use" the locals to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $y)) - ) - - ;; CHECK: (func $get_{} (result (ref null ${})) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get_{} (type $none_=>_ref?|${}|) (result (ref null ${})) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $get_{} (result (ref null ${})) - (unreachable) - ) - ;; CHECK: (func $get_{i32} (result (ref null ${i32})) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get_{i32} (type $none_=>_ref?|${i32}|) (result (ref null ${i32})) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $get_{i32} (result (ref null ${i32})) - (unreachable) - ) - ;; CHECK: (func $get_{f64} (result (ref null ${f64})) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get_{f64} (type $none_=>_ref?|${f64}|) (result (ref null ${f64})) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $get_{f64} (result (ref null ${f64})) - (unreachable) - ) - - ;; CHECK: (func $call-various-params-yes - ;; CHECK-NEXT: (call $various-params-yes - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $various-params-yes - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $get_null_{i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-various-params-yes (type $none_=>_none) - ;; NOMNL-NEXT: (call $various-params-yes - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $various-params-yes - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (call $get_null_{i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-various-params-yes - ;; The first argument gets {i32} and {i32}; the second {i32} and {i32_i64}; - ;; both of those pairs can be optimized to {i32}. - ;; There is also an i32 in the middle, which should not confuse us. - (call $various-params-yes - (call $get_null_{i32}) - (i32.const 0) - (call $get_null_{i32}) - ) - (call $various-params-yes - (call $get_null_{i32}) - (i32.const 1) - (call $get_null_{i32_i64}) - ) - ) - ;; This function is called in ways that *do* allow us to alter the types of - ;; its parameters (see last function). - ;; CHECK: (func $various-params-yes (param $x (ref null ${i32})) (param $i i32) (param $y (ref null ${i32})) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $various-params-yes (type $ref?|${i32}|_i32_ref?|${i32}|_=>_none) (param $x (ref null ${i32})) (param $i i32) (param $y (ref null ${i32})) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $i) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $various-params-yes (param $x (ref null ${})) (param $i i32) (param $y (ref null ${})) - ;; "Use" the locals to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $i)) - (drop (local.get $y)) - ) - - ;; CHECK: (func $call-various-params-set - ;; CHECK-NEXT: (call $various-params-set - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $various-params-set - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: (call $get_null_{i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-various-params-set (type $none_=>_none) - ;; NOMNL-NEXT: (call $various-params-set - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $various-params-set - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: (call $get_null_{i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-various-params-set - ;; The first argument gets {i32} and {i32}; the second {i32} and {i32_i64; - ;; both of those pairs can be optimized to {i32} - (call $various-params-set - (call $get_null_{i32}) - (call $get_null_{i32}) - ) - (call $various-params-set - (call $get_null_{i32}) - (call $get_null_{i32_i64}) - ) - ) - ;; This function is called in ways that *do* allow us to alter the types of - ;; its parameters (see last function), however, we reuse the parameters by - ;; writing to them, which causes problems in one case. - ;; CHECK: (func $various-params-set (param $x (ref null ${i32})) (param $y (ref null ${i32})) - ;; CHECK-NEXT: (local $2 (ref null ${})) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (call $get_null_{i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $various-params-set (type $ref?|${i32}|_ref?|${i32}|_=>_none) (param $x (ref null ${i32})) (param $y (ref null ${i32})) - ;; NOMNL-NEXT: (local $2 (ref null ${})) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (ref.null ${}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $y - ;; NOMNL-NEXT: (call $get_null_{i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $various-params-set (param $x (ref null ${})) (param $y (ref null ${})) - ;; "Use" the locals to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $y)) - ;; Write to $x a value that will not fit in the refined type, which will - ;; force us to do a fixup: the param will get the new type, and a new local - ;; will stay at the old type, and we will use that local throughout the - ;; function. - (local.set $x (ref.null ${})) - (drop - (local.get $x) - ) - ;; Write to $y in a way that does not cause any issue, and we should not do - ;; any fixup while we refine the type. - (local.set $y (call $get_null_{i32_i64})) - (drop - (local.get $y) - ) - ) - - ;; CHECK: (func $call-various-params-tee - ;; CHECK-NEXT: (call $various-params-tee - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-various-params-tee (type $none_=>_none) - ;; NOMNL-NEXT: (call $various-params-tee - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-various-params-tee - ;; The argument gets {i32}, which allows us to refine. - (call $various-params-tee - (call $get_null_{i32}) - ) - ) - ;; CHECK: (func $various-params-tee (param $x (ref null ${i32})) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result (ref null ${i32})) - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (call $get_null_{i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $various-params-tee (type $ref?|${i32}|_=>_none) (param $x (ref null ${i32})) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block $block (result (ref null ${i32})) - ;; NOMNL-NEXT: (local.tee $x - ;; NOMNL-NEXT: (call $get_null_{i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $various-params-tee (param $x (ref null ${})) - ;; "Use" the locals to avoid other optimizations kicking in. - (drop (local.get $x)) - ;; Write to $x in a way that allows us to make the type more specific. We - ;; must also update the type of the tee (if we do not, a validation error - ;; would occur), and that will also cause the block's type to update as well. - (drop - (block (result (ref null ${})) - (local.tee $x (call $get_null_{i32_i64})) - ) - ) - ) - - ;; CHECK: (func $call-various-params-null - ;; CHECK-NEXT: (call $various-params-null - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null ${i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $get_null_{i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $various-params-null - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null ${i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null ${i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-various-params-null (type $none_=>_none) - ;; NOMNL-NEXT: (call $various-params-null - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null ${i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $get_null_{i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $various-params-null - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null ${i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null ${i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-various-params-null - ;; The first argument gets non-null values, allowing us to refine it. The - ;; second gets only one. - (call $various-params-null - (ref.as_non_null (ref.null ${i32})) - (call $get_null_{i32}) - ) - (call $various-params-null - (ref.as_non_null (ref.null ${i32})) - (ref.as_non_null (ref.null ${i32})) - ) - ) - ;; This function is called in ways that allow us to make the first parameter - ;; non-nullable. - ;; CHECK: (func $various-params-null (param $x (ref ${i32})) (param $y (ref null ${i32})) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $various-params-null (type $ref|${i32}|_ref?|${i32}|_=>_none) (param $x (ref ${i32})) (param $y (ref null ${i32})) - ;; NOMNL-NEXT: (local $temp i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (local.get $temp) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $various-params-null (param $x (ref null ${})) (param $y (ref null ${})) - (local $temp i32) - ;; "Use" the locals to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $y)) - ;; Use a local in this function as well, which should be ignored by this pass - ;; (when we scan and update all local.gets and sets, we should only do so on - ;; parameters, and not vars - and we can crash if we scan/update things we - ;; should not). - (local.set $temp (local.get $temp)) - ) - - ;; CHECK: (func $call-various-params-middle - ;; CHECK-NEXT: (call $various-params-middle - ;; CHECK-NEXT: (call $get_null_{i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $various-params-middle - ;; CHECK-NEXT: (call $get_null_{i32_f32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-various-params-middle (type $none_=>_none) - ;; NOMNL-NEXT: (call $various-params-middle - ;; NOMNL-NEXT: (call $get_null_{i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $various-params-middle - ;; NOMNL-NEXT: (call $get_null_{i32_f32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-various-params-middle - ;; The argument gets {i32_i64} and {i32_f32}. This allows us to refine from - ;; {} to {i32}, a type "in the middle". - (call $various-params-middle - (call $get_null_{i32_i64}) - ) - (call $various-params-middle - (call $get_null_{i32_f32}) - ) - ) - ;; CHECK: (func $various-params-middle (param $x (ref null ${i32})) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $various-params-middle (type $ref?|${i32}|_=>_none) (param $x (ref null ${i32})) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $various-params-middle (param $x (ref null ${})) - ;; "Use" the local to avoid other optimizations kicking in. - (drop (local.get $x)) - ) - - ;; CHECK: (func $unused-and-refinable - ;; CHECK-NEXT: (local $0 (ref null data)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unused-and-refinable (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 (ref null data)) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $unused-and-refinable (param $0 dataref) - ;; This function does not use $0. It is called with ${}, so it is also - ;; a parameter whose type we can refine. Do not do both operations: instead, - ;; just remove it because it is ignored, without altering the type (handling - ;; both operations would introduce some corner cases, and it just isn't worth - ;; handling them if the param is completely unused anyhow). We should see in - ;; the test output that the local $0 (the unused param) becomes a local - ;; because it is unused, and that local does *not* have its type refined to - ;; ${} (it will however be changed to be nullable, which it must be as a - ;; local). - ) - - ;; CHECK: (func $call-unused-and-refinable - ;; CHECK-NEXT: (call $unused-and-refinable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-unused-and-refinable (type $none_=>_none) - ;; NOMNL-NEXT: (call $unused-and-refinable) - ;; NOMNL-NEXT: ) - (func $call-unused-and-refinable - (call $unused-and-refinable - (struct.new_default ${}) - ) - ) - - ;; CHECK: (func $non-nullable-fixup (param $0 (ref ${})) - ;; CHECK-NEXT: (local $1 (ref null data)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $non-nullable-fixup (type $ref|${}|_=>_none) (param $0 (ref ${})) - ;; NOMNL-NEXT: (local $1 (ref null data)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $non-nullable-fixup (param $0 dataref) - ;; Use the param to avoid other opts removing it, and to force us to do a - ;; fixup when we refine the param's type. When doing so, we must handle the - ;; fact that the new local's type is non-nullable. - (local.set $0 - (local.get $0) - ) - ) - - ;; CHECK: (func $call-non-nullable-fixup - ;; CHECK-NEXT: (call $non-nullable-fixup - ;; CHECK-NEXT: (struct.new_default ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-non-nullable-fixup (type $none_=>_none) - ;; NOMNL-NEXT: (call $non-nullable-fixup - ;; NOMNL-NEXT: (struct.new_default ${}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-non-nullable-fixup - (call $non-nullable-fixup - (struct.new_default ${}) - ) - ) - - ;; CHECK: (func $call-update-null - ;; CHECK-NEXT: (call $update-null - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $update-null - ;; CHECK-NEXT: (struct.new_default ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-update-null (type $none_=>_none) - ;; NOMNL-NEXT: (call $update-null - ;; NOMNL-NEXT: (ref.null ${}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $update-null - ;; NOMNL-NEXT: (struct.new_default ${}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-update-null - ;; Call a function with one of the parameters a null of a type that we can - ;; update in order to get a better LUB. - (call $update-null - (ref.null any) - ) - (call $update-null - (struct.new_default ${}) - ) - ) - - ;; CHECK: (func $update-null (param $x (ref null ${})) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $update-null (type $ref?|${}|_=>_none) (param $x (ref null ${})) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $update-null (param $x (ref null any)) - ;; "Use" the param to avoid other optimizations kicking in. We should only - ;; see the type of the param refined to a null ${} after updating the null - ;; in the caller. - (drop (local.get $x)) - ) - - ;; CHECK: (func $get_null_{i32} (result (ref null ${i32})) - ;; CHECK-NEXT: (ref.null ${i32}) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get_null_{i32} (type $none_=>_ref?|${i32}|) (result (ref null ${i32})) - ;; NOMNL-NEXT: (ref.null ${i32}) - ;; NOMNL-NEXT: ) - (func $get_null_{i32} (result (ref null ${i32})) - ;; Helper function that returns a null value of ${i32}. We use this instead of - ;; a direct ref.null because those can be rewritten by LUBFinder. - (ref.null ${i32}) - ) - - ;; CHECK: (func $get_null_{i32_i64} (result (ref null ${i32_i64})) - ;; CHECK-NEXT: (ref.null ${i32_i64}) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get_null_{i32_i64} (type $none_=>_ref?|${i32_i64}|) (result (ref null ${i32_i64})) - ;; NOMNL-NEXT: (ref.null ${i32_i64}) - ;; NOMNL-NEXT: ) - (func $get_null_{i32_i64} (result (ref null ${i32_i64})) - (ref.null ${i32_i64}) - ) - - ;; CHECK: (func $get_null_{i32_f32} (result (ref null ${i32_f32})) - ;; CHECK-NEXT: (ref.null ${i32_f32}) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get_null_{i32_f32} (type $none_=>_ref?|${i32_f32}|) (result (ref null ${i32_f32})) - ;; NOMNL-NEXT: (ref.null ${i32_f32}) - ;; NOMNL-NEXT: ) - (func $get_null_{i32_f32} (result (ref null ${i32_f32})) - (ref.null ${i32_f32}) - ) -) diff -Nru binaryen-108/test/lit/passes/dae-gc-refine-return.wast binaryen-99/test/lit/passes/dae-gc-refine-return.wast --- binaryen-108/test/lit/passes/dae-gc-refine-return.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dae-gc-refine-return.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,818 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --dae -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --dae --nominal -S -o - | filecheck %s --check-prefix NOMNL - -(module - ;; CHECK: (type $return_{} (func (result (ref ${})))) - ;; NOMNL: (type $return_{} (func_subtype (result (ref ${})) func)) - (type $return_{} (func (result (ref ${})))) - - ;; CHECK: (type ${i32} (struct (field i32))) - - ;; CHECK: (type ${i32_i64} (struct (field i32) (field i64))) - - ;; CHECK: (type ${i32_f32} (struct (field i32) (field f32))) - ;; NOMNL: (type ${} (struct_subtype data)) - - ;; NOMNL: (type ${i32} (struct_subtype (field i32) ${})) - - ;; NOMNL: (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) - - ;; NOMNL: (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) - (type ${i32_f32} (struct_subtype (field i32) (field f32) ${i32})) - - (type ${i32_i64} (struct_subtype (field i32) (field i64) ${i32})) - - (type ${i32} (struct_subtype (field i32) ${})) - - ;; CHECK: (type ${} (struct )) - (type ${} (struct)) - - (table 1 1 funcref) - - ;; We cannot refine the return type if nothing is actually returned. - ;; CHECK: (func $refine-return-no-return (result anyref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-no-return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-no-return (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-no-return) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $refine-return-no-return (result anyref) - ;; Call this function, so that we attempt to optimize it. Note that we do not - ;; just drop the result, as that would cause the drop optimizations to kick - ;; in. - (local $temp anyref) - (local.set $temp (call $refine-return-no-return)) - - (unreachable) - ) - - ;; We cannot refine the return type if it is already the best it can be. - ;; CHECK: (func $refine-return-no-refining (result anyref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $any anyref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-no-refining) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-no-refining (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $any anyref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-no-refining) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $any) - ;; NOMNL-NEXT: ) - (func $refine-return-no-refining (result anyref) - (local $temp anyref) - (local $any anyref) - - (local.set $temp (call $refine-return-no-refining)) - - (local.get $any) - ) - - ;; Refine the return type based on the value flowing out. - ;; CHECK: (func $refine-return-flow (result funcref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-flow) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-flow (type $none_=>_funcref) (result funcref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $func funcref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-flow) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - (func $refine-return-flow (result anyref) - (local $temp anyref) - (local $func funcref) - - (local.set $temp (call $refine-return-flow)) - - (local.get $func) - ) - ;; CHECK: (func $call-refine-return-flow (result funcref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $call-refine-return-flow) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result funcref) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $refine-return-flow) - ;; CHECK-NEXT: (call $refine-return-flow) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-refine-return-flow (type $none_=>_funcref) (result funcref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $call-refine-return-flow) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if (result funcref) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (call $refine-return-flow) - ;; NOMNL-NEXT: (call $refine-return-flow) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-refine-return-flow (result anyref) - (local $temp anyref) - (local.set $temp (call $call-refine-return-flow)) - - ;; After refining the return value of the above function, refinalize will - ;; update types here, which will lead to updating the if, and then the entire - ;; function's return value. - (if (result anyref) - (i32.const 1) - (call $refine-return-flow) - (call $refine-return-flow) - ) - ) - - ;; Refine the return type based on a return. - ;; CHECK: (func $refine-return-return (result funcref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-return (type $none_=>_funcref) (result funcref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $func funcref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-return) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $refine-return-return (result anyref) - (local $temp anyref) - (local $func funcref) - - (local.set $temp (call $refine-return-return)) - - (return (local.get $func)) - ) - - ;; Refine the return type based on multiple values. - ;; CHECK: (func $refine-return-many (result funcref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-many) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-many (type $none_=>_funcref) (result funcref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $func funcref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-many) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - (func $refine-return-many (result anyref) - (local $temp anyref) - (local $func funcref) - - (local.set $temp (call $refine-return-many)) - - (if - (i32.const 1) - (return (local.get $func)) - ) - (if - (i32.const 2) - (return (local.get $func)) - ) - (local.get $func) - ) - - ;; CHECK: (func $refine-return-many-blocked (result anyref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (local $data (ref null data)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-many-blocked) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-many-blocked (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $func funcref) - ;; NOMNL-NEXT: (local $data (ref null data)) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-many-blocked) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - (func $refine-return-many-blocked (result anyref) - (local $temp anyref) - (local $func funcref) - (local $data (ref null data)) - - (local.set $temp (call $refine-return-many-blocked)) - - (if - (i32.const 1) - (return (local.get $func)) - ) - (if - (i32.const 2) - ;; The refined return value is blocked by this return. - (return (local.get $data)) - ) - (local.get $func) - ) - - ;; CHECK: (func $refine-return-many-blocked-2 (result anyref) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (local $data (ref null data)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-many-blocked-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-many-blocked-2 (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $func funcref) - ;; NOMNL-NEXT: (local $data (ref null data)) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-many-blocked-2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - (func $refine-return-many-blocked-2 (result anyref) - (local $temp anyref) - (local $func funcref) - (local $data (ref null data)) - - (local.set $temp (call $refine-return-many-blocked-2)) - - (if - (i32.const 1) - (return (local.get $func)) - ) - (if - (i32.const 2) - (return (local.get $func)) - ) - ;; The refined return value is blocked by this value. - (local.get $data) - ) - - ;; CHECK: (func $refine-return-many-middle (result (ref null ${i32})) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local ${i32_i64} (ref null ${i32_i64})) - ;; CHECK-NEXT: (local ${i32_f32} (ref null ${i32_f32})) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $refine-return-many-middle) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get ${i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get ${i32_f32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-many-middle (type $none_=>_ref?|${i32}|) (result (ref null ${i32})) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local ${i32_i64} (ref null ${i32_i64})) - ;; NOMNL-NEXT: (local ${i32_f32} (ref null ${i32_f32})) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (call $refine-return-many-middle) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get ${i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get ${i32_f32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $refine-return-many-middle (result anyref) - (local $temp anyref) - (local ${i32_i64} (ref null ${i32_i64})) - (local ${i32_f32} (ref null ${i32_f32})) - - (local.set $temp (call $refine-return-many-middle)) - - ;; Return two different struct types, with an LUB that is not equal to either - ;; of them. - (if - (i32.const 1) - (return (local.get ${i32_i64})) - ) - (return (local.get ${i32_f32})) - ) - - ;; We can refine the return types of tuples. - ;; CHECK: (func $refine-return-tuple (result funcref i32) - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (call $refine-return-tuple) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $refine-return-tuple (type $none_=>_funcref_i32) (result funcref i32) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (local $func funcref) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (tuple.extract 0 - ;; NOMNL-NEXT: (call $refine-return-tuple) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (tuple.make - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $refine-return-tuple (result anyref i32) - (local $temp anyref) - (local $func funcref) - - (local.set $temp - (tuple.extract 0 - (call $refine-return-tuple) - ) - ) - - (tuple.make - (local.get $func) - (i32.const 1) - ) - ) - - ;; This function does a return call of the one after it. The one after it - ;; returns a ref.func of this one. They both begin by returning a funcref; - ;; after refining the return type of the second function, it will have a more - ;; specific type (which is ok as subtyping is allowed with tail calls). - ;; CHECK: (func $do-return-call (result funcref) - ;; CHECK-NEXT: (return_call $return-ref-func) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $do-return-call (type $none_=>_funcref) (result funcref) - ;; NOMNL-NEXT: (return_call $return-ref-func) - ;; NOMNL-NEXT: ) - (func $do-return-call (result funcref) - (return_call $return-ref-func) - ) - ;; CHECK: (func $return-ref-func (result (ref $none_=>_funcref)) - ;; CHECK-NEXT: (ref.func $do-return-call) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $return-ref-func (type $none_=>_ref|none_->_funcref|) (result (ref $none_=>_funcref)) - ;; NOMNL-NEXT: (ref.func $do-return-call) - ;; NOMNL-NEXT: ) - (func $return-ref-func (result funcref) - (ref.func $do-return-call) - ) - - ;; Show that we can optimize the return type of a function that does a tail - ;; call. - ;; CHECK: (func $tail-callee (result (ref ${})) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-callee (type $return_{}) (result (ref ${})) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $tail-callee (result (ref ${})) - (unreachable) - ) - ;; CHECK: (func $tail-caller-yes (result (ref ${})) - ;; CHECK-NEXT: (return_call $tail-callee) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-yes (type $return_{}) (result (ref ${})) - ;; NOMNL-NEXT: (return_call $tail-callee) - ;; NOMNL-NEXT: ) - (func $tail-caller-yes (result anyref) - ;; This function's return type can be refined because of this call, whose - ;; target's return type is more specific than anyref. - (return_call $tail-callee) - ) - ;; CHECK: (func $tail-caller-no (result anyref) - ;; CHECK-NEXT: (local $any anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return_call $tail-callee) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-no (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $any anyref) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return_call $tail-callee) - ;; NOMNL-NEXT: ) - (func $tail-caller-no (result anyref) - (local $any anyref) - - ;; This function's return type cannot be refined because of another return - ;; whose type prevents it. - (if (i32.const 1) - (return (local.get $any)) - ) - (return_call $tail-callee) - ) - ;; CHECK: (func $tail-call-caller - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-caller-yes) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-caller-no) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-call-caller (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $tail-caller-yes) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $tail-caller-no) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tail-call-caller - ;; Call the functions to cause optimization to happen. - (drop - (call $tail-caller-yes) - ) - (drop - (call $tail-caller-no) - ) - ) - - ;; As above, but with an indirect tail call. - ;; CHECK: (func $tail-callee-indirect (result (ref ${})) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-callee-indirect (type $return_{}) (result (ref ${})) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $tail-callee-indirect (result (ref ${})) - (unreachable) - ) - ;; CHECK: (func $tail-caller-indirect-yes (result (ref ${})) - ;; CHECK-NEXT: (return_call_indirect $0 (type $return_{}) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-indirect-yes (type $return_{}) (result (ref ${})) - ;; NOMNL-NEXT: (return_call_indirect $0 (type $return_{}) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tail-caller-indirect-yes (result anyref) - (return_call_indirect (type $return_{}) (i32.const 0)) - ) - ;; CHECK: (func $tail-caller-indirect-no (result anyref) - ;; CHECK-NEXT: (local $any anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return_call_indirect $0 (type $return_{}) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-indirect-no (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $any anyref) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return_call_indirect $0 (type $return_{}) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tail-caller-indirect-no (result anyref) - (local $any anyref) - - (if (i32.const 1) - (return (local.get $any)) - ) - (return_call_indirect (type $return_{}) (i32.const 0)) - ) - ;; CHECK: (func $tail-call-caller-indirect - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-caller-indirect-yes) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-caller-indirect-no) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-call-caller-indirect (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $tail-caller-indirect-yes) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $tail-caller-indirect-no) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tail-call-caller-indirect - (drop - (call $tail-caller-indirect-yes) - ) - (drop - (call $tail-caller-indirect-no) - ) - ) - - ;; As above, but with a tail call by function reference. - ;; CHECK: (func $tail-callee-call_ref (result (ref ${})) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-callee-call_ref (type $return_{}) (result (ref ${})) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $tail-callee-call_ref (result (ref ${})) - (unreachable) - ) - ;; CHECK: (func $tail-caller-call_ref-yes (result (ref ${})) - ;; CHECK-NEXT: (local $return_{} (ref null $return_{})) - ;; CHECK-NEXT: (return_call_ref - ;; CHECK-NEXT: (local.get $return_{}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-call_ref-yes (type $return_{}) (result (ref ${})) - ;; NOMNL-NEXT: (local $return_{} (ref null $return_{})) - ;; NOMNL-NEXT: (return_call_ref - ;; NOMNL-NEXT: (local.get $return_{}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tail-caller-call_ref-yes (result anyref) - (local $return_{} (ref null $return_{})) - - (return_call_ref (local.get $return_{})) - ) - ;; CHECK: (func $tail-caller-call_ref-no (result anyref) - ;; CHECK-NEXT: (local $any anyref) - ;; CHECK-NEXT: (local $return_{} (ref null $return_{})) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return_call_ref - ;; CHECK-NEXT: (local.get $return_{}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-call_ref-no (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $any anyref) - ;; NOMNL-NEXT: (local $return_{} (ref null $return_{})) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return_call_ref - ;; NOMNL-NEXT: (local.get $return_{}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tail-caller-call_ref-no (result anyref) - (local $any anyref) - (local $return_{} (ref null $return_{})) - - (if (i32.const 1) - (return (local.get $any)) - ) - (return_call_ref (local.get $return_{})) - ) - ;; CHECK: (func $tail-caller-call_ref-unreachable - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-caller-call_ref-unreachable (type $none_=>_none) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $tail-caller-call_ref-unreachable (result anyref) - ;; An unreachable means there is no function signature to even look at. We - ;; should not hit an assertion on such things. - (return_call_ref (unreachable)) - ) - ;; CHECK: (func $tail-call-caller-call_ref - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-caller-call_ref-yes) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-caller-call_ref-no) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $tail-caller-call_ref-unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tail-call-caller-call_ref (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $tail-caller-call_ref-yes) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $tail-caller-call_ref-no) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $tail-caller-call_ref-unreachable) - ;; NOMNL-NEXT: ) - (func $tail-call-caller-call_ref - (drop - (call $tail-caller-call_ref-yes) - ) - (drop - (call $tail-caller-call_ref-no) - ) - (drop - (call $tail-caller-call_ref-unreachable) - ) - ) - - ;; CHECK: (func $update-null (param $x i32) (param $y i32) (result (ref null ${i32})) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (struct.new_default ${i32_f32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (ref.null ${i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (struct.new_default ${i32_i64}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $update-null (type $i32_i32_=>_ref?|${i32}|) (param $x i32) (param $y i32) (result (ref null ${i32})) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (struct.new_default ${i32_f32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (ref.null ${i32}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (struct.new_default ${i32_i64}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $update-null (param $x i32) (param $y i32) (result anyref) - ;; Of the three returns here, the null can be updated, and the LUB is - ;; determined by the other two, and is their shared parent ${}. - (if - (local.get $x) - (if - (local.get $y) - (return (struct.new ${i32_f32})) - (return (ref.null any)) - ) - (return (struct.new ${i32_i64})) - ) - ) - - ;; CHECK: (func $call-update-null (result anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $update-null - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $update-null - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-update-null (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $update-null - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $update-null - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-update-null (result anyref) - ;; Call $update-null so it gets optimized. (Call it with various values so - ;; that other opts do not inline the constants.) - (drop - ($call $update-null - (i32.const 0) - (i32.const 1) - ) - ) - ($call $update-null - (i32.const 1) - (i32.const 0) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/dae-gc.wast binaryen-99/test/lit/passes/dae-gc.wast --- binaryen-108/test/lit/passes/dae-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dae-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,255 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: foreach %s %t wasm-opt -all --dae -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt -all --dae --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type ${} (struct )) - ;; NOMNL: (type ${} (struct_subtype data)) - (type ${} (struct)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $none_=>_none) - ;; NOMNL-NEXT: (call $bar) - ;; NOMNL-NEXT: ) - (func $foo - (call $bar - (i31.new - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $bar - ;; CHECK-NEXT: (local $0 (ref null i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i31.new - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $bar (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 (ref null i31)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.tee $0 - ;; NOMNL-NEXT: (i31.new - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.tee $0 - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $bar (param $0 i31ref) - (drop - ;; after the parameter is removed, we create a nullable local to replace it, - ;; and must update the tee's type accordingly to avoid a validation error, - ;; and also add a ref.as_non_null so that the outside still receives the - ;; same type as before - (local.tee $0 - (i31.new - (i32.const 2) - ) - ) - ) - ;; test for an unreachable tee, whose type must be unreachable even after - ;; the change (the tee would need to be dropped if it were not unreachable, - ;; so the correctness in this case is visible in the output) - (local.tee $0 - (unreachable) - ) - ) - ;; a function that gets an rtt that is never used. we cannot create a local for - ;; that parameter, as it is not defaultable, so do not remove the parameter. - ;; CHECK: (func $get-rtt (param $0 (rtt ${})) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get-rtt (type $rtt_${}_=>_none) (param $0 (rtt ${})) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $get-rtt (param $0 (rtt ${})) - (nop) - ) - ;; CHECK: (func $send-rtt - ;; CHECK-NEXT: (call $get-rtt - ;; CHECK-NEXT: (rtt.canon ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $send-rtt (type $none_=>_none) - ;; NOMNL-NEXT: (call $get-rtt - ;; NOMNL-NEXT: (rtt.canon ${}) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $send-rtt - (call $get-rtt - (rtt.canon ${}) - ) - ) -) - -;; Test ref.func and ref.null optimization of constant parameter values. -(module - ;; CHECK: (func $foo (param $0 (ref $none_=>_none)) - ;; CHECK-NEXT: (local $1 (ref null $none_=>_none)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.func $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $ref|none_->_none|_=>_none) (param $0 (ref $none_=>_none)) - ;; NOMNL-NEXT: (local $1 (ref null $none_=>_none)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (ref.func $a) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $foo (param $x (ref func)) (param $y (ref func)) - ;; "Use" the params to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $y)) - ) - - ;; CHECK: (func $call-foo - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (ref.func $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (ref.func $c) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-foo (type $none_=>_none) - ;; NOMNL-NEXT: (call $foo - ;; NOMNL-NEXT: (ref.func $b) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $foo - ;; NOMNL-NEXT: (ref.func $c) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-foo - ;; Call $foo with a constant function in the first param, which we - ;; can optimize, but different ones in the second. - (call $foo - (ref.func $a) - (ref.func $b) - ) - (call $foo - (ref.func $a) - (ref.func $c) - ) - ) - - ;; CHECK: (func $bar (param $0 (ref null $none_=>_none)) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $bar (type $ref?|none_->_none|_=>_none) (param $0 (ref null $none_=>_none)) - ;; NOMNL-NEXT: (local $1 anyref) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (ref.null func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $bar (param $x (ref null any)) (param $y (ref null any)) - ;; "Use" the params to avoid other optimizations kicking in. - (drop (local.get $x)) - (drop (local.get $y)) - ) - - ;; CHECK: (func $call-bar - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (ref.null $none_=>_none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (ref.func $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $call-bar (type $none_=>_none) - ;; NOMNL-NEXT: (call $bar - ;; NOMNL-NEXT: (ref.null $none_=>_none) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $bar - ;; NOMNL-NEXT: (ref.func $a) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $call-bar - ;; Call with nulls. Mixing nulls is fine as they all have the same value, and - ;; we can optimize. However, mixing a null with a reference stops us in the - ;; second param. - (call $bar - (ref.null func) - (ref.null func) - ) - (call $bar - (ref.null any) - (ref.func $a) - ) - ) - - ;; Helper functions so we have something to take the reference of. - ;; CHECK: (func $a - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $a (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $a) - ;; CHECK: (func $b - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $b (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $b) - ;; CHECK: (func $c - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $c (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $c) -) diff -Nru binaryen-108/test/lit/passes/dae-optimizing.wast binaryen-99/test/lit/passes/dae-optimizing.wast --- binaryen-108/test/lit/passes/dae-optimizing.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dae-optimizing.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --dae-optimizing -S -o - | filecheck %s - -(module - (type $0 (func (param f32) (result f32))) - (type $1 (func (param f64 f32 f32 f64 f32 i64 f64) (result i32))) - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_f32 (func (result f32))) - - ;; CHECK: (type $2 (func (param f64 f32 f32 f64 f32 i32 i32 f64) (result i32))) - (type $2 (func (param f64 f32 f32 f64 f32 i32 i32 f64) (result i32))) - ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) - (global $global$0 (mut i32) (i32.const 10)) - ;; CHECK: (func $0 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result f32) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 33554432) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$2 (result f32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -11) - ;; CHECK-NEXT: ) - (func $0 (; 0 ;) (type $1) (param $0 f64) (param $1 f32) (param $2 f32) (param $3 f64) (param $4 f32) (param $5 i64) (param $6 f64) (result i32) - (local $7 i32) - (local $8 i32) - (if - (local.tee $7 - (i32.const 33554432) - ) - (drop - (loop $label$2 (result f32) - (if - (global.get $global$0) - (return - (local.get $7) - ) - ) - (local.set $8 - (block $label$4 (result i32) - (drop - (local.tee $7 - (local.get $8) - ) - ) - (i32.const 0) - ) - ) - (br_if $label$2 - (local.get $7) - ) - (f32.const 1) - ) - ) - (drop - (call $1 - (f32.const 1) - ) - ) - ) - (i32.const -11) - ) - ;; CHECK: (func $1 (result f32) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - (func $1 (; 1 ;) (type $0) (param $0 f32) (result f32) - (f32.const 0) - ) - ;; CHECK: (func $2 (param $0 f64) (param $1 f32) (param $2 f32) (param $3 f64) (param $4 f32) (param $5 i32) (param $6 i32) (param $7 f64) (result i32) - ;; CHECK-NEXT: (call $0) - ;; CHECK-NEXT: ) - (func $2 (; 2 ;) (type $2) (param $0 f64) (param $1 f32) (param $2 f32) (param $3 f64) (param $4 f32) (param $5 i32) (param $6 i32) (param $7 f64) (result i32) - (call $0 - (f64.const 1) - (f32.const 1) - (f32.const 1) - (f64.const 1) - (f32.const 1) - (i64.const 1) - (f64.const 1) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/dae_tnh.wast binaryen-99/test/lit/passes/dae_tnh.wast --- binaryen-108/test/lit/passes/dae_tnh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dae_tnh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: foreach %s %t wasm-opt --dae --all-features -tnh -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $ref?|$struct|_=>_none (func (param (ref null $struct)))) - - ;; CHECK: (type $struct (struct (field i32))) - (type $struct (struct_subtype (field i32) data)) - - ;; CHECK: (func $target - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target (param $x i32) - (nop) - ) - - ;; CHECK: (func $caller (param $ref (ref null $struct)) - ;; CHECK-NEXT: (call $target) - ;; CHECK-NEXT: ) - (func $caller (param $ref (ref null $struct)) - (call $target - ;; This might trap in theory, but in traps-never-happen mode which is - ;; enabled here, we can ignore and remove such side effects, allowing us - ;; to optimize away this parameter which is never used. - (struct.get $struct 0 - (local.get $ref) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/dce_all-features.wast binaryen-99/test/lit/passes/dce_all-features.wast --- binaryen-108/test/lit/passes/dce_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dce_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1417 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --dce --all-features -S -o - | filecheck %s - -(module - (memory 10) - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $1 (func)) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - (type $1 (func)) - (table 1 1 funcref) - (elem (i32.const 0) $call-me) - ;; CHECK: (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) - - ;; CHECK: (type $f32_i64_=>_none (func (param f32 i64))) - - ;; CHECK: (type $f32_i64_=>_i32 (func (param f32 i64) (result i32))) - - ;; CHECK: (global $x (mut i32) (i32.const 0)) - (global $x (mut i32) (i32.const 0)) - ;; CHECK: (memory $0 10) - - ;; CHECK: (table $0 1 1 funcref) - - ;; CHECK: (elem (i32.const 0) $call-me) - - ;; CHECK: (func $call-me (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $call-me (type $ii) (param $0 i32) (param $1 i32) - (nop) - ) - ;; CHECK: (func $code-to-kill - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $out3 - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out4 - ;; CHECK-NEXT: (br_table $out4 $out4 $out4 $out4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out5 - ;; CHECK-NEXT: (br_if $out5 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out16 - ;; CHECK-NEXT: (block $in - ;; CHECK-NEXT: (br_if $out16 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block11 - ;; CHECK-NEXT: (block $out18 - ;; CHECK-NEXT: (block $in19 - ;; CHECK-NEXT: (br_if $in19 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out20 - ;; CHECK-NEXT: (block $in21 - ;; CHECK-NEXT: (br_table $out20 $in21 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out22 - ;; CHECK-NEXT: (block $in23 - ;; CHECK-NEXT: (br_table $in23 $out22 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block13 - ;; CHECK-NEXT: (block $out25 - ;; CHECK-NEXT: (block $in26 - ;; CHECK-NEXT: (br_table $in26 $in26 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block15 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out29 - ;; CHECK-NEXT: (loop $in30 - ;; CHECK-NEXT: (br_if $out29 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block20 - ;; CHECK-NEXT: (loop $in32 - ;; CHECK-NEXT: (br_if $in32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 139) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 246) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 55) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 66) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 77) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 88) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 99) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $code-to-kill (type $1) - (local $x i32) - (block $out - (br $out) - (drop - (i32.const 0) - ) - (if - (i32.const 1) - (drop - (i32.const 2) - ) - ) - (br_table $out $out $out $out - (i32.const 3) - ) - (call $code-to-kill) - ) - (if - (i32.const 0) - (block $out - (unreachable) - (drop - (i32.const 0) - ) - ) - ) - (if - (i32.const 0) - (block $out - (return) - (drop - (i32.const 0) - ) - ) - ) - (block $out - (br_table $out $out $out $out - (i32.const 4) - ) - (drop - (i32.const 0) - ) - ) - (block $out - (br_if $out - (i32.const 3) - ) - (drop - (i32.const 0) - ) - ) - (if - (i32.const 0) - (block $block4 - (if - (i32.const 0) - (block $out - (unreachable) - (drop - (i32.const 0) - ) - ) - (block $out - (unreachable) - (drop - (i32.const 0) - ) - ) - ) - (drop - (i32.const 0) - ) - ) - ) - (if - (i32.const 0) - (drop - (block $out (result i32) - (br $out - (unreachable) - ) - (drop - (i32.const 0) - ) - (unreachable) - ) - ) - ) - (if - (i32.const 0) - (drop - (block $out (result i32) - (br_if $out - (unreachable) - (i32.const 0) - ) - (drop - (i32.const 0) - ) - (unreachable) - ) - ) - ) - (if - (i32.const 0) - (drop - (block $out (result i32) - (br_if $out - (unreachable) - (unreachable) - ) - (drop - (i32.const 0) - ) - (unreachable) - ) - ) - ) - (block $out - (block $in - (br_if $out - (i32.const 1) - ) - ) - (unreachable) - ) - (if - (i32.const 0) - (block $block11 - (block $out - (block $in - (br_if $in - (i32.const 1) - ) - ) - (unreachable) - ) - (drop - (i32.const 10) - ) - ) - ) - (block $out - (block $in - (br_table $out $in - (i32.const 1) - ) - ) - (unreachable) - ) - (block $out - (block $in - (br_table $in $out - (i32.const 1) - ) - ) - (unreachable) - ) - (if - (i32.const 0) - (block $block13 - (block $out - (block $in - (br_table $in $in - (i32.const 1) - ) - ) - (unreachable) - ) - (drop - (i32.const 10) - ) - ) - ) - (if - (i32.const 0) - (block $block15 - (drop - (i32.const 10) - ) - (drop - (i32.const 42) - ) - (unreachable) - (return - (unreachable) - ) - (unreachable) - (return) - ) - ) - (if - (i32.const 0) - (loop $loop-in18 - (unreachable) - ) - ) - (block $out - (loop $in - (br_if $out - (i32.const 1) - ) - (unreachable) - ) - ) - (if - (i32.const 0) - (block $block20 - (loop $in - (br_if $in - (i32.const 1) - ) - (unreachable) - ) - (drop - (i32.const 10) - ) - ) - ) - (if - (i32.const 1) - (call $call-me - (i32.const 123) - (unreachable) - ) - ) - (if - (i32.const 2) - (call $call-me - (unreachable) - (i32.const 0) - ) - ) - (if - (i32.const 3) - (call $call-me - (unreachable) - (unreachable) - ) - ) - (if - (i32.const -1) - (call_indirect (type $ii) - (i32.const 123) - (i32.const 456) - (unreachable) - ) - ) - (if - (i32.const -2) - (call_indirect (type $ii) - (i32.const 139) - (unreachable) - (i32.const 0) - ) - ) - (if - (i32.const -3) - (call_indirect (type $ii) - (i32.const 246) - (unreachable) - (unreachable) - ) - ) - (if - (i32.const -4) - (call_indirect (type $ii) - (unreachable) - (unreachable) - (unreachable) - ) - ) - (if - (i32.const 11) - (local.set $x - (unreachable) - ) - ) - (if - (i32.const 22) - (drop - (i32.load - (unreachable) - ) - ) - ) - (if - (i32.const 33) - (i32.store - (i32.const 0) - (unreachable) - ) - ) - (if - (i32.const 44) - (i32.store - (unreachable) - (i32.const 0) - ) - ) - (if - (i32.const 55) - (i32.store - (unreachable) - (unreachable) - ) - ) - (if - (i32.const 66) - (drop - (i32.eqz - (unreachable) - ) - ) - ) - (if - (i32.const 77) - (drop - (i32.add - (unreachable) - (i32.const 0) - ) - ) - ) - (if - (i32.const 88) - (drop - (i32.add - (i32.const 0) - (unreachable) - ) - ) - ) - (if - (i32.const 99) - (i32.add - (unreachable) - (unreachable) - ) - ) - (if - (i32.const 100) - (drop - (select - (i32.const 123) - (i32.const 456) - (unreachable) - ) - ) - ) - (if - (i32.const 101) - (drop - (select - (i32.const 123) - (unreachable) - (i32.const 456) - ) - ) - ) - (if - (i32.const 102) - (drop - (select - (unreachable) - (i32.const 123) - (i32.const 456) - ) - ) - ) - (drop - (i32.const 1337) - ) - ) - ;; CHECK: (func $killer - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $killer (type $1) - (unreachable) - (drop - (i32.const 1000) - ) - ) - ;; CHECK: (func $target - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $target (type $1) - (drop - (i32.const 2000) - ) - ) - ;; CHECK: (func $typed-block-none-then-unreachable (result i32) - ;; CHECK-NEXT: (block $top-typed - ;; CHECK-NEXT: (block $switch$0 - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $typed-block-none-then-unreachable (result i32) - (block $top-typed (result i32) - (block $switch$0 ;; this looks like it can be broken to, so it gets type 'none' - (return - (i32.const 0) - ) - (br $switch$0) ;; this is not reachable, so dce cleans it up, changing $switch$0's type - ) - (return ;; and this is cleaned up as well, leaving $top-typed in need of a type change - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32) - ;; CHECK-NEXT: (block $switch$7 - ;; CHECK-NEXT: (block $switch-default$10 - ;; CHECK-NEXT: (block $switch-case$9 - ;; CHECK-NEXT: (block $switch-case$8 - ;; CHECK-NEXT: (br_table $switch-case$9 $switch-case$8 $switch-default$10 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $$$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $$$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32) - (block $switch$7 - (block $switch-default$10 - (block $switch-case$9 - (block $switch-case$8 - (br_table $switch-case$9 $switch-case$8 $switch-default$10 - (i32.const -1) - ) - ) - ) - (return - (local.get $$$0) - ) - (br $switch$7) - ) - (return - (local.get $$$0) - ) - ) - (return - (i32.const 0) - ) - ) - ;; CHECK: (func $global - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $global - (unreachable) - (drop (global.get $x)) - (global.set $x (i32.const 1)) - ) - ;; CHECK: (func $ret (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ret (result i32) - (return - (i32.const 0) - ) - (nop) - (i32.const 0) - ) - ;; CHECK: (func $unreachable-br (result i32) - ;; CHECK-NEXT: (block $out (result i32) - ;; CHECK-NEXT: (br $out - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-br (result i32) - (block $out (result i32) - (br $out - (br $out (i32.const 0)) - ) - ) - ) - ;; CHECK: (func $unreachable-br-loop (result i32) - ;; CHECK-NEXT: (loop $out - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-br-loop (result i32) - (loop $out - (br $out) - ) - ) - ;; CHECK: (func $unreachable-block-ends-switch (result i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-block-ends-switch (result i32) - (block $label$0 (result i32) - (block $label$3 - (nop) - (br_table $label$3 - (unreachable) - ) - (unreachable) - ) - (i32.const 19) - ) - ) - ;; CHECK: (func $unreachable-block-ends-br_if (result i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-block-ends-br_if (result i32) - (block $label$0 (result i32) - (block $label$2 - (nop) - (br_if $label$2 - (unreachable) - ) - (unreachable) - ) - (i32.const 19) - ) - ) - ;; CHECK: (func $unreachable-brs-3 (result i32) - ;; CHECK-NEXT: (block $label$0 (result i32) - ;; CHECK-NEXT: (br $label$0 - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-brs-3 (result i32) - (block $label$0 (result i32) - (br $label$0 - (memory.grow - (br $label$0 - (i32.const 18) - ) - ) - ) - (i32.const 21) - ) - ) - ;; CHECK: (func $unreachable-brs-4 (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-brs-4 (param $var$0 i32) (result i32) - (i32.add - (i32.const 1) - (block $label$0 (result i32) - (br $label$0 - (block $label$1 (result i32) ;; this block is declared i32, but we can see it is unreachable - (drop - (br_if $label$0 - (i32.const 4104) - (unreachable) - ) - ) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ;; CHECK: (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (if (result i64) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$0 (result i64) - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result i64) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) - (local $2 i64) - (if (result i64) - (i64.eqz - (local.get $var$0) - ) - (block $label$0 (result i64) - (local.get $var$1) - ) - (block $label$1 (result i64) - (call $call-unreach - (i64.sub - (local.get $var$0) - (i64.const 1) - ) - (i64.mul - (block (result i64) - (local.set $2 - (local.get $var$0) - ) - (nop) - (local.get $2) - ) - (unreachable) - ) - ) - ) - ) - ) - ;; CHECK: (func $br-gone-means-block-type-changes-then-refinalize-at-end-is-too-late (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br-gone-means-block-type-changes-then-refinalize-at-end-is-too-late (param $var$0 i32) (result i32) - (block $label$0 (result i32) - (br $label$0 - (block (result i32) - (nop) - (drop - (br_if $label$0 - (unreachable) - (local.get $var$0) - ) - ) - (i32.const 4) - ) - ) - ) - ) - ;; CHECK: (func $br-with-unreachable-value-should-not-give-a-block-a-value (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (block $label$0 (result i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $label$0 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br-with-unreachable-value-should-not-give-a-block-a-value (param $var$0 i32) (result i32) - (block $label$0 (result i32) - (br $label$0 - (block (result i32) ;; turns into unreachable when refinalized - (drop - (br_if $label$0 - (i32.const 8) - (local.get $var$0) - ) - ) - (unreachable) - ) - ) - (i32.const 16) - ) - ) - ;; CHECK: (func $replace-br-value-of-i32-with-unreachable (result i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $replace-br-value-of-i32-with-unreachable (result i32) - (block $label$0 (result i32) - (br $label$0 - (block $label$1 (result i32) - (nop) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $shorten-block-requires-sync-refinalize (param $var$0 i32) (param $var$1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $shorten-block-requires-sync-refinalize (param $var$0 i32) (param $var$1 i32) - (block $label$0 - (unreachable) - (if - (unreachable) - (br_if $label$0 - (local.get $var$1) - ) - ) - ) - ) - ;; CHECK: (func $block-with-type-but-is-unreachable (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block-with-type-but-is-unreachable (param $var$0 i32) (result i32) - (block $label$0 (result i32) - (br $label$0 - (block $block (result i32) - (nop) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $if-with-type-but-is-unreachable (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-with-type-but-is-unreachable (param $var$0 i32) (result i32) - (block $label$0 (result i32) - (br $label$0 - (if (result i32) - (local.get $var$0) - (unreachable) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $unreachable-loop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $unreachable-loop - (loop $label$2 - (unreachable) - (br $label$2) - ) - ) - ;; CHECK: (func $br-block-from-unary (result i32) - ;; CHECK-NEXT: (block $label$6 (result i32) - ;; CHECK-NEXT: (block $label$7 - ;; CHECK-NEXT: (br $label$6 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br-block-from-unary (result i32) - (block $label$6 (result i32) - (i32.ctz - (block $label$7 (result i32) - (br $label$6 - (i32.const 8) - ) - ) - ) - ) - ) - ;; CHECK: (func $replace-unary-with-br-child - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $label$6 (result i32) - ;; CHECK-NEXT: (br $label$6 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $replace-unary-with-br-child - (drop - (block $label$6 (result i32) - (i32.ctz - (br $label$6 - (i32.const 8) - ) - ) - ) - ) - ) - ;; CHECK: (func $br_if-unreach-then-br_if-normal - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_if-unreach-then-br_if-normal - (block $out - (nop) - (br_if $out - (unreachable) - ) - (br_if $out - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $replace-with-unreachable-affects-parent (param $var$0 f32) (param $var$1 i64) - ;; CHECK-NEXT: (block $top - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $replace-with-unreachable-affects-parent - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (i64.const -15917430362925035) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $replace-with-unreachable-affects-parent (param $var$0 f32) (param $var$1 i64) - (block $top - (drop - (f32.load offset=4 - (i64.ne - (i64.const 0) - (if (result i64) - (block (result i32) - (call $replace-with-unreachable-affects-parent - (f32.const 1) - (i64.const -15917430362925035) - ) - (i32.const 1) - ) - (unreachable) - (unreachable) - ) - ) - ) - ) - (nop) ;; this is not reachable due to the above code, so we replace it with unreachable. type should go to parent - ) - ) - ;; CHECK: (func $replace-block-changes-later-when-if-goes - ;; CHECK-NEXT: (block $top - ;; CHECK-NEXT: (global.set $x - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $inner - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (i64.const -15917430362925035) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $replace-block-changes-later-when-if-goes - (block $top ;; and so should this - (global.set $x - (i32.const 0) - ) - (drop - (f32.load offset=4 - (i64.ne - (block $inner (result i64) ;; this becomes unreachable - (drop - (call $helper - (f32.const 1) - (i64.const -15917430362925035) - ) - ) - (unreachable) - ) - (i64.const 0) - ) - ) - ) - (if - (i32.load16_s offset=22 align=1 - (i32.const 0) - ) - (br $top) ;; this keeps the block none after the inner block gets unreachable. but it will vanish into unreachable itself - (unreachable) - ) - ) - ) - ;; CHECK: (func $helper (param $var$0 f32) (param $var$1 i64) (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $helper (param $var$0 f32) (param $var$1 i64) (result i32) - (i32.const 0) - ) -) -;; if goes to unreachable, need to propagate that up to the global.set -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global (mut f64) (f64.const 0)) - (global $global (mut f64) (f64.const 0)) - ;; CHECK: (func $0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (global.set $global - (if (result f64) - (i32.const 0) - (unreachable) - (unreachable) - ) - ) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (local $local f64) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (local $local f64) - (local.set $local - (if (result f64) - (i32.const 0) - (unreachable) - (unreachable) - ) - ) - ) -) - -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $unnecessary-concrete-block (result i32) - ;; CHECK-NEXT: (block $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unnecessary-concrete-block (result i32) - (block $foo (result i32) ;; unnecessary type - (nop) - (unreachable) - ) - ) - ;; CHECK: (func $necessary-concrete-block (result i32) - ;; CHECK-NEXT: (block $foo (result i32) - ;; CHECK-NEXT: (br $foo - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $necessary-concrete-block (result i32) - (block $foo (result i32) - (br $foo (i32.const 1)) - (unreachable) - ) - ) - ;; CHECK: (func $unnecessary-concrete-if (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unnecessary-concrete-if (result i32) - (if (result i32) ;; unnecessary type - (i32.const 0) - (return (i32.const 1)) - (unreachable) - ) - ) - ;; CHECK: (func $unnecessary-concrete-try (result i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unnecessary-concrete-try (result i32) - (try (result i32) - (do - (unreachable) - ) - (catch_all - (unreachable) - ) - ) - ) - ;; CHECK: (func $note-loss-of-if-children - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $note-loss-of-if-children - (block $label$1 - (if ;; begins unreachable - type never changes - but after the condition - ;; becomes unreachable, it will lose the children, which means no more - ;; br to the outer block, changing that type. - (block $label$2 (result i32) - (nop) - (unreachable) - ) - (unreachable) - (br $label$1) - ) - ) - ) - ;; CHECK: (func $note-loss-of-non-control-flow-children - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $note-loss-of-non-control-flow-children - (block $out - (drop - (i32.add - (block (result i32) - (nop) - (unreachable) - ) - (br $out) ;; when this is removed as dead, the block becomes unreachable - ) - ) - ) - ) -) -(module - ;; CHECK: (type $none_=>_ref|any| (func (result (ref any)))) - - ;; CHECK: (func $foo (result (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (result (ref any)) - (block $label$1 (result (ref any)) - ;; this break has an unreachable input, and so it does not have a heap type - ;; there, and no heap type to send on the branch. this tests we do not hit - ;; the assertion in getHeapType() if we call that. - (br_on_non_null $label$1 - (block (result anyref) - (unreachable) - ) - ) - (unreachable) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/dce-eh.wast binaryen-99/test/lit/passes/dce-eh.wast --- binaryen-108/test/lit/passes/dce-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dce-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --dce -all -S -o - | filecheck %s - -;; If either try body or catch body is reachable, the whole try construct is -;; reachable -(module - ;; CHECK: (tag $e (param)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo) - (tag $e) - - - ;; CHECK: (func $try_unreachable - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $try_unreachable - (try - (do - (unreachable) - ) - (catch_all) - ) - (call $foo) ;; shouldn't be dce'd - ) - - ;; CHECK: (func $catch_unreachable - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $catch_unreachable - (try - (do) - (catch_all - (unreachable) - ) - ) - (call $foo) ;; shouldn't be dce'd - ) - - ;; CHECK: (func $both_unreachable - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $both_unreachable - (try - (do - (unreachable) - ) - (catch_all - (unreachable) - ) - ) - (call $foo) ;; should be dce'd - ) - - ;; CHECK: (func $throw - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (throw $e) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $throw - ;; All these wrapping expressions before 'throw' will be dce'd - (drop - (block $label$0 (result externref) - (if - (i32.clz - (block $label$1 (result i32) - (throw $e) - ) - ) - (nop) - ) - (ref.null extern) - ) - ) - ) - - ;; CHECK: (func $rethrow - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rethrow $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $rethrow - (try $l0 - (do) - (catch $e - (drop - ;; This i32.add will be dce'd - (i32.add - (i32.const 0) - (rethrow $l0) - ) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/dce_vacuum_remove-unused-names.wast binaryen-99/test/lit/passes/dce_vacuum_remove-unused-names.wast --- binaryen-108/test/lit/passes/dce_vacuum_remove-unused-names.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dce_vacuum_remove-unused-names.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --dce --vacuum --remove-unused-names -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $f32_f32_=>_f32 (func (param f32 f32) (result f32))) - - ;; CHECK: (type $i64_=>_i64 (func (param i64) (result i64))) - - ;; CHECK: (func $__Z12serveroptionPc (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $__Z12serveroptionPc (result i32) - (block $switch$0 - (return - (i32.const 0) - ) - (br $switch$0) - ) - (return - (i32.const 0) - ) - ) - ;; CHECK: (func $drop-unreachable (param $var$0 f32) (param $var$1 f32) (result f32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $drop-unreachable (param $var$0 f32) (param $var$1 f32) (result f32) - (block $label$0 (result f32) - (loop $label$2 - (drop - (unreachable) - ) - (unreachable) - ) - (local.get $var$1) - ) - ) - - ;; CHECK: (func $set-unreachable (param $var$0 i64) (result i64) - ;; CHECK-NEXT: (local $var$1 i64) - ;; CHECK-NEXT: (local $var$2 i64) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set-unreachable (param $var$0 i64) (result i64) - (local $var$1 i64) - (local $var$2 i64) - (block $label$0 (result i64) - (block $label$1 - (loop $label$2 - (if - (i64.eq - (local.get $var$1) - (i64.const 0) - ) - (unreachable) - (local.set $var$2 - (i64.mul - (unreachable) - (local.get $var$2) - ) - ) - ) - (br $label$2) - ) - ) - (local.get $var$2) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/dealign64.wast binaryen-99/test/lit/passes/dealign64.wast --- binaryen-108/test/lit/passes/dealign64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dealign64.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --dealign --enable-memory64 -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 i64 1 1) - (memory $0 i64 1 1) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (i64.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (i64.const 20) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (i64.const 24) - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop (i32.load (i64.const 4))) - (drop (i32.load align=1 (i64.const 8))) - (drop (i32.load align=2 (i64.const 12))) - (i32.store (i64.const 16) (i32.const 28)) - (i32.store align=1 (i64.const 20) (i32.const 32)) - (i32.store align=2 (i64.const 24) (i32.const 36)) - ) -) diff -Nru binaryen-108/test/lit/passes/dealign.wast binaryen-99/test/lit/passes/dealign.wast --- binaryen-108/test/lit/passes/dealign.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/dealign.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --dealign -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - ;; CHECK: (func $test - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (drop (i32.load (i32.const 4))) - (drop (i32.load align=1 (i32.const 8))) - (drop (i32.load align=2 (i32.const 12))) - (i32.store (i32.const 16) (i32.const 28)) - (i32.store align=1 (i32.const 20) (i32.const 32)) - (i32.store align=2 (i32.const 24) (i32.const 36)) - ) -) diff -Nru binaryen-108/test/lit/passes/denan.wast binaryen-99/test/lit/passes/denan.wast --- binaryen-108/test/lit/passes/denan.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/denan.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,271 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --denan -S -o - | filecheck %s - -(module - ;; CHECK: (type $f32_=>_f32 (func (param f32) (result f32))) - - ;; CHECK: (type $f64_=>_f64 (func (param f64) (result f64))) - - ;; CHECK: (type $i32_f32_i64_f64_=>_none (func (param i32 f32 i64 f64))) - - ;; CHECK: (type $f32_f64_=>_none (func (param f32 f64))) - - ;; CHECK: (global $global$1 (mut f32) (f32.const 0)) - (global $global$1 (mut f32) (f32.const nan)) - ;; CHECK: (global $global$2 (mut f32) (f32.const 12.34000015258789)) - (global $global$2 (mut f32) (f32.const 12.34)) - ;; CHECK: (func $foo32 (param $x f32) (result f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (call $foo32 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo32 (param $x f32) (result f32) - (call $foo32 (local.get $x)) - ) - ;; CHECK: (func $foo64 (param $x f64) (result f64) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $deNan64 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $deNan64 - ;; CHECK-NEXT: (call $foo64 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo64 (param $x f64) (result f64) - (call $foo64 (local.get $x)) - ) - ;; CHECK: (func $various (param $x i32) (param $y f32) (param $z i64) (param $w f64) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (call $deNan64 - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $various (param $x i32) (param $y f32) (param $z i64) (param $w f64) - ) - ;; CHECK: (func $ignore-local.get (param $f f32) (param $d f64) - ;; CHECK-NEXT: (local.set $f - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (call $deNan64 - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $f - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $deNan64 - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $f - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (call $deNan64 - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ignore-local.get (param $f f32) (param $d f64) - (drop (local.get $f)) - (drop (local.get $d)) - (local.set $f (local.get $f)) - (local.set $d (local.get $d)) - (drop (local.get $f)) - (drop (local.get $d)) - (drop (f32.abs (local.get $f))) - (drop (f64.abs (local.get $d))) - (local.set $f (f32.abs (local.get $f))) - (local.set $d (f64.abs (local.get $d))) - (drop (local.get $f)) - (drop (local.get $d)) - ) - ;; CHECK: (func $tees (param $x f32) (result f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $tees (param $x f32) (result f32) - (local.tee $x - (local.tee $x - (local.tee $x - (local.tee $x - (local.get $x)))))) - ;; CHECK: (func $select (param $x f32) (result f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $deNan32 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select (param $x f32) (result f32) - (select - (local.get $x) - (local.get $x) - (i32.const 1))) -) -;; existing names should not be a problem -;; CHECK: (func $deNan32 (param $0 f32) (result f32) -;; CHECK-NEXT: (if (result f32) -;; CHECK-NEXT: (f32.eq -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (f32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $deNan64 (param $0 f64) (result f64) -;; CHECK-NEXT: (if (result f64) -;; CHECK-NEXT: (f64.eq -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (f64.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $f32_=>_f32 (func (param f32) (result f32))) - - ;; CHECK: (type $f64_=>_f64 (func (param f64) (result f64))) - - ;; CHECK: (func $deNan32 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $deNan32) - ;; CHECK: (func $deNan64 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $deNan64) - ;; CHECK: (func $foo32 (param $x f32) (result f32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $deNan32_0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $deNan32_0 - ;; CHECK-NEXT: (call $foo32 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo32 (param $x f32) (result f32) - (call $foo32 (local.get $x)) - ) - ;; CHECK: (func $foo64 (param $x f64) (result f64) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $deNan64_0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $deNan64_0 - ;; CHECK-NEXT: (call $foo64 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo64 (param $x f64) (result f64) - (call $foo64 (local.get $x)) - ) - -) -;; CHECK: (func $deNan32_0 (param $0 f32) (result f32) -;; CHECK-NEXT: (if (result f32) -;; CHECK-NEXT: (f32.eq -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (f32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $deNan64_0 (param $0 f64) (result f64) -;; CHECK-NEXT: (if (result f64) -;; CHECK-NEXT: (f64.eq -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (f64.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/directize_all-features.wast binaryen-99/test/lit/passes/directize_all-features.wast --- binaryen-108/test/lit/passes/directize_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/directize_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,906 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --directize --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo) - - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - ;; helper function - (unreachable) - ) - - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - ;; CHECK: (table $1 5 5 funcref) - (table $1 5 5 funcref) - (elem (table $0) (i32.const 1) func $dummy) - (elem (table $1) (i32.const 1) func $f) - ;; CHECK: (elem $0 (table $0) (i32.const 1) func $dummy) - - ;; CHECK: (elem $1 (table $1) (i32.const 1) func $f) - - ;; CHECK: (func $dummy (param $0 i32) (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $dummy (param i32) (result i32) - (local.get 0) - ) - ;; CHECK: (func $f (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $f (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $g (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call $f - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $g (param $x i32) (param $y i32) - (call_indirect $1 (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -;; at table edges -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - ;; CHECK: (table $1 5 5 funcref) - (table $1 5 5 funcref) - (elem (table $1) (i32.const 4) func $foo) - ;; CHECK: (elem (table $1) (i32.const 4) func $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect $1 (type $ii) - (local.get $x) - (local.get $y) - (i32.const 4) - ) - ) -) - -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 0) $foo) - ;; CHECK: (elem (i32.const 0) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 0) - ) - ) -) - -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - ;; CHECK: (table $1 5 5 funcref) - (table $1 5 5 funcref) - (elem (i32.const 0) $foo $foo $foo $foo $foo) - (elem (table $1) (i32.const 0) func $foo $foo $foo $foo $foo) - ;; CHECK: (elem $0 (table $0) (i32.const 0) func $foo $foo $foo $foo $foo) - - ;; CHECK: (elem $1 (table $1) (i32.const 0) func $foo $foo $foo $foo $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect $1 (type $ii) - (local.get $x) - (local.get $y) - (i32.const 2) - ) - ) -) - -;; imported table -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (import "env" "table" (table $table 5 5 funcref)) - (import "env" "table" (table $table 5 5 funcref)) - (elem (i32.const 1) $foo) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call_indirect $table (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -;; exported table -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (export "tab" (table $0)) - (export "tab" (table $0)) - (elem (i32.const 1) $foo) - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -;; non-constant table offset -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (global $g (mut i32) (i32.const 1)) - - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (global $g (mut i32) (i32.const 1)) - (elem (global.get $g) $foo) - ;; CHECK: (elem (global.get $g) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (global $g (mut i32) (i32.const 1)) - - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - ;; CHECK: (table $1 5 5 funcref) - (table $1 5 5 funcref) - (global $g (mut i32) (i32.const 1)) - (elem (table $1) (global.get $g) func $foo) - ;; CHECK: (elem (table $1) (global.get $g) func $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call_indirect $1 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect $1 (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -;; non-constant call index -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) (param $z i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (local.get $z) - ) - ) -) - -;; bad index -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 5) - ) - ) -) - -;; missing index -(module - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 2) - ) - ) -) - -;; bad type -(module - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -;; no table -(module - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (func $foo (param $0 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) - (unreachable) - ) -) - -;; change types -(module - (type (func)) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (table $0 8 8 funcref) - (table $0 8 8 funcref) - ;; CHECK: (func $0 - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (block ;; the type of this block will change - (nop) - (call_indirect (type 0) - (i32.const 15) - ) - ) - ) -) - -(module ;; indirect tail call - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo) - ;; CHECK: (elem (i32.const 1) $foo) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $bar (param $x i32) (param $y i32) - ;; CHECK-NEXT: (return_call $foo - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) (param $y i32) - (return_call_indirect (type $ii) - (local.get $x) - (local.get $y) - (i32.const 1) - ) - ) -) - -(module - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - ;; CHECK: (table $0 5 5 funcref) - (table $0 5 5 funcref) - (elem (i32.const 1) $foo1 $foo2) - ;; CHECK: (elem (i32.const 1) $foo1 $foo2) - - ;; CHECK: (func $foo1 (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo1 (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $foo2 (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo2 (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $select (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (call $foo1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo2 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select (param $x i32) (param $y i32) (param $z i32) - ;; Test we can optimize a call_indirect whose index is a select between two - ;; constants. We can emit an if and two direct calls for that. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (i32.const 1) - (i32.const 2) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $select-bad-1 (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-bad-1 (param $x i32) (param $y i32) (param $z i32) - ;; As above but one select arm is not constant. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (local.get $z) - (i32.const 2) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $select-bad-2 (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-bad-2 (param $x i32) (param $y i32) (param $z i32) - ;; As above but the other select arm is not constant. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (i32.const 2) - (local.get $z) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $select-out-of-range (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo2 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-out-of-range (param $x i32) (param $y i32) (param $z i32) - ;; Both are constants, but one is out of range for the table, and there is no - ;; valid function to call there; emit an unreachable. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (i32.const 99999) - (i32.const 2) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $select-both-out-of-range (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-both-out-of-range (param $x i32) (param $y i32) (param $z i32) - ;; Both are constants, and both are out of range for the table. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (i32.const 99999) - (i32.const -1) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $select-unreachable-operand (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-unreachable-operand (param $x i32) (param $y i32) (param $z i32) - ;; One operand is unreachable. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (unreachable) - (i32.const 2) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $select-unreachable-condition (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-unreachable-condition (param $x i32) (param $y i32) (param $z i32) - ;; The condition is unreachable. We should not even create any vars here, and - ;; just not do anything. - (call_indirect (type $ii) - (local.get $x) - (local.get $y) - (select - (i32.const 1) - (i32.const 2) - (unreachable) - ) - ) - ) -) - -(module - ;; CHECK: (type $F (func (param (ref func)))) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (table $0 15 15 funcref) - (table $0 15 15 funcref) - (type $F (func (param (ref func)))) - (elem (i32.const 10) $foo-ref $foo-ref) - - ;; CHECK: (elem (i32.const 10) $foo-ref $foo-ref) - - ;; CHECK: (elem declare func $select-non-nullable) - - ;; CHECK: (func $foo-ref (param $0 (ref func)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo-ref (param (ref func)) - ;; helper function - (unreachable) - ) - - ;; CHECK: (func $select-non-nullable (param $x i32) - ;; CHECK-NEXT: (local $1 (ref null $i32_=>_none)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.func $select-non-nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $foo-ref - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo-ref - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-non-nullable (param $x i32) - ;; Test we can handle a non-nullable value when optimizing a select, during - ;; which we place values in locals. - (call_indirect (type $F) - (ref.func $select-non-nullable) - (select - (i32.const 10) - (i32.const 11) - (local.get $x) - ) - ) - ) - - ;; CHECK: (func $select-non-nullable-unreachable-condition - ;; CHECK-NEXT: (call_indirect $0 (type $F) - ;; CHECK-NEXT: (ref.func $select-non-nullable) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-non-nullable-unreachable-condition - ;; Test we ignore an unreachable condition and don't make any changes at all - ;; to the code (in particular, we shouldn't add any vars). - (call_indirect (type $F) - (ref.func $select-non-nullable) - (select - (i32.const 10) - (i32.const 11) - (unreachable) - ) - ) - ) - - ;; CHECK: (func $select-non-nullable-unreachable-arg (param $x i32) - ;; CHECK-NEXT: (call_indirect $0 (type $F) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-non-nullable-unreachable-arg (param $x i32) - ;; Test we ignore an unreachable argument and don't make any changes at all - ;; to the code (in particular, we shouldn't add any vars). - (call_indirect (type $F) - (unreachable) - (select - (i32.const 10) - (i32.const 11) - (local.get $x) - ) - ) - ) -) - -;; A table.set prevents optimization. -(module - ;; CHECK: (type $v (func)) - (type $v (func)) - - ;; CHECK: (table $has-set 5 5 funcref) - (table $has-set 5 5 funcref) - - ;; CHECK: (table $no-set 5 5 funcref) - (table $no-set 5 5 funcref) - - ;; CHECK: (elem $0 (table $has-set) (i32.const 1) func $foo) - (elem $0 (table $has-set) (i32.const 1) $foo) - - ;; CHECK: (elem $1 (table $no-set) (i32.const 1) func $foo) - (elem $1 (table $no-set) (i32.const 1) $foo) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (table.set $has-set - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - ;; Technically this set writes the same value as is already there, but the - ;; analysis will give up on optimizing when it sees any set to a table. - (table.set $has-set - (i32.const 1) - (ref.func $foo) - ) - ) - - ;; CHECK: (func $bar - ;; CHECK-NEXT: (call_indirect $has-set (type $v) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $bar - ;; We can't optimize this one, but we can the one after it. - (call_indirect $has-set (type $v) - (i32.const 1) - ) - (call_indirect $no-set (type $v) - (i32.const 1) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/extract-function.wast binaryen-99/test/lit/passes/extract-function.wast --- binaryen-108/test/lit/passes/extract-function.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/extract-function.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --extract-function=foo -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --extract-function --pass-arg=extract-function@foo -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --extract-function-index=0 -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --extract-function-index --pass-arg=extract-function-index@0 -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "bar" (func $bar)) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: ) - (func $foo - (call $bar) - ) - - (func $bar - (call $foo) - ) - - (func $other - (drop (i32.const 1)) - ) -) - -(module - ;; Use another function in the table, but the table is not used in the - ;; extracted function - (table $t 10 funcref) - - (elem $0 (table $t) (i32.const 0) func $other) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "other" (func $other)) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo - (nop) - ) - - (func $other - (drop (i32.const 1)) - ) -) - -(module - ;; Use another function in the table, and the table *is* used. As a result, - ;; the table and its elements will remain. The called function, $other, will - ;; remain as an import that is placed in the table. - - ;; CHECK: (type $none (func)) - (type $none (func)) - - ;; CHECK: (import "env" "other" (func $other)) - - ;; CHECK: (table $t 10 funcref) - (table $t 10 funcref) - - ;; CHECK: (elem $0 (i32.const 0) $other) - (elem $0 (table $t) (i32.const 0) func $other) - - ;; Test that an existing export does not cause us to crash. - ;; CHECK: (export "foo" (func $foo)) - (export "foo" (func $foo)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (call_indirect (type $none) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (call_indirect (type $none) (i32.const 10)) - ) - - (func $other - (drop (i32.const 1)) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten_all-features.wast binaryen-99/test/lit/passes/flatten_all-features.wast --- binaryen-108/test/lit/passes/flatten_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,3534 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (type $2 (func (result i32))) - - ;; CHECK: (type $1 (func)) - - ;; CHECK: (type $ii (func (param i32 i32))) - (type $ii (func (param i32 i32))) - (type $1 (func)) - (type $2 (func (result i32))) - ;; CHECK: (type $3 (func (param i32) (result i32))) - (type $3 (func (param i32) (result i32))) - ;; CHECK: (type $none_=>_f32 (func (result f32))) - - ;; CHECK: (type $4 (func (param i64 i64) (result i64))) - (type $4 (func (param i64 i64) (result i64))) - ;; CHECK: (type $none_=>_anyref (func (result anyref))) - - ;; CHECK: (global $x (mut i32) (i32.const 0)) - (global $x (mut i32) (i32.const 0)) - (table 1 1 funcref) - (elem (i32.const 0) $call-me) - ;; CHECK: (memory $0 10) - (memory $0 10) - ;; CHECK: (table $0 1 1 funcref) - - ;; CHECK: (elem (i32.const 0) $call-me) - - ;; CHECK: (func $a1 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a1 - (drop (i32.add (i32.const 0) (i32.const 1))) - ) - ;; CHECK: (func $a2 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a2 (result i32) - (i32.add (i32.const 0) (i32.const 1)) - ) - ;; CHECK: (func $a3 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a3 (result i32) - (i32.add - (i32.const 0) - (block (result i32) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $a4 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a4 - (drop - (i32.add - (i32.const 0) - (block (result i32) - (i32.const 1) - ) - ) - ) - ) - ;; CHECK: (func $a5 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a5 (result i32) - (i32.add - (block (result i32) - (i32.const 0) - ) - (block (result i32) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $a6 (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a6 (result i32) - (local $x i32) - (i32.add - (block (result i32) - (local.tee $x - (i32.const 0) - ) - ) - (block (result i32) - (local.tee $x - (i32.const 1) - ) - ) - ) - ) - ;; CHECK: (func $a7 (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block $block2 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a7 (result i32) - (local $x i32) - (block (result i32) - (i32.add - (block (result i32) - (local.tee $x - (i32.const 0) - ) - ) - (block (result i32) - (local.tee $x - (i32.const 1) - ) - ) - ) - ) - ) - ;; CHECK: (func $a8 (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block $outer - ;; CHECK-NEXT: (block $inner - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $inner) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block4 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a8 (result i32) - (local $x i32) - (block $outer (result i32) - (block $inner (result i32) - (i32.add - (block (result i32) - (br $inner - (i32.const -1) - ) - (br $outer - (i32.const 0) - ) - (i32.const 1) - ) - (block (result i32) - (br $outer - (i32.const 2) - ) - (local.tee $x - (i32.const 3) - ) - ) - ) - ) - ) - ) - ;; CHECK: (func $a9 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (loop $outer - ;; CHECK-NEXT: (loop $inner - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $outer - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a9 (result i32) - (loop $outer (result i32) - (loop $inner (result i32) - (br_if $outer (i32.const -1)) - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - ) - ) - ;; CHECK: (func $a10 (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block $outer - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $outer - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $outer - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $outer - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $outer - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a10 (result i32) - (local $x i32) - (block $outer (result i32) - (drop (br_if $outer (i32.const 0) (i32.const 1))) - (drop (br_if $outer (local.tee $x (i32.const 2)) (i32.const 3))) - (drop (br_if $outer (i32.const 4) (local.tee $x (i32.const 5)))) - (drop (br_if $outer (local.tee $x (i32.const 6)) (local.tee $x (i32.const 7)))) - (br $outer (i32.const 8)) - ) - ) - ;; CHECK: (func $a11 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a11 - (if (i32.const 0) - (drop (i32.const 1)) - ) - ) - ;; CHECK: (func $a12 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a12 (result i32) - (if (result i32) (i32.const 0) - (i32.const 1) - (i32.const 2) - ) - ) - ;; CHECK: (func $a13 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block $x - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $x - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a13 (result i32) - (block $x i32 - (if i32 - (br_table $x (i32.const 2) (i32.const 0)) - (i32.const 0) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $a14 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $block - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a14 (result i32) - (block i32 - (select - (i32.const 0) (i32.const 1) (br_table 0 (i32.const 7) (i32.const 1)) - ) - ) - ) - ;; CHECK: (func $a15 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 53) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $a15 - (if - (i32.load16_u - (i32.const 53) - ) - (unreachable) - (drop - (block $label$3 (result f32) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $a16 (result i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a16 (result i32) - (local $x i32) - (block $label$1 (result i32) - (drop - (br_if $label$1 - (local.tee $x ;; set here, then it is undone later, but this value is used, not the contents of $x! - (i32.const 1) - ) - (i32.eqz ;; 0 into 1, so take the br_if - (block $label$2 (result i32) - (local.set $x - (i32.const 0) ;; undo the above tee - ) - (i32.const 0) - ) - ) - ) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $a17 (result f32) - ;; CHECK-NEXT: (local $var$0 f32) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local $3 f32) - ;; CHECK-NEXT: (local $4 f32) - ;; CHECK-NEXT: (local $5 f32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (f32.const -137438953472) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f32.max - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a17 (result f32) - (local $var$0 f32) - (f32.max - (local.get $var$0) - (select - (local.tee $var$0 - (f32.const -137438953472) - ) - (local.get $var$0) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $a18 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a18 (result i32) - (block $label$1 (result i32) - (i32.load16_s - (drop ;; an unreachable drop. one we move its contents outside, it should stay unreachable - (br_if $label$1 - (i32.const 1) - (unreachable) - ) - ) - ) - ) - ) - ;; CHECK: (func $a19 (result f32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (f32.const 4289944320) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $a19 (result f32) - (block $label$0 - (block $label$1 - (drop - (select - (unreachable) ;; move this out, so it happens before the return - (return - (f32.const 4289944320) - ) - (i32.const 65535) - ) - ) - ) - ) - ) - ;; CHECK: (func $call-me (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $call-me (param $0 i32) (param $1 i32) - (nop) - ) - ;; CHECK: (func $code-to-kill - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $out $out $out $out - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call $code-to-kill) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out1 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out3 - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out4 - ;; CHECK-NEXT: (br_table $out4 $out4 $out4 $out4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out5 - ;; CHECK-NEXT: (br_if $out5 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out8 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out9 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out11 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out13 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out15 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out16 - ;; CHECK-NEXT: (block $in - ;; CHECK-NEXT: (br_if $out16 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block11 - ;; CHECK-NEXT: (block $out18 - ;; CHECK-NEXT: (block $in19 - ;; CHECK-NEXT: (br_if $in19 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out20 - ;; CHECK-NEXT: (block $in21 - ;; CHECK-NEXT: (br_table $out20 $in21 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out22 - ;; CHECK-NEXT: (block $in23 - ;; CHECK-NEXT: (br_table $in23 $out22 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block13 - ;; CHECK-NEXT: (block $out25 - ;; CHECK-NEXT: (block $in26 - ;; CHECK-NEXT: (br_table $in26 $in26 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block15 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (loop $loop-in18 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out29 - ;; CHECK-NEXT: (loop $in30 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $out29 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block20 - ;; CHECK-NEXT: (loop $in32 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $in32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call $call-me - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call $call-me - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call $call-me - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (i32.const 139) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (i32.const 246) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call_indirect $0 (type $ii) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 55) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 66) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 77) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 88) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 99) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $code-to-kill - (local $x i32) - (block $out - (br $out) - (drop - (i32.const 0) - ) - (if - (i32.const 1) - (drop - (i32.const 2) - ) - ) - (br_table $out $out $out $out - (i32.const 3) - ) - (call $code-to-kill) - ) - (if - (i32.const 0) - (block $out1 - (unreachable) - (drop - (i32.const 0) - ) - ) - ) - (if - (i32.const 0) - (block $out3 - (return) - (drop - (i32.const 0) - ) - ) - ) - (block $out4 - (br_table $out4 $out4 $out4 $out4 - (i32.const 4) - ) - (drop - (i32.const 0) - ) - ) - (block $out5 - (br_if $out5 - (i32.const 3) - ) - (drop - (i32.const 0) - ) - ) - (if - (i32.const 0) - (block $block4 - (if - (i32.const 0) - (block $out8 - (unreachable) - (drop - (i32.const 0) - ) - ) - (block $out9 - (unreachable) - (drop - (i32.const 0) - ) - ) - ) - (drop - (i32.const 0) - ) - ) - ) - (if - (i32.const 0) - (drop - (block $out11 (result i32) - (br $out11 - (unreachable) - ) - (drop - (i32.const 0) - ) - (unreachable) - ) - ) - ) - (if - (i32.const 0) - (drop - (block $out13 (result i32) - (br_if $out13 - (unreachable) - (i32.const 0) - ) - (drop - (i32.const 0) - ) - (unreachable) - ) - ) - ) - (if - (i32.const 0) - (drop - (block $out15 (result i32) - (br_if $out15 - (unreachable) - (unreachable) - ) - (drop - (i32.const 0) - ) - (unreachable) - ) - ) - ) - (block $out16 - (block $in - (br_if $out16 - (i32.const 1) - ) - ) - (unreachable) - ) - (if - (i32.const 0) - (block $block11 - (block $out18 - (block $in19 - (br_if $in19 - (i32.const 1) - ) - ) - (unreachable) - ) - (drop - (i32.const 10) - ) - ) - ) - (block $out20 - (block $in21 - (br_table $out20 $in21 - (i32.const 1) - ) - ) - (unreachable) - ) - (block $out22 - (block $in23 - (br_table $in23 $out22 - (i32.const 1) - ) - ) - (unreachable) - ) - (if - (i32.const 0) - (block $block13 - (block $out25 - (block $in26 - (br_table $in26 $in26 - (i32.const 1) - ) - ) - (unreachable) - ) - (drop - (i32.const 10) - ) - ) - ) - (if - (i32.const 0) - (block $block15 - (drop - (i32.const 10) - ) - (drop - (i32.const 42) - ) - (unreachable) - (return - (unreachable) - ) - (unreachable) - (return) - ) - ) - (if - (i32.const 0) - (loop $loop-in18 - (unreachable) - ) - ) - (block $out29 - (loop $in30 - (br_if $out29 - (i32.const 1) - ) - (unreachable) - ) - ) - (if - (i32.const 0) - (block $block20 - (loop $in32 - (br_if $in32 - (i32.const 1) - ) - (unreachable) - ) - (drop - (i32.const 10) - ) - ) - ) - (if - (i32.const 1) - (call $call-me - (i32.const 123) - (unreachable) - ) - ) - (if - (i32.const 2) - (call $call-me - (unreachable) - (i32.const 0) - ) - ) - (if - (i32.const 3) - (call $call-me - (unreachable) - (unreachable) - ) - ) - (if - (i32.const -1) - (call_indirect (type $ii) - (i32.const 123) - (i32.const 456) - (unreachable) - ) - ) - (if - (i32.const -2) - (call_indirect (type $ii) - (i32.const 139) - (unreachable) - (i32.const 0) - ) - ) - (if - (i32.const -3) - (call_indirect (type $ii) - (i32.const 246) - (unreachable) - (unreachable) - ) - ) - (if - (i32.const -4) - (call_indirect (type $ii) - (unreachable) - (unreachable) - (unreachable) - ) - ) - (if - (i32.const 11) - (local.set $x - (unreachable) - ) - ) - (if - (i32.const 22) - (drop - (i32.load - (unreachable) - ) - ) - ) - (if - (i32.const 33) - (i32.store - (i32.const 0) - (unreachable) - ) - ) - (if - (i32.const 44) - (i32.store - (unreachable) - (i32.const 0) - ) - ) - (if - (i32.const 55) - (i32.store - (unreachable) - (unreachable) - ) - ) - (if - (i32.const 66) - (drop - (i32.eqz - (unreachable) - ) - ) - ) - (if - (i32.const 77) - (drop - (i32.add - (unreachable) - (i32.const 0) - ) - ) - ) - (if - (i32.const 88) - (drop - (i32.add - (i32.const 0) - (unreachable) - ) - ) - ) - (if - (i32.const 99) - (i32.add - (unreachable) - (unreachable) - ) - ) - (if - (i32.const 100) - (drop - (select - (i32.const 123) - (i32.const 456) - (unreachable) - ) - ) - ) - (if - (i32.const 101) - (drop - (select - (i32.const 123) - (unreachable) - (i32.const 456) - ) - ) - ) - (if - (i32.const 102) - (drop - (select - (unreachable) - (i32.const 123) - (i32.const 456) - ) - ) - ) - (drop - (i32.const 1337) - ) - ) - ;; CHECK: (func $killer - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $killer (type $1) - (unreachable) - (drop - (i32.const 1000) - ) - ) - ;; CHECK: (func $target - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $target (type $1) - (drop - (i32.const 2000) - ) - ) - ;; CHECK: (func $typed-block-none-then-unreachable (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $top-typed - ;; CHECK-NEXT: (block $switch$0 - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br $switch$0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $typed-block-none-then-unreachable (type $2) (result i32) - (block $top-typed (result i32) - (block $switch$0 - (return - (i32.const 0) - ) - (br $switch$0) - ) - (return - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $switch$7 - ;; CHECK-NEXT: (block $switch-default$10 - ;; CHECK-NEXT: (block $switch-case$9 - ;; CHECK-NEXT: (block $switch-case$8 - ;; CHECK-NEXT: (br_table $switch-case$9 $switch-case$8 $switch-default$10 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $$$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br $switch$7) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $$$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $typed-block-remove-br-changes-type (type $3) (param $$$0 i32) (result i32) - (block $switch$7 - (block $switch-default$10 - (block $switch-case$9 - (block $switch-case$8 - (br_table $switch-case$9 $switch-case$8 $switch-default$10 - (i32.const -1) - ) - ) - ) - (return - (local.get $$$0) - ) - (br $switch$7) - ) - (return - (local.get $$$0) - ) - ) - (return - (i32.const 0) - ) - ) - ;; CHECK: (func $global - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $global (type $1) - (unreachable) - (drop - (global.get $x) - ) - (global.set $x - (i32.const 1) - ) - ) - ;; CHECK: (func $ret (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ret (type $2) (result i32) - (return - (i32.const 0) - ) - (nop) - (i32.const 0) - ) - ;; CHECK: (func $unreachable-br (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-br (type $2) (result i32) - (block $out (result i32) - (br $out - (br $out - (i32.const 0) - ) - ) - ) - ) - ;; CHECK: (func $unreachable-br-loop (result i32) - ;; CHECK-NEXT: (loop $out - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $unreachable-br-loop (type $2) (result i32) - (loop $out - (br $out) - ) - ) - ;; CHECK: (func $unreachable-block-ends-switch (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_table $label$3 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-block-ends-switch (type $2) (result i32) - (block $label$0 (result i32) - (block $label$3 - (nop) - (br_table $label$3 - (unreachable) - ) - (unreachable) - ) - (i32.const 19) - ) - ) - ;; CHECK: (func $unreachable-block-ends-br_if (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-block-ends-br_if (result i32) - (block $label$0 (result i32) - (block $label$2 - (nop) - (br_if $label$2 - (unreachable) - ) - (unreachable) - ) - (i32.const 19) - ) - ) - ;; CHECK: (func $unreachable-brs-3 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$0) - ;; CHECK-NEXT: (memory.grow - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-brs-3 (result i32) - (block $label$0 (result i32) - (br $label$0 - (memory.grow - (br $label$0 - (i32.const 18) - ) - ) - ) - (i32.const 21) - ) - ) - ;; CHECK: (func $unreachable-brs-4 (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 4104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$0 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-brs-4 (param $var$0 i32) (result i32) - (i32.add - (i32.const 1) - (block $label$0 (result i32) - (br $label$0 - (block $label$1 (result i32) - (drop - (br_if $label$0 - (i32.const 4104) - (unreachable) - ) - ) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ;; CHECK: (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i64) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i64) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i64) - ;; CHECK-NEXT: (local $15 i64) - ;; CHECK-NEXT: (local $16 i64) - ;; CHECK-NEXT: (local $17 i64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $call-unreach - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) - (local $2 i64) - (if (result i64) - (i64.eqz - (local.get $var$0) - ) - (block $label$0 (result i64) - (local.get $var$1) - ) - (block $label$1 (result i64) - (call $call-unreach - (i64.sub - (local.get $var$0) - (i64.const 1) - ) - (i64.mul - (block $block (result i64) - (local.set $2 - (local.get $var$0) - ) - (nop) - (local.get $2) - ) - (unreachable) - ) - ) - ) - ) - ) - - ;; flatten-specific - ;; CHECK: (func $test-flatten - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i32) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i32) - ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (local $24 i32) - ;; CHECK-NEXT: (local $25 i32) - ;; CHECK-NEXT: (local $26 i32) - ;; CHECK-NEXT: (local $27 i32) - ;; CHECK-NEXT: (local $28 i32) - ;; CHECK-NEXT: (local $29 i32) - ;; CHECK-NEXT: (local $30 i32) - ;; CHECK-NEXT: (local $31 i32) - ;; CHECK-NEXT: (local $32 i32) - ;; CHECK-NEXT: (local $33 i32) - ;; CHECK-NEXT: (local $34 i32) - ;; CHECK-NEXT: (local $35 i32) - ;; CHECK-NEXT: (local $36 i32) - ;; CHECK-NEXT: (local $37 i32) - ;; CHECK-NEXT: (local $38 i32) - ;; CHECK-NEXT: (local $39 i32) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_table $out $out $out $out - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $in - ;; CHECK-NEXT: (block $switch-in - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $in $switch-in $in - ;; CHECK-NEXT: (i32.const 777) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $in) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop-in - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $21 - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $22 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (local.set $23 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $23 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $24 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $25 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (local.set $26 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $26 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $27 - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (local.set $28 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $28 - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $29 - ;; CHECK-NEXT: (local.get $28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $30 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (local.get $29) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (local.set $31 - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $31 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $32 - ;; CHECK-NEXT: (local.get $31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $32) - ;; CHECK-NEXT: (local.set $35 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (local.set $33 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $33 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $34 - ;; CHECK-NEXT: (local.get $33) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $35 - ;; CHECK-NEXT: (local.get $34) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $36 - ;; CHECK-NEXT: (local.get $35) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $temp - ;; CHECK-NEXT: (local.set $37 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $temp - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $38 - ;; CHECK-NEXT: (local.get $37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $37 - ;; CHECK-NEXT: (local.get $38) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $39 - ;; CHECK-NEXT: (local.get $37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $39) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test-flatten - (block $out - (drop (i32.add (i32.const 1) (i32.const 2))) - (drop (i32.add (i32.const 1) (br $out))) - (drop (i32.add (br $out) (i32.const 1))) - (drop (i32.add (i32.const 1) (br_table $out $out $out $out (i32.const 3)))) - (drop (i32.add (i32.const 1) - (block (result i32) - (drop (i32.const 2)) - (drop (i32.const 3)) - (i32.const 4) - ) - )) - (drop (i32.add (i32.const 1) - (block $in (result i32) - (drop - (block $switch-in (result i32) - (br_table $in $switch-in $in (i32.const 2) (i32.const 777)) - ) - ) - (br $in (i32.const 3)) - (i32.const 4) - ) - )) - (drop (i32.add (i32.const 1) - (loop (result i32) - (i32.const 5) - ) - )) - (drop (i32.add (i32.const 1) - (if (result i32) - (i32.const 6) - (i32.const 7) - (i32.const 8) - ) - )) - (drop - (select - (i32.const 9) - (i32.const 10) - (i32.const 11) - ) - ) - (drop - (select - (br $out) - (i32.const 10) - (i32.const 11) - ) - ) - (drop - (select - (i32.const 9) - (br $out) - (i32.const 11) - ) - ) - (drop - (select - (i32.const 9) - (i32.const 10) - (br $out) - ) - ) - (drop - (select - (if (result i32) - (i32.const 11) - (i32.const 12) - (i32.const 13) - ) - (i32.const 9) - (i32.const 10) - ) - ) - (drop - (select - (i32.const 9) - (if (result i32) - (i32.const 11) - (i32.const 12) - (i32.const 13) - ) - (i32.const 10) - ) - ) - (drop - (select - (i32.const 9) - (i32.const 10) - (if (result i32) - (i32.const 11) - (i32.const 12) - (i32.const 13) - ) - ) - ) - (drop - (select - (if (result i32) - (i32.const 11) - (i32.const 12) - (i32.const 13) - ) - (i32.const 14) - (if (result i32) - (i32.const 15) - (i32.const 16) - (i32.const 17) - ) - ) - ) - (drop (i32.add (i32.const 1) (return))) - (drop (i32.add (i32.const 1) (unreachable))) - (drop - (if (result i32) - (if (result i32) - (i32.const 5) - (i32.const 6) - (i32.const 7) - ) - (i32.const 8) - (if (result i32) - (i32.const 9) - (i32.const 10) - (i32.const 11) - ) - ) - ) - (drop - (block $temp (result i32) - (br_if $temp - (i32.const 1) - (i32.const 2) - ) - ) - ) - ) - ) - ;; CHECK: (func $flatten-return-value (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $flatten-return-value (result i32) - (drop (i32.add (i32.const 1) (return (i32.const 2)))) - (i32.const 3) - ) - ;; CHECK: (func $unbug - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $432 i32) - ;; CHECK-NEXT: (local $430 i32) - ;; CHECK-NEXT: (local $431 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $433 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i32) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block $block44 - ;; CHECK-NEXT: (block $label$78 - ;; CHECK-NEXT: (local.set $430 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $430) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $432 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block45 - ;; CHECK-NEXT: (block $label$79 - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.load16_u offset=2 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $431 - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (local.get $431) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $432 - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $433 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (local.get $432) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (local.get $433) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $21 - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $22 - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unbug - (local $12 i32) - (local $432 i32) - (local $430 i32) - (local $431 i32) - (local $9 i32) - (local $5 i32) - (local $433 i32) - (drop - (block (result i32) - (if - (i32.eq - (local.get $12) - (i32.const 65535) - ) - (block - (block $label$78 - (local.set $430 - (i32.const 0) - ) - ) - (local.set $432 - (local.get $430) - ) - ) - (block - (block $label$79 - (local.set $431 - (i32.lt_u - (local.get $9) - (i32.load16_u offset=2 - (i32.add - (local.get $5) - (i32.mul - (local.get $12) - (i32.const 12) - ) - ) - ) - ) - ) - ) - (local.set $432 - (local.get $431) - ) - ) - ) - (local.set $433 - (i32.const 1) - ) - (i32.xor - (local.get $432) - (local.get $433) - ) - ) - ) - ) - ;; CHECK: (func $outer-block-typed (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $outer-block-typed (type $3) (param $var$0 i32) (result i32) - (block (result i32) - (i32.add - (i32.const 1) - (block $label$0 (result i32) - (i32.const 16) - ) - ) - ) - ) - ;; CHECK: (func $nested-br_if-with-value (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block $label$0 - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-br_if-with-value (result i32) - (local $0 i32) - (block $label$0 (result i32) - (drop - (br_if $label$0 - (i32.const 0) - (block (result i32) - (local.get $0) - ) - ) - ) - (i32.const 1) - ) - ) - ;; CHECK: (func $switch-unreachable - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (br_table $label$3 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $switch-unreachable - (block $label$3 - (br_table $label$3 - (unreachable) - ) - ) - ) - ;; CHECK: (func $br_if_order (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block $outer - ;; CHECK-NEXT: (block $inner - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $outer - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (call $br_if_order - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $inner - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_if_order (param $x i32) (result i32) - (block $outer (result i32) - (block $inner (result i32) - (br_if $inner - (br_if $outer - (i32.const 0) - (i32.const 1) - ) - (call $br_if_order - (block (result i32) - (i32.const -16) - ) - ) - ) - ) - ) - ) - ;; CHECK: (func $tees (param $x i32) (param $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $tees (param $x i32) (param $y i32) - (drop (local.tee $x (i32.const 1))) - (drop (local.tee $x (unreachable))) - (drop (local.tee $y (local.tee $x (i32.const 2)))) - ) - ;; CHECK: (func $return (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $return (param $x i32) (result i32) - (return (i32.sub (i32.const 1) (i32.const 2))) - ) - - ;; subtypes - - ;; br_if leaves a value on the stack if not taken, which later can be the last - ;; element of the enclosing innermost block and flow out. So in case br_if - ;; targets an outer branch whose return type is a supertype of the br_if's - ;; value type, we need the value to be set into two locals: one with the outer - ;; block's type, and one with its value type. - ;; CHECK: (func $subtype (result anyref) - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (local $2 anyref) - ;; CHECK-NEXT: (local $3 anyref) - ;; CHECK-NEXT: (local $4 anyref) - ;; CHECK-NEXT: (local $5 anyref) - ;; CHECK-NEXT: (local $6 anyref) - ;; CHECK-NEXT: (block $label0 - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subtype (result anyref) - (local $0 externref) - (block $label0 (result anyref) - (block (result externref) - (local.tee $0 - (br_if $label0 - (ref.null extern) - (i32.const 0) - ) - ) - ) - ) - ) -) -(module - ;; CHECK: (type $i64_f32_=>_none (func (param i64 f32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (export "test" (func $1)) - - ;; CHECK: (func $0 (param $0 i64) (param $1 f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $0 (param $0 i64) (param $1 f32) - (nop) - ) - (func "test" (result i32) - (call $0 - (unreachable) ;; the unreachable should be handled properly, and not be - ;; reordered with the return - (return - (i32.const -111) - ) - ) - ) -) -;; non-nullable temp vars we add must be handled properly, as non-nullable -;; locals are not allowed -;; CHECK: (func $1 (result i32) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: (return -;; CHECK-NEXT: (i32.const -111) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $0 -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $none_=>_none (func)) - (type $none_=>_none (func)) - ;; CHECK: (type $none_=>_funcref (func (result funcref))) - - ;; CHECK: (func $0 (result funcref) - ;; CHECK-NEXT: (local $0 (ref null $none_=>_none)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $none_=>_none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (result funcref) - (ref.as_non_null - (ref.null $none_=>_none) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten_dfo_O3_enable-threads.wast binaryen-99/test/lit/passes/flatten_dfo_O3_enable-threads.wast --- binaryen-108/test/lit/passes/flatten_dfo_O3_enable-threads.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_dfo_O3_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,272 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --dfo -O3 --enable-threads -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i64_i32_=>_f64 (func (param i64 i32) (result f64))) - - ;; CHECK: (type $f64_=>_f64 (func (param f64) (result f64))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (memory $0 (shared 1 1)) - (memory $0 (shared 1 1)) - (func "one" - (loop $label$2 - (br_if $label$2 - (block $label$3 (result i32) - (drop - (br_if $label$3 - (i32.const 0) - (i32.load - (i32.const 3060) - ) - ) - ) - (i32.const 0) - ) - ) - ) - (unreachable) - ) - (func "two" (param $var$0 i32) (param $var$1 i32) (result i32) - (nop) - (nop) - (nop) - (nop) - (nop) - (if - (i32.const 0) - (i32.store8 - (i32.const 8) - (block $label$2 (result i32) - (drop - (br_if $label$2 - (i32.const 1) - (i32.const 0) - ) - ) - (if - (i32.const 0) - (drop - (br_if $label$2 - (i32.const 1) - (i32.const 1) - ) - ) - ) - (block $label$4 - (br_if $label$4 - (i32.const 0) - ) - (br_if $label$4 - (i32.const 0) - ) - (drop - (br_if $label$2 - (i32.const 1) - (i32.const 0) - ) - ) - ) - (i32.const 6704) - ) - ) - ) - (nop) - (i32.const 0) - ) - (func "use-var" (param $var$0 i64) (param $var$1 i32) (result f64) - (local $var$2 i32) - (block $label$1 - (br_table $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 - (i32.wrap_i64 - (if (result i64) - (i32.const 0) - (i64.const 1) - (if (result i64) - (if (result i32) - (i32.const 0) - (unreachable) - (block $label$6 (result i32) - (block $label$7 - (loop $label$8 - (br_if $label$8 - (br_if $label$6 - (local.tee $var$2 - (block $label$9 (result i32) - (local.get $var$1) - ) - ) - (i32.const 0) - ) - ) - (loop $label$10 - (if - (i32.const 0) - (local.set $var$2 - (local.get $var$1) - ) - ) - ) - (drop - (i32.eqz - (local.get $var$2) - ) - ) - ) - ) - (unreachable) - ) - ) - (unreachable) - (i64.const 1) - ) - ) - ) - ) - ) - (unreachable) - ) - (func "bad1" - (local $var$2 i32) - (local $var$4 i32) - (block $label$1 - (loop $label$2 - (local.set $var$4 - (if (result i32) - (i32.const 0) - (block (result i32) - (local.set $var$4 - (local.tee $var$2 - (i32.xor - (i32.const 0) - (i32.const -1) - ) - ) - ) - (i32.const 0) - ) - (block (result i32) - (local.set $var$4 - (local.tee $var$2 - (i32.xor - (i32.const 0) - (i32.const -1) - ) - ) - ) - (i32.const 0) - ) - ) - ) - (i32.store - (i32.const 1) - (i32.shl - (local.get $var$2) - (i32.const 14) - ) - ) - ) - ) - ) - (func "only-dfo" (param $var$0 f64) (result f64) - (local $var$1 i32) - (local $var$2 i32) - (loop $label$1 - (if - (local.tee $var$1 - (local.tee $var$2 - (local.get $var$1) - ) - ) - (if - (local.get $var$2) - (i64.atomic.store32 offset=3 - (i32.and - (local.get $var$1) ;; only dfo can figure out that this is 0 - (i32.const 15) - ) - (i64.const -32768) - ) - ) - ) - (br $label$1) - ) - ) - (func "dfo-tee-get" (result i32) - (local $0 i32) - (if (result i32) - (local.tee $0 - (i32.const 1) - ) - (loop $label$2 (result i32) - (select - (i32.const 1) - (i32.const -1709605511) - (local.get $0) - ) - ) - (unreachable) - ) - ) -) - -;; CHECK: (export "one" (func $0)) - -;; CHECK: (export "two" (func $1)) - -;; CHECK: (export "use-var" (func $2)) - -;; CHECK: (export "bad1" (func $3)) - -;; CHECK: (export "only-dfo" (func $4)) - -;; CHECK: (export "dfo-tee-get" (func $5)) - -;; CHECK: (func $0 (; has Stack IR ;) -;; CHECK-NEXT: (block $label$3 -;; CHECK-NEXT: (br_if $label$3 -;; CHECK-NEXT: (i32.load -;; CHECK-NEXT: (i32.const 3060) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) - -;; CHECK: (func $1 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) - -;; CHECK: (func $2 (; has Stack IR ;) (param $0 i64) (param $1 i32) (result f64) -;; CHECK-NEXT: (loop $label$8 -;; CHECK-NEXT: (br_if $label$8 -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) - -;; CHECK: (func $3 (; has Stack IR ;) -;; CHECK-NEXT: (i32.store -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: (i32.const -16384) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $4 (; has Stack IR ;) (param $0 f64) (result f64) -;; CHECK-NEXT: (local $1 i32) -;; CHECK-NEXT: (loop $label$1 -;; CHECK-NEXT: (br $label$1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $5 (; has Stack IR ;) (result i32) -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/flatten-eh.wast binaryen-99/test/lit/passes/flatten-eh.wast --- binaryen-108/test/lit/passes/flatten-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,234 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --flatten -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e-i32 (param i32)) - (tag $e-i32 (param i32)) - ;; CHECK: (tag $e-f32 (param f32)) - (tag $e-f32 (param f32)) - - ;; CHECK: (func $try_catch - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e-i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-f32 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (pop f32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try_catch (local $x i32) - ;; Basic try-catch test - (try - (do - (throw $e-i32 (i32.const 0)) - ) - (catch $e-i32 - (drop - (pop i32) - ) - ) - (catch $e-f32 - (drop - (pop f32) - ) - ) - ) - ) - - ;; CHECK: (func $try_catch_pop_fixup - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $l0 - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $l0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try_catch_pop_fixup - ;; After --flatten, a block is created within the 'catch', which makes the - ;; pop's location invalid. This tests whether it is fixed up correctly after - ;; --flatten. - (block $l0 - (try - (do) - (catch $e-i32 - (drop - (pop i32) - ) - (br $l0) - ) - ) - ) - ) - - ;; CHECK: (func $try_catch_return_value (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try_catch_return_value (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch $e-i32 - (pop i32) - ) - ) - ) - - ;; CHECK: (func $try_unreachable (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try_unreachable (result i32) - (try (result i32) - (do - (unreachable) - ) - (catch $e-i32 - (pop i32) - ) - ) - ) - - ;; CHECK: (func $catch_unreachable (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $catch_unreachable (result i32) - (try (result i32) - (do - (i32.const 3) - ) - (catch $e-i32 - (drop - (pop i32) - ) - (unreachable) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten_i64-to-i32-lowering.wast binaryen-99/test/lit/passes/flatten_i64-to-i32-lowering.wast --- binaryen-108/test/lit/passes/flatten_i64-to-i32-lowering.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_i64-to-i32-lowering.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,667 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --i64-to-i32-lowering -S -o - | filecheck %s - -(module - (memory 1 1) - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_i64 (func (result i64))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "func" (func $import (result i64))) - (import "env" "func" (func $import (result i64))) - ;; CHECK: (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $defined (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $0$hi i32) - ;; CHECK-NEXT: (local $i64toi32_i32$0 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$1 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$2 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$3 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$4 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$3 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: (local.get $i64toi32_i32$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $i64toi32_i32$4) - ;; CHECK-NEXT: (local.get $i64toi32_i32$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $i64toi32_i32$5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $i64toi32_i32$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0$hi - ;; CHECK-NEXT: (local.get $i64toi32_i32$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$5 - ;; CHECK-NEXT: (local.get $0$hi) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $i64toi32_i32$HIGH_BITS - ;; CHECK-NEXT: (local.get $i64toi32_i32$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $defined (result i64) - (i64.add (i64.const 1) (i64.const 2)) - ) - ;; CHECK: (func $unreachable-select-i64 (result i32) - ;; CHECK-NEXT: (local $i64toi32_i32$0 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $unreachable-select-i64 (result i64) - (select - (i64.const 1) - (unreachable) - (i32.const 2) - ) - ) - ;; CHECK: (func $unreachable-select-i64-b (result i32) - ;; CHECK-NEXT: (local $i64toi32_i32$0 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $unreachable-select-i64-b (result i64) - (select - (unreachable) - (i64.const 3) - (i32.const 4) - ) - ) - ;; CHECK: (func $unreachable-select-i64-c (result i32) - ;; CHECK-NEXT: (local $i64toi32_i32$0 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $unreachable-select-i64-c (result i64) - (select - (i64.const 5) - (i64.const 6) - (unreachable) - ) - ) - ;; CHECK: (func $mem - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $0$hi i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $1$hi i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $2$hi i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $3$hi i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $4$hi i32) - ;; CHECK-NEXT: (local $i64toi32_i32$0 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$1 i32) - ;; CHECK-NEXT: (local $i64toi32_i32$2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0$hi - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (local.get $0$hi) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1$hi - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (local.get $1$hi) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.load align=2 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.load offset=4 align=2 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2$hi - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (local.get $2$hi) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.load offset=4 align=1 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3$hi - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (local.get $3$hi) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $i64toi32_i32$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4$hi - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (local.get $4$hi) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=2 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 align=2 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 align=1 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $i64toi32_i32$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $i64toi32_i32$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $i64toi32_i32$0) - ;; CHECK-NEXT: (local.get $i64toi32_i32$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $mem - (drop (i64.load align=8 (i32.const 0))) - (drop (i64.load align=4 (i32.const 0))) - (drop (i64.load align=2 (i32.const 0))) - (drop (i64.load align=1 (i32.const 0))) - (drop (i64.load (i32.const 0))) - (i64.store align=8 (i32.const 0) (i64.const 1)) - (i64.store align=4 (i32.const 0) (i64.const 2)) - (i64.store align=2 (i32.const 0) (i64.const 3)) - (i64.store align=1 (i32.const 0) (i64.const 4)) - (i64.store (i32.const 0) (i64.const 5)) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (global $f (mut i32) (i32.const -1412567121)) - (global $f (mut i64) (i64.const 0x12345678ABCDEFAF)) - ;; CHECK: (global $g (mut i32) (global.get $f)) - (global $g (mut i64) (global.get $f)) - ;; CHECK: (global $f$hi (mut i32) (i32.const 305419896)) - - ;; CHECK: (global $g$hi (mut i32) (global.get $f$hi)) - - ;; CHECK: (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) - - ;; CHECK: (export "exp" (func $1)) - - ;; CHECK: (export "unreach" (func $2)) - - ;; CHECK: (func $call (param $0 i32) (param $0$hi i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $call (param i64)) - (func "exp" - (call $call (global.get $f)) - (global.set $f (i64.const 0x1122334455667788)) - ) - (func "unreach" - (global.set $f - (block $label$1 (result i64) - (unreachable) - ) - ) - ) -) -;; CHECK: (func $1 -;; CHECK-NEXT: (local $0 i32) -;; CHECK-NEXT: (local $0$hi i32) -;; CHECK-NEXT: (local $i64toi32_i32$0 i32) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (local.set $0 -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (global.get $f$hi) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.get $f) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.set $0$hi -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $call -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (local.get $0$hi) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (global.set $f -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (i32.const 287454020) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.const 1432778632) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $f$hi -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $2 -;; CHECK-NEXT: (local $0 i32) -;; CHECK-NEXT: (local $0$hi i32) -;; CHECK-NEXT: (local $1 i32) -;; CHECK-NEXT: (local $1$hi i32) -;; CHECK-NEXT: (local $i64toi32_i32$0 i32) -;; CHECK-NEXT: (block $label$1 -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (local.set $1 -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (local.get $0$hi) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.set $1$hi -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (global.set $f -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (local.get $1$hi) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $f$hi -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $f (mut i32) (i32.const -1412567121)) - (global $f (mut i64) (i64.const 0x12345678ABCDEFAF)) - ;; CHECK: (global $g (mut i32) (global.get $f)) - (global $g (mut i64) (global.get $f)) - ;; CHECK: (global $f$hi (mut i32) (i32.const 305419896)) - - ;; CHECK: (global $g$hi (mut i32) (global.get $f$hi)) - - ;; CHECK: (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) - - ;; CHECK: (export "exp" (func $1)) - - ;; CHECK: (func $call (param $0 i32) (param $0$hi i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $call (param i64)) - (func "exp" - (call $call (global.get $f)) - (global.set $f (i64.const 0x1122334455667788)) - ) -) -;; CHECK: (func $1 -;; CHECK-NEXT: (local $0 i32) -;; CHECK-NEXT: (local $0$hi i32) -;; CHECK-NEXT: (local $i64toi32_i32$0 i32) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (local.set $0 -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (global.get $f$hi) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.get $f) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.set $0$hi -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $call -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (local.get $0$hi) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (global.set $f -;; CHECK-NEXT: (block (result i32) -;; CHECK-NEXT: (local.set $i64toi32_i32$0 -;; CHECK-NEXT: (i32.const 287454020) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.const 1432778632) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $f$hi -;; CHECK-NEXT: (local.get $i64toi32_i32$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - (type $i64_f64_i32_=>_none (func (param i64 f64 i32))) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) - - ;; CHECK: (table $0 37 funcref) - (table $0 37 funcref) - ;; CHECK: (func $0 - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -32768) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $0 - (call_indirect (type $i64_f64_i32_=>_none) - (unreachable) - (f64.const 1) - (i32.const -32768) - (i32.const 20) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten_rereloop.wast binaryen-99/test/lit/passes/flatten_rereloop.wast --- binaryen-108/test/lit/passes/flatten_rereloop.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_rereloop.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1975 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --rereloop -S -o - | filecheck %s - -(module - (memory 1) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_f64 (func (result f64))) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $i32_=>_f32 (func (param i32) (result f32))) - - ;; CHECK: (type $none_=>_f32 (func (result f32))) - - ;; CHECK: (global $global (mut i32) (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (memory $0 1) - - ;; CHECK: (func $0 (result f64) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const -nan:0xfffffd63e4e5a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (result f64) - (if - (i32.const 0) - (loop $label$2 - (unreachable) - ) - ) - (f64.const -nan:0xfffffd63e4e5a) - ) - ;; CHECK: (func $1 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$6$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch$1$leave - ;; CHECK-NEXT: (block $switch$1$default - ;; CHECK-NEXT: (block $switch$1$case$4 - ;; CHECK-NEXT: (br_table $switch$1$case$4 $switch$1$case$4 $switch$1$default - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$6$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch$6$leave - ;; CHECK-NEXT: (block $switch$6$default - ;; CHECK-NEXT: (block $switch$6$case$3 - ;; CHECK-NEXT: (br_table $switch$6$case$3 $switch$6$default - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $1 (result i32) - (block $label$8 - (block $label$9 - (block $label$16 - (block $label$18 - (block $label$19 - (br_table $label$18 $label$16 $label$19 - (i32.const 0) - ) - ) - (br_table $label$9 $label$8 - (i32.const 1) - ) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (i32.const 2) - ) - ;; CHECK: (func $skip-empty - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skip-empty - (block $a1 - (block $a2 - (block $a3 - (block $a4 - (br $a4) - ) - (br $a3) - ) - (br $a2) - ) - (br $a1) - ) - ) - ;; CHECK: (func $skip-empty-2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$5$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$5$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$4$break - ;; CHECK-NEXT: (call $skip-empty) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (call $skip-empty) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skip-empty-2 - (block $a1 - (block $a2 - (block $a3 - (block $a4 - (br $a4) - ) - (call $skip-empty) - (br $a3) - ) - (call $skip-empty) - (br $a2) - ) - (br $a1) - ) - ) - ;; CHECK: (func $skip-empty-3 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$5$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$5$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$4$break - ;; CHECK-NEXT: (call $skip-empty) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (call $skip-empty) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skip-empty-3 - (block $a1 - (block $a2 - (block $a3 - (block $a4 - (nop) - (br $a4) - (nop) - ) - (nop) - (call $skip-empty) - (nop) - (br $a3) - ) - (nop) - (call $skip-empty) - (nop) - (br $a2) - ) - (br $a1) - ) - ) - ;; CHECK: (func $skip-empty-4 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skip-empty-4 (param $x i32) - (block $a1 - (block $a2 - (block $a3 - (block $a4 - (br_table $a1 $a2 $a3 $a4 $a1 $a2 $a3 $a4 (local.get $x)) - ) - (br $a3) - ) - (br $a2) - ) - (br $a1) - ) - ) - ;; CHECK: (func $skipping (param $0 i32) (result f32) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local $3 f32) - ;; CHECK-NEXT: (local $4 f32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skipping (param $0 i32) (result f32) - (if - (i32.const 0) - (unreachable) - ) ;; branches joining here lead to skip opportunities - (loop $label$2 (result f32) - (f32.const 1) - ) - ) - ;; CHECK: (func $merging - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $merging - (if - (i32.const 0) - (return) - ;; no else, but the else ends up with a return too, and we can merge them - ) - ) - ;; CHECK: (func $unswitch - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unswitch - (block $label$1 - (br_table $label$1 $label$1 - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $skip-only-empty - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$3$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$3$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block$3$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skip-only-empty - (if - (i32.const 1) - (global.set $global - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $skip-only-one-branch-out (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $skip-only-one-branch-out (result i32) - (block $label$1 - (nop) - ) - (if - (i32.const 1) - (unreachable) ;; blocks a path through - ) - (i32.const 0) - ) - ;; CHECK: (func $multipass-for-skips (result f32) - ;; CHECK-NEXT: (local $0 f32) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local $3 f32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block $block$7$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f32.const 9223372036854775808) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$7$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.const 65505) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$7$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multipass-for-skips (result f32) - (if (result f32) - (i32.const 0) - (block (result f32) - (block $label$2 - (br_if $label$2 - (i32.const 536870912) - ) - ) - (f32.const 9223372036854775808) - ) - (f32.const 65505) - ) - ) - ;; CHECK: (func $branch-merge-vs-replace - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $branch-merge-vs-replace - (if - (i32.const 0) - (unreachable) - ) - ) - ;; CHECK: (func $unswitch-amount - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const -23) - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$6$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch$4$leave - ;; CHECK-NEXT: (block $switch$4$default - ;; CHECK-NEXT: (block $switch$4$case$2 - ;; CHECK-NEXT: (br_table $switch$4$case$2 $switch$4$default - ;; CHECK-NEXT: (i32.const 44064) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$6$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unswitch-amount - (block $label$1 - (if - (i32.const -23) - (nop) - (block - (block $label$4 - (br_table $label$1 $label$4 - (i32.const 44064) - ) - ) - (unreachable) - ) - ) - ) - ) -) -;; manual TODO: merge branches, all the parts -(module - ;; CHECK: (type $3 (func (param i32))) - - ;; CHECK: (type $0 (func)) - (type $0 (func)) - ;; CHECK: (type $2 (func (param i32) (result i32))) - - ;; CHECK: (type $1 (func (result i32))) - (type $1 (func (result i32))) - (type $2 (func (param i32) (result i32))) - (type $3 (func (param i32))) - ;; CHECK: (func $trivial - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - (func $trivial (; 0 ;) (type $0) - (nop) - ) - ;; CHECK: (func $trivial2 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $trivial) - ;; CHECK-NEXT: (call $trivial) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial2 (; 1 ;) (type $0) - (block - (call $trivial) - (nop) - (call $trivial) - (nop) - ) - (nop) - ) - ;; CHECK: (func $return-void - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - (func $return-void (; 2 ;) (type $0) - (return) - (unreachable) - ) - ;; CHECK: (func $return-val (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $return-val (; 3 ;) (type $1) (result i32) - (return - (i32.const 1) - ) - (unreachable) - ) - ;; CHECK: (func $ifs (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ifs (; 4 ;) (type $2) (param $x i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (block - (block - (local.set $1 - (local.get $x) - ) - (if - (local.get $1) - (block - (block - (local.set $2 - (local.get $x) - ) - (if - (local.get $2) - (block - (return - (i32.const 2) - ) - (unreachable) - ) - (block - (return - (i32.const 3) - ) - (unreachable) - ) - ) - ) - (unreachable) - ) - ) - ) - (nop) - (block - (local.set $3 - (local.get $x) - ) - (if - (local.get $3) - (block - (return - (i32.const 4) - ) - (unreachable) - ) - ) - ) - (nop) - (return - (i32.const 5) - ) - (unreachable) - ) - (local.set $5 - (local.get $4) - ) - (return - (local.get $5) - ) - ) - ;; CHECK: (func $loops (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block $block$21$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (loop $shape$2$continue - ;; CHECK-NEXT: (call $trivial) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $shape$2$continue) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block$21$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$24$break - ;; CHECK-NEXT: (loop $shape$4$continue - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $trivial) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (br $shape$4$continue) - ;; CHECK-NEXT: (br $block$24$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (loop $shape$6$continue - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $trivial) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (br $shape$6$continue) - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loops (; 5 ;) (type $3) (param $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (block - (block - (local.set $1 - (local.get $x) - ) - (if - (local.get $1) - (block - (loop $top - (block - (call $trivial) - (nop) - (br $top) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - ) - ) - (nop) - (loop $top2 - (block - (call $trivial) - (nop) - (local.set $2 - (local.get $x) - ) - (br_if $top2 - (local.get $2) - ) - (nop) - ) - (nop) - ) - (nop) - (loop $top3 - (block - (call $trivial) - (nop) - (block - (local.set $3 - (local.get $x) - ) - (if - (local.get $3) - (block - (br $top3) - (unreachable) - ) - ) - ) - (nop) - ) - (nop) - ) - (nop) - ) - (nop) - ) - ;; CHECK: (func $br-out (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (call $br-out - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br-out (; 6 ;) (type $3) (param $x i32) - (block $out - (call $br-out - (i32.const 5) - ) - (nop) - (br $out) - (unreachable) - ) - (nop) - ) - ;; CHECK: (func $unreachable (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $block$4$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (call $unreachable - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $unreachable - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $unreachable - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable (; 7 ;) (type $3) (param $x i32) - (local $1 i32) - (local $2 i32) - (block - (block - (local.set $1 - (local.get $x) - ) - (if - (local.get $1) - (block - (block - (local.set $2 - (local.get $x) - ) - (if - (local.get $2) - (block - (block $block - (call $unreachable - (i32.const 1) - ) - (nop) - (unreachable) - (unreachable) - (call $unreachable - (i32.const 2) - ) - (nop) - ) - (unreachable) - ) - (block - (block $block4 - (call $unreachable - (i32.const 3) - ) - (nop) - (return) - (unreachable) - (call $unreachable - (i32.const 4) - ) - (nop) - ) - (unreachable) - ) - ) - ) - (unreachable) - ) - ) - ) - (nop) - (block $out - (call $unreachable - (i32.const 5) - ) - (nop) - (br $out) - (unreachable) - (call $unreachable - (i32.const 6) - ) - (nop) - ) - (nop) - ) - (nop) - ) - ;; CHECK: (func $empty-blocks (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $block$2$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$2$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $empty-blocks (; 8 ;) (type $3) (param $x i32) - (block - (block $block - ) - (nop) - (block $block5 - ) - (nop) - ) - (nop) - ) - ;; CHECK: (func $before-and-after (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (block $block$4$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$8$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$8$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$10$break - ;; CHECK-NEXT: (loop $shape$4$continue - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (br $shape$4$continue) - ;; CHECK-NEXT: (br $block$10$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$11$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$11$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block$11$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$15$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$15$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$15$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$21$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$21$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block$21$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$28$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$28$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$30$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$30$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $before-and-after - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $before-and-after (; 9 ;) (type $3) (param $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (block - (call $before-and-after - (i32.const 1) - ) - (nop) - (block $block - (call $before-and-after - (i32.const 2) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 3) - ) - (nop) - (block $out - (call $before-and-after - (i32.const 4) - ) - (nop) - (local.set $1 - (local.get $x) - ) - (br_if $out - (local.get $1) - ) - (nop) - (call $before-and-after - (i32.const 5) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 6) - ) - (nop) - (loop $loop-in - (nop) - ) - (nop) - (call $before-and-after - (i32.const 7) - ) - (nop) - (loop $top - (nop) - ) - (nop) - (call $before-and-after - (i32.const 8) - ) - (nop) - (loop $top2 - (block - (call $before-and-after - (i32.const 9) - ) - (nop) - (local.set $2 - (local.get $x) - ) - (br_if $top2 - (local.get $2) - ) - (nop) - (call $before-and-after - (i32.const 10) - ) - (nop) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 11) - ) - (nop) - (block - (local.set $3 - (local.get $x) - ) - (if - (local.get $3) - (block - (call $before-and-after - (i32.const 12) - ) - (nop) - ) - ) - ) - (nop) - (call $before-and-after - (i32.const 13) - ) - (nop) - (block - (local.set $4 - (local.get $x) - ) - (if - (local.get $4) - (block - (call $before-and-after - (i32.const 14) - ) - (nop) - ) - (block - (call $before-and-after - (i32.const 15) - ) - (nop) - ) - ) - ) - (nop) - (block - (local.set $5 - (local.get $x) - ) - (if - (local.get $5) - (block - (block $block8 - (call $before-and-after - (i32.const 16) - ) - (nop) - ) - (nop) - ) - ) - ) - (nop) - (call $before-and-after - (i32.const 17) - ) - (nop) - (block $block9 - (call $before-and-after - (i32.const 18) - ) - (nop) - (block $block10 - (call $before-and-after - (i32.const 19) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 20) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 21) - ) - (nop) - (block $block11 - (block $block12 - (call $before-and-after - (i32.const 22) - ) - (nop) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 23) - ) - (nop) - (block $no1 - (block $no2 - (call $before-and-after - (i32.const 24) - ) - (nop) - ) - (nop) - ) - (nop) - (call $before-and-after - (i32.const 25) - ) - (nop) - ) - (nop) - ) - ;; CHECK: (func $switch (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $block$3$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$3$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block$9$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $switch - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch$3$leave - ;; CHECK-NEXT: (block $switch$3$default - ;; CHECK-NEXT: (block $switch$3$case$9 - ;; CHECK-NEXT: (br_table $switch$3$case$9 $switch$3$case$9 $switch$3$case$9 $switch$3$default - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$9$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $switch - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$9$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $switch - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $switch (; 10 ;) (type $3) (param $x i32) - (local $1 i32) - (local $2 i32) - (block $out - (block $a - (local.set $1 - (local.get $x) - ) - (br_table $a $a - (local.get $1) - ) - (unreachable) - ) - (nop) - (call $switch - (i32.const 1) - ) - (nop) - (block $b - (block $c - (local.set $2 - (local.get $x) - ) - (br_table $b $b $b $c - (local.get $2) - ) - (unreachable) - ) - (nop) - (call $switch - (i32.const 2) - ) - (nop) - ) - (nop) - (call $switch - (i32.const 3) - ) - (nop) - ) - (nop) - ) - ;; CHECK: (func $no-return - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $block$6$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$6$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$6$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-return (; 11 ;) (type $0) - (if - (i32.const 1) - (block - (drop - (i32.const 2) - ) - (nop) - ) - (block - (drop - (i32.const 3) - ) - (nop) - ) - ) - (nop) - ) - ;; CHECK: (func $if-br-wat (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $block$3$break - ;; CHECK-NEXT: (block $block$4$break - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $if-br-wat - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $if-br-wat - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (br $block$3$break) - ;; CHECK-NEXT: (br $block$4$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $if-br-wat - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $block$3$break) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $if-br-wat - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-br-wat (; 12 ;) (type $3) (param $x i32) - (local $1 i32) - (local $2 i32) - (block - (call $if-br-wat - (i32.const 0) - ) - (nop) - (block $label$2 - (block - (local.set $1 - (local.get $x) - ) - (if - (local.get $1) - (block - (call $if-br-wat - (i32.const 1) - ) - (nop) - ) - (block - (block - (local.set $2 - (local.get $x) - ) - (if - (local.get $2) - (block - (br $label$2) - (unreachable) - ) - ) - ) - (nop) - ) - ) - ) - (nop) - (call $if-br-wat - (i32.const 2) - ) - (nop) - ) - (nop) - (call $if-br-wat - (i32.const 3) - ) - (nop) - ) - (nop) - ) - ;; CHECK: (func $switcher-to-nowhere (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch$1$leave - ;; CHECK-NEXT: (block $switch$1$default - ;; CHECK-NEXT: (block $switch$1$case$4 - ;; CHECK-NEXT: (block $switch$1$case$5 - ;; CHECK-NEXT: (br_table $switch$1$case$5 $switch$1$case$4 $switch$1$default - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $switcher-to-nowhere (; 13 ;) (type $2) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (block - (block $switch - (block $switch-case0 - (block $switch-case - (local.set $1 - (local.get $0) - ) - (br_table $switch-case $switch-case0 $switch - (local.get $1) - ) - (unreachable) - ) - (nop) - (return - (i32.const 1) - ) - (unreachable) - ) - (nop) - (return - (i32.const 2) - ) - (unreachable) - ) - (nop) - (return - (i32.const 3) - ) - (unreachable) - ) - (local.set $3 - (local.get $2) - ) - (return - (local.get $3) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast binaryen-99/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast --- binaryen-108/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,171 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --simplify-locals-nonesting --dfo -O3 -S -o - | filecheck %s - -(module - (memory 1) - (func "if-select" - (local $var$0 i32) - (nop) - (drop - (if (result i32) - (select - (i32.const 65473) - (i32.const 1) - (local.get $var$0) - ) - (i32.const -2405046) - (i32.const 1) - ) - ) - ) - (func "unreachable-body-update-zext" (result f64) - (if - (i32.eqz - (i32.const 0) - ) - (unreachable) - ) - (f64.const -9223372036854775808) - ) - (func "ssa-const" (param $var$0 i32) (param $var$1 f64) (param $var$2 f64) (result i32) - (block $label$1 (result i32) - (block $label$2 - (if - (i32.const 1) - (block - (drop - (loop $label$5 (result i64) - (if (result i64) - (i32.const 0) - (i64.load offset=22 - (i32.and - (br_if $label$1 - (i32.const 0) - (i32.const 0) - ) - (i32.const 15) - ) - (i64.const 1) - ) - (i64.const 1) - ) - ) - ) - ) - ) - (unreachable) - ) - ) - ) - (func "if-nothing" (param $var$0 i64) - (local $var$1 i32) - (local $var$2 i32) - (block $label$1 - (loop $label$2 - (block $label$3 - (block $label$4 - (br_if $label$3 - (i32.eqz - (if (result i32) - (i32.const 0) - (i32.const 0) - (local.get $var$2) - ) - ) - ) - (unreachable) - ) - (unreachable) - ) - ) - (unreachable) - ) - ) - (func "only-dfo" (param $var$0 f64) (result i32) - (local $var$1 i32) - (local $var$2 i32) - (local $var$3 i32) - (local $var$4 i32) - (loop $label$1 - (local.set $var$3 - (local.tee $var$1 - (local.tee $var$2 - (local.get $var$1) - ) - ) - ) - (if - (i32.eqz - (local.get $var$4) - ) - (block - (local.set $var$4 - (select - (local.get $var$3) - (i32.const -2147483648) - (local.get $var$2) - ) - ) - (br $label$1) - ) - ) - ) - (i32.const -2766) - ) -) - -;; CHECK: (type $none_=>_none (func)) - -;; CHECK: (type $none_=>_f64 (func (result f64))) - -;; CHECK: (type $i32_f64_f64_=>_i32 (func (param i32 f64 f64) (result i32))) - -;; CHECK: (type $i64_=>_none (func (param i64))) - -;; CHECK: (type $f64_=>_i32 (func (param f64) (result i32))) - -;; CHECK: (export "if-select" (func $0)) - -;; CHECK: (export "unreachable-body-update-zext" (func $1)) - -;; CHECK: (export "ssa-const" (func $2)) - -;; CHECK: (export "if-nothing" (func $3)) - -;; CHECK: (export "only-dfo" (func $4)) - -;; CHECK: (func $0 (; has Stack IR ;) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: ) - -;; CHECK: (func $1 (; has Stack IR ;) (result f64) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) - -;; CHECK: (func $2 (; has Stack IR ;) (param $0 i32) (param $1 f64) (param $2 f64) (result i32) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) - -;; CHECK: (func $3 (; has Stack IR ;) (param $0 i64) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) - -;; CHECK: (func $4 (; has Stack IR ;) (param $0 f64) (result i32) -;; CHECK-NEXT: (local $1 i32) -;; CHECK-NEXT: (loop $label$1 -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.eqz -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (local.set $1 -;; CHECK-NEXT: (i32.const -2147483648) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (br $label$1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.const -2766) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast binaryen-99/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast --- binaryen-108/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,4674 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --simplify-locals-nonesting --souperify --enable-threads -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $none_=>_f64 (func (result f64))) - - ;; CHECK: (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) - - ;; CHECK: (type $i64_i64_i64_=>_i64 (func (param i64 i64 i64) (result i64))) - - ;; CHECK: (type $i64_i64_i32_f32_=>_none (func (param i64 i64 i32 f32))) - - ;; CHECK: (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) - - ;; CHECK: (memory $0 (shared 1 1)) - (memory $0 (shared 1 1)) - ;; Figure 1a from the Souper paper https://arxiv.org/pdf/1711.04422.pdf - ;; CHECK: (export "replaced-print-internal" (func $56)) - - ;; CHECK: (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) - ;; CHECK-NEXT: (local $i i32) - ;; CHECK-NEXT: (local $j i32) - ;; CHECK-NEXT: (local $r i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) - (local $i i32) - (local $j i32) - (local $r i32) - (local.set $i - (i64.eq - (local.get $a) - (local.get $x) - ) - ) - (local.set $j - (i64.ne - (local.get $a) - (local.get $y) - ) - ) - (local.set $r - (i32.and - (local.get $i) - (local.get $j) - ) - ) - (return (local.get $r)) - ) - ;; Figure 1b, with a potential path condition - ;; CHECK: (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) - ;; CHECK-NEXT: (local $i i32) - ;; CHECK-NEXT: (local $j i32) - ;; CHECK-NEXT: (local $r i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) - (local $i i32) - (local $j i32) - (local $r i32) - (if - (i64.lt_s - (local.get $x) - (local.get $y) - ) - (block - (local.set $i - (i64.eq - (local.get $a) - (local.get $x) - ) - ) - (local.set $j - (i64.ne - (local.get $a) - (local.get $y) - ) - ) - (local.set $r - (i32.and - (local.get $i) - (local.get $j) - ) - ) - (return (local.get $r)) - ) - (unreachable) - ) - ) - ;; Figure 3, simplified to an if - ;; CHECK: (func $figure-3-if (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $figure-3-if (param $x i32) (result i32) - (if - (i32.and - (local.get $x) - (i32.const 1) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - (return - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $send-i32 (param $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $send-i32 (param i32)) - ;; flipping of greater than/or equals ops, which are not in Souper IR - ;; CHECK: (func $flips - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $z i64) - ;; CHECK-NEXT: (local $w i64) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i64) - ;; CHECK-NEXT: (local $17 i64) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i64) - ;; CHECK-NEXT: (local $20 i64) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i64) - ;; CHECK-NEXT: (local $23 i64) - ;; CHECK-NEXT: (local $24 i32) - ;; CHECK-NEXT: (local $25 i64) - ;; CHECK-NEXT: (local $26 i64) - ;; CHECK-NEXT: (local $27 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $send-i32 - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $21 - ;; CHECK-NEXT: (i64.ge_u - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $send-i32 - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $24 - ;; CHECK-NEXT: (i64.gt_s - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $send-i32 - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $27 - ;; CHECK-NEXT: (i64.gt_u - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $send-i32 - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $flips - (local $x i32) - (local $y i32) - (local $z i64) - (local $w i64) - (local.set $x (i32.ge_s (local.get $x) (local.get $y))) - (local.set $x (i32.ge_u (local.get $x) (local.get $y))) - (local.set $x (i32.gt_s (local.get $x) (local.get $y))) - (local.set $x (i32.gt_u (local.get $x) (local.get $y))) - (call $send-i32 (i64.ge_s (local.get $z) (local.get $w))) - (call $send-i32 (i64.ge_u (local.get $z) (local.get $w))) - (call $send-i32 (i64.gt_s (local.get $z) (local.get $w))) - (call $send-i32 (i64.gt_u (local.get $z) (local.get $w))) - ) - ;; CHECK: (func $various-conditions-1 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $various-conditions-1 (param $x i32) - (if - (local.get $x) - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - ) - ) - ;; CHECK: (func $various-conditions-2 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $various-conditions-2 (param $x i32) - (if - (i32.lt_s - (local.get $x) - (i32.const 0) - ) - (local.set $x - (i32.sub - (local.get $x) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $various-conditions-3 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $various-conditions-3 (param $x i32) - (if - (i32.reinterpret_f32 (f32.const 0)) - (local.set $x - (i32.sub - (local.get $x) - (i32.const 4) - ) - ) - ) - ) - ;; CHECK: (func $various-conditions-4 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $various-conditions-4 (param $x i32) - (if - (unreachable) - (local.set $x - (i32.add - (local.get $x) - (i32.const 3) - ) - ) - ) - ) - ;; CHECK: (func $unaries (param $x i32) (param $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.popcnt - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unaries (param $x i32) (param $y i32) - (if - (i32.eqz - (local.get $x) - ) - (local.set $x - (i32.add - (i32.ctz - (local.get $y) - ) - (i32.sub - (i32.clz - (local.get $x) - ) - (i32.popcnt - (local.get $y) - ) - ) - ) - ) - ) - ) - ;; CHECK: (func $unary-condition (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unary-condition (param $x i32) - (if - (i32.ctz - (i32.gt_u - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $unary-condition-2 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unary-condition-2 (param $x i32) - (if - (i32.eqz - (i32.gt_u - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $if-else-cond (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-cond (param $x i32) (result i32) - (if - (i32.lt_s - (local.get $x) - (i32.const 1) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - (return - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $trivial-ret (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial-ret (result i32) - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - ;; CHECK: (func $trivial-const (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial-const (result i32) - (i32.const 0) - ) - ;; CHECK: (func $trivial-const-block (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial-const-block (result i32) - (nop) - (i32.const 0) - ) - ;; CHECK: (func $bad-phi-value (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bad-phi-value (result i32) - (if (result i32) - (if (result i32) - (i32.const 1) - (i32.load - (i32.const 0) - ) - (i32.const 0) - ) - (i32.const 0) - (i32.const 1) - ) - ) - ;; CHECK: (func $bad-phi-value-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bad-phi-value-2 (param $x i32) (result i32) - (if - (if (result i32) - (i32.const 1) - (i32.load - (i32.const 0) - ) - (i32.const 0) - ) - (local.set $x (i32.const 1)) - (local.set $x (i32.const 2)) - ) - (local.get $x) - ) - ;; CHECK: (func $select (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $select (param $x i32) (result i32) - (return - (select - (i32.const 1) - (i32.const 2) - (i32.const 3) - ) - ) - ) - ;; CHECK: (func $select-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $select-2 (param $x i32) (param $y i32) (result i32) - (return - (select - (i32.add - (local.get $x) - (local.get $y) - ) - (i32.add - (local.get $x) - (i32.const 1) - ) - (i32.add - (i32.const 2) - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $block-phi-1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block-phi-1 (param $x i32) (param $y i32) (result i32) - (block $out - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - (br_if $out (local.get $y)) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - (i32.add - (local.get $x) - (i32.const 3) - ) - ) - ;; CHECK: (func $block-phi-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block-phi-2 (param $x i32) (param $y i32) (result i32) - (block $out - (local.set $x - (i32.const 1) - ) - (br_if $out (local.get $y)) - (local.set $x - (i32.const 2) - ) - ) - (i32.add - (local.get $x) - (i32.const 3) - ) - ) - ;; CHECK: (func $zero_init-phi-bad_type (result f64) - ;; CHECK-NEXT: (local $x f64) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero_init-phi-bad_type (result f64) - (local $x f64) - (if - (i32.const 0) - (local.set $x - (f64.const 1) - ) - ) - (local.get $x) - ) - ;; CHECK: (func $phi-bad-type (result f64) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $phi-bad-type (result f64) - (block $label$1 (result f64) - (if (result f64) - (i32.const 0) - (f64.const 0) - (f64.const 1) - ) - ) - ) - ;; CHECK: (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $i i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $i - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $i - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) - (local $i i32) - (if - (i32.le_s - (local.get $x) - (local.get $y) - ) - (local.set $i - (i32.eq - (local.get $x) - (local.get $y) - ) - ) - (local.set $i - (i32.add - (local.get $x) - (local.get $y) - ) - ) - ) - (local.get $i) - ) - ;; CHECK: (func $call (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $call) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $call) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $call) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $call (result i32) - (return - (i32.mul - (i32.add - (call $call) - (call $call) - ) - (i32.add - (i32.const 10) - (call $call) - ) - ) - ) - ) - ;; CHECK: (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (return (local.get $x)) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (unreachable) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) - (block $out - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (br $out) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $out $out $out - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) - (block $out - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (br_table $out $out $out (i32.const 1)) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) - (block $out - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (br_if $out - (local.get $x) - ) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; there *IS* a phi here since it was a br_if - (return - (local.get $x) - ) - ) - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const -8531) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$3) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const -8531) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$2) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const -8531) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) - (block $label$1 - (block $label$2 - (block $label$3 - (if - (local.get $2) - (if - (local.get $0) - (block - (local.set $1 - (i32.const -8531) - ) - (br $label$3) - ) - (block - (local.set $1 - (i32.const -8531) - ) - (br $label$1) - ) - ) - ) - (br $label$2) - ) - (drop - (i32.load - (i32.const 0) - ) - ) - (br $label$1) - ) - (i32.store16 - (i32.const 1) - (local.get $1) - ) - (unreachable) - ) - (i32.store16 - (i32.const 0) - (i32.const -8531) - ) - ) - ;; CHECK: (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) - (block - (unreachable) - (if - (local.get $x) - (local.set $x - (i32.const 1) - ) - (local.set $x - (i32.const 2) - ) - ) - (return - (local.get $x) - ) - ) - ) - ;; CHECK: (func $merge-with-one-less (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (block $label$5 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $label$5 $label$4 $label$3 $label$2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $merge-with-one-less (param $var$0 i32) (result i32) - (block $label$1 - (block $label$2 - (block $label$3 - (block $label$4 - (block $label$5 - (br_table $label$5 $label$4 $label$3 $label$2 - (i32.load - (i32.const 1) - ) - ) - ) - (unreachable) - ) - (br $label$1) - ) - (f64.store - (i32.load - (local.tee $var$0 - (i32.const 8) - ) - ) - (f64.const 0) - ) - (br $label$1) - ) - (unreachable) - ) - (i32.store - (local.get $var$0) - (i32.const 16) - ) - (i32.const 1) - ) - ;; CHECK: (func $deep (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i32) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i32) - ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (local $24 i32) - ;; CHECK-NEXT: (local $25 i32) - ;; CHECK-NEXT: (local $26 i32) - ;; CHECK-NEXT: (local $27 i32) - ;; CHECK-NEXT: (local $28 i32) - ;; CHECK-NEXT: (local $29 i32) - ;; CHECK-NEXT: (local $30 i32) - ;; CHECK-NEXT: (local $31 i32) - ;; CHECK-NEXT: (local $32 i32) - ;; CHECK-NEXT: (local $33 i32) - ;; CHECK-NEXT: (local $34 i32) - ;; CHECK-NEXT: (local $35 i32) - ;; CHECK-NEXT: (local $36 i32) - ;; CHECK-NEXT: (local $37 i32) - ;; CHECK-NEXT: (local $38 i32) - ;; CHECK-NEXT: (local $39 i32) - ;; CHECK-NEXT: (local $40 i32) - ;; CHECK-NEXT: (local $41 i32) - ;; CHECK-NEXT: (local $42 i32) - ;; CHECK-NEXT: (local $43 i32) - ;; CHECK-NEXT: (local $44 i32) - ;; CHECK-NEXT: (local $45 i32) - ;; CHECK-NEXT: (local $46 i32) - ;; CHECK-NEXT: (local $47 i32) - ;; CHECK-NEXT: (local $48 i32) - ;; CHECK-NEXT: (local $49 i32) - ;; CHECK-NEXT: (local $50 i32) - ;; CHECK-NEXT: (local $51 i32) - ;; CHECK-NEXT: (local $52 i32) - ;; CHECK-NEXT: (local $53 i32) - ;; CHECK-NEXT: (local $54 i32) - ;; CHECK-NEXT: (local $55 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $deep (param $x i32) (result i32) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.get $x) - ) - ;; CHECK: (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i64) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i64) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i64) - ;; CHECK-NEXT: (local $17 i64) - ;; CHECK-NEXT: (local $18 i64) - ;; CHECK-NEXT: (local $19 i64) - ;; CHECK-NEXT: (local $20 i64) - ;; CHECK-NEXT: (local $21 i64) - ;; CHECK-NEXT: (local $22 i64) - ;; CHECK-NEXT: (local $23 i64) - ;; CHECK-NEXT: (local $24 i64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.div_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) - (if - (i64.lt_s - (local.get $x) - (local.get $y) - ) - (if - (i64.eqz - (local.get $x) - ) - (local.set $t - (i64.add - (local.get $x) - (local.get $y) - ) - ) - (local.set $t - (i64.sub - (local.get $x) - (local.get $y) - ) - ) - ) - (if - (i64.eqz - (local.get $y) - ) - (local.set $t - (i64.mul - (local.get $x) - (local.get $y) - ) - ) - (local.set $t - (i64.div_s - (local.get $x) - (local.get $y) - ) - ) - ) - ) - (return (local.get $t)) - ) - ;; CHECK: (func $loop-1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-1 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - ) - ;; neither needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-2 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.add (local.get $y) (i32.const 4))) - ) - ;; neither needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-3 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-3 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.add (local.get $y) (i32.const 4))) - (br_if $loopy (local.get $y)) - ) - ;; both needed - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-4 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-4 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (br_if $loopy (local.get $y)) - ) - ;; only x needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-5 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-5 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.const 2)) ;; same value - (br_if $loopy (local.get $y)) - ) - ;; only x needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-6 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-6 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (local.get $y)) ;; same value - (br_if $loopy (local.get $y)) - ) - ;; only x needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-7 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-7 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.const 5)) ;; different! - (br_if $loopy (local.get $y)) - ) - ;; y changed but we don't need a phi for it - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-8 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $z i32) - ;; CHECK-NEXT: (local $w i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-8 (param $x i32) (param $y i32) (result i32) - (local $z i32) - (local $w i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $z (local.get $x)) - (local.set $w (local.get $y)) - (local.set $x (i32.const 1)) ;; same! - (local.set $y (i32.const 4)) ;; different! - (br_if $loopy (local.get $y)) - ) - ;; x is always 3, and y needs a phi. - ;; each is also copied to another local, which we need - ;; to handle properly - (return - (i32.mul - (i32.add - (local.get $x) - (local.get $y) - ) - (i32.sub - (local.get $z) - (local.get $w) - ) - ) - ) - ) - ;; CHECK: (func $loop-9 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-9 (param $x i32) (param $y i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $t (local.get $x)) - (local.set $x (local.get $y)) - (local.set $y (local.get $t)) - (br_if $loopy (local.get $t)) - ) - ;; x and y swapped, so both need phis - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-10 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-10 (param $x i32) (param $y i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 1)) - (loop $loopy ;; we swap the values. but we need a deeper analysis to figure that out... - (local.set $t (local.get $x)) - (local.set $x (local.get $y)) - (local.set $y (local.get $t)) - (br_if $loopy (local.get $t)) - ) - ;; x and y swapped, but the same constant was swapped - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (loop $loopy - (local.set $x (i32.const 4)) - (br_if $loopy (local.get $t)) - (local.set $y (i32.const 5)) - (br_if $loopy (local.get $t)) - (local.set $z (i32.const 6)) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 4))) - (br_if $loopy (local.get $t)) - (local.set $y (i32.add (local.get $y) (i32.const 5))) - (br_if $loopy (local.get $t)) - (local.set $z (i32.add (local.get $z) (i32.const 6))) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $loopy) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (loop $loopy - (block $out - (local.set $x (i32.add (local.get $x) (i32.const 4))) - (br_if $out (local.get $t)) - (local.set $y (i32.add (local.get $y) (i32.const 5))) - (br_if $out (local.get $t)) - (local.set $z (i32.add (local.get $z) (i32.const 6))) - (br $loopy) - ) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $loopy) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (block $out - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 4))) - (br_if $out (local.get $t)) - (local.set $y (i32.add (local.get $y) (i32.const 5))) - (br_if $out (local.get $t)) - (local.set $z (i32.add (local.get $z) (i32.const 6))) - (br $loopy) - ) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 f64) - ;; CHECK-NEXT: (local $9 f64) - ;; CHECK-NEXT: (local $10 f64) - ;; CHECK-NEXT: (local $11 f64) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (loop $label$2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) - (if - (local.get $var$2) - (drop - (loop $label$2 (result f64) - (if - (block $label$3 (result i32) - (if - (i32.const 0) - (unreachable) - ) - (nop) - (i32.const 0) - ) - (unreachable) - ) - (br_if $label$2 - (local.get $var$2) - ) - (f64.const 0) - ) - ) - ) - ) - ;; CHECK: (func $loop-unreachable - ;; CHECK-NEXT: (local $var$0 i32) - ;; CHECK-NEXT: (local $var$1 f64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 f64) - ;; CHECK-NEXT: (local $12 f64) - ;; CHECK-NEXT: (local $13 f64) - ;; CHECK-NEXT: (loop $label$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (loop $label$6 - ;; CHECK-NEXT: (block $label$7 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$7 - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$7 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $label$6 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $loop-unreachable - (local $var$0 i32) - (local $var$1 f64) - (loop $label$1 - (local.set $var$1 - (block $label$2 (result f64) - (block $label$3 - (local.set $var$0 - (block $label$4 (result i32) - (if - (i32.const 1337) - (unreachable) - ) - (local.get $var$0) - ) - ) - (loop $label$6 - (br_if $label$6 - (block $label$7 (result i32) - (drop - (br_if $label$7 - (local.get $var$0) - (i32.const 65535) - ) - ) - (drop - (br_if $label$7 - (local.get $var$0) - (i32.const 0) - ) - ) - (unreachable) - ) - ) - ) - ) - (local.get $var$1) - ) - ) - (br $label$1) - ) - ) - ;; CHECK: (func $phi-value-turns-bad (result f64) - ;; CHECK-NEXT: (local $var$0 i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $var$2 f32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 f32) - ;; CHECK-NEXT: (local $13 f32) - ;; CHECK-NEXT: (local $14 f32) - ;; CHECK-NEXT: (local $15 f32) - ;; CHECK-NEXT: (local $16 f64) - ;; CHECK-NEXT: (local $17 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (i32.atomic.rmw16.sub_u offset=22 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (loop $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $phi-value-turns-bad (result f64) - (local $var$0 i32) - (local $var$1 i32) - (local $var$2 f32) - (local.set $var$2 - (if (result f32) - (local.tee $var$0 - (i32.atomic.rmw16.sub_u offset=22 - (i32.const 0) - (i32.const 0) - ) - ) - (unreachable) - (block (result f32) - (if - (loop $label$3 (result i32) - (block $label$4 (result i32) - (i32.clz - (br_if $label$4 - (local.get $var$0) - (i32.const 1) - ) - ) - ) - ) - (nop) - ) - (f32.const 1) - ) - ) - ) - (unreachable) - ) - ;; CHECK: (func $multi-use (param $x i32) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multi-use (param $x i32) (result i32) - (local $temp i32) - (local.set $temp (i32.add (local.get $x) (i32.const 1))) - (i32.add (local.get $temp) (local.get $temp)) - ) - ;; CHECK: (func $multi-use-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multi-use-2 (param $x i32) (result i32) - (local $temp i32) - (local.set $temp (i32.add (local.get $x) (i32.const 1))) - (local.set $x (i32.mul (local.get $temp) (i32.const 2))) - (i32.sub (local.get $x) (local.get $temp)) - ) - ;; CHECK: (func $many-single-uses-with-param (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $many-single-uses-with-param (param $x i32) (result i32) - (return - (i32.eqz - (i32.add - (i32.mul - (i32.const 10) - (local.get $x) - ) - (i32.sub - (i32.ctz - (local.get $x) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (func "replaced-print-internal" (param $var$0 i32) - (local $var$1 i32) - (local $var$2 i32) - (local $var$3 i32) - (if - (local.tee $var$0 - (i32.add - (local.get $var$0) - (i32.const -7) - ) - ) - (block $label$2 - (block $label$3 - (local.set $var$1 - (local.get $var$0) - ) - (br_if $label$3 - (local.tee $var$3 - (i32.const 12) - ) - ) - (unreachable) - ) - (br_if $label$2 - (i32.eqz - (local.get $var$1) - ) - ) - (if - (i32.ne - (i32.load - (i32.const 0) - ) - (local.get $var$0) - ) - (unreachable) - ) - (unreachable) - ) - ) - ) - ;; CHECK: (func $56 (param $var$0 i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $var$2 i32) - ;; CHECK-NEXT: (local $var$3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (i32.const -7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - - ;; CHECK: (func $multiple-uses-to-non-expression (param $x i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multiple-uses-to-non-expression (param $x i32) - (local $temp i32) - (local.set $x - (i32.add - (local.get $x) - (i32.const 10) - ) - ) - (i32.store - (i32.const 1) - (local.get $x) ;; x+10 has two uses! - ) - (i32.store - (i32.const 2) - (i32.add - (local.get $x) - (i32.const 20) - ) - ) - ) - ;; CHECK: (func $nested-phi-forwarding (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $var$2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (loop $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (block $label$5 - ;; CHECK-NEXT: (block $label$6 - ;; CHECK-NEXT: (block $label$7 - ;; CHECK-NEXT: (block $label$8 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$4) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $label$3 - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$9 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$9 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store offset=176 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-phi-forwarding (param $var$0 i32) (result i32) - (local $var$1 i32) - (local $var$2 i32) - (block $label$1 - (block $label$2 - (loop $label$3 - (block $label$4 - (block $label$5 - (block $label$6 - (block $label$7 - (block $label$8 - (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 - (local.get $var$0) - ) - ) - (local.set $var$1 - (i32.const 1) - ) - ) - (br $label$4) - ) - (unreachable) - ) - (br $label$1) - ) - (br_if $label$3 - (local.tee $var$2 - (i32.const 1) - ) - ) - ) - ) - (block $label$9 - (br_if $label$9 - (i32.or - (i32.const 1) - (local.get $var$1) - ) - ) - ) - (unreachable) - ) - (i32.store offset=176 - (i32.const 0) - (local.get $var$2) - ) - (i32.const 0) - ) - ;; CHECK: (func $zext-numGets (param $var$0 i32) (param $var$1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zext-numGets (param $var$0 i32) (param $var$1 i32) - (if - (i32.ctz - (block $label$1 (result i32) - (drop - (br_if $label$1 - (i32.const 1) - (i32.load - (i32.const -8) - ) - ) - ) - (i32.eqz - (i32.load - (i32.const -16) - ) - ) - ) - ) - (unreachable) - ) - ) - ;; CHECK: (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) - (local $temp i32) - (if - (i32.ctz - (block $label$1 (result i32) - (drop - (br_if $label$1 - (i32.const 1) - (i32.load - (i32.const -8) - ) - ) - ) - (local.set $temp - (i32.eqz - (i32.load - (i32.const -16) - ) - ) - ) - (drop - (local.get $temp) - ) - (local.get $temp) - ) - ) - (unreachable) - ) - ) - ;; CHECK: (func $flipped-needs-right-origin (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $flipped-needs-right-origin (param $var$0 i32) (result i32) - (local $var$1 i32) - (block $label$1 - (br_if $label$1 - (i32.load - (i32.const 1) - ) - ) - (local.set $var$1 - (i32.const 2) - ) - ) - (if - (i32.gt_s - (i32.const 3) - (i32.add - (local.get $var$1) - (i32.const 4) - ) - ) - (unreachable) - ) - (i32.const 5) - ) - ;; CHECK: (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - (i32.store - (local.tee $var$1 - (i32.gt_u - (local.get $var$1) - (i32.const 1) - ) - ) - (i32.const 2) - ) - (i32.store offset=8 - (i32.const 3) - (i32.sub - (i32.const 4) - (local.get $var$1) - ) - ) - (unreachable) - ) - ;; CHECK: (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (loop $label$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) - (loop $label$1 - (if - (i32.const 0) - (block - (local.set $var$2 - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - (br $label$1) - ) - ) - (local.set $var$3 - (local.get $var$2) - ) - (local.set $var$2 - (local.get $var$3) - ) - (br $label$1) - ) - ) - ;; CHECK: (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - ;; CHECK-NEXT: (local $var$3 i32) - ;; CHECK-NEXT: (local $var$4 i32) - ;; CHECK-NEXT: (local $var$5 i32) - ;; CHECK-NEXT: (local $var$6 i32) - ;; CHECK-NEXT: (local $var$7 i32) - ;; CHECK-NEXT: (local $var$8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (loop $label$2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $var$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (local.set $var$3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $var$3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - (local $var$3 i32) - (local $var$4 i32) - (local $var$5 i32) - (local $var$6 i32) - (local $var$7 i32) - (local $var$8 i32) - (local.set $var$1 - (i32.const 1) - ) - (if - (i32.const 0) - (loop $label$2 - (if - (local.get $var$1) - (nop) - ) - (local.set $var$1 - (i32.sub - (i32.const 0) - (local.tee $var$3 - (i32.const 1) - ) - ) - ) - (br_if $label$2 - (i32.const 0) - ) - ) - ) - (if - (local.get $var$1) - (local.set $var$3 - (i32.const 1) - ) - ) - (i32.store - (i32.const 8) - (i32.add - (local.get $var$3) - (i32.const 16) - ) - ) - (i32.store - (i32.const 8) - (i32.const 64) - ) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast binaryen-99/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast --- binaryen-108/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,4606 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --flatten --simplify-locals-nonesting --souperify-single-use --enable-threads -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $none_=>_f64 (func (result f64))) - - ;; CHECK: (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) - - ;; CHECK: (type $i64_i64_i64_=>_i64 (func (param i64 i64 i64) (result i64))) - - ;; CHECK: (type $i64_i64_i32_f32_=>_none (func (param i64 i64 i32 f32))) - - ;; CHECK: (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) - - ;; CHECK: (memory $0 (shared 1 1)) - (memory $0 (shared 1 1)) - ;; Figure 1a from the Souper paper https://arxiv.org/pdf/1711.04422.pdf - ;; CHECK: (export "replaced-print-internal" (func $55)) - - ;; CHECK: (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) - ;; CHECK-NEXT: (local $i i32) - ;; CHECK-NEXT: (local $j i32) - ;; CHECK-NEXT: (local $r i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) - (local $i i32) - (local $j i32) - (local $r i32) - (local.set $i - (i64.eq - (local.get $a) - (local.get $x) - ) - ) - (local.set $j - (i64.ne - (local.get $a) - (local.get $y) - ) - ) - (local.set $r - (i32.and - (local.get $i) - (local.get $j) - ) - ) - (return (local.get $r)) - ) - ;; Figure 1b, with a potential path condition - ;; CHECK: (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) - ;; CHECK-NEXT: (local $i i32) - ;; CHECK-NEXT: (local $j i32) - ;; CHECK-NEXT: (local $r i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) - (local $i i32) - (local $j i32) - (local $r i32) - (if - (i64.lt_s - (local.get $x) - (local.get $y) - ) - (block - (local.set $i - (i64.eq - (local.get $a) - (local.get $x) - ) - ) - (local.set $j - (i64.ne - (local.get $a) - (local.get $y) - ) - ) - (local.set $r - (i32.and - (local.get $i) - (local.get $j) - ) - ) - (return (local.get $r)) - ) - (unreachable) - ) - ) - ;; Figure 3, simplified to an if - ;; CHECK: (func $figure-3-if (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $figure-3-if (param $x i32) (result i32) - (if - (i32.and - (local.get $x) - (i32.const 1) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - (return - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; flipping of greater than/or equals ops, which are not in Souper IR - ;; CHECK: (func $flips - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $flips - (local $x i32) - (local $y i32) - (local.set $x (i32.ge_s (local.get $x) (local.get $y))) - (local.set $x (i32.ge_u (local.get $x) (local.get $y))) - (local.set $x (i32.gt_s (local.get $x) (local.get $y))) - (local.set $x (i32.gt_u (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $various-conditions-1 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $various-conditions-1 (param $x i32) - (if - (local.get $x) - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - ) - ) - ;; CHECK: (func $various-conditions-2 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $various-conditions-2 (param $x i32) - (if - (i32.lt_s - (local.get $x) - (i32.const 0) - ) - (local.set $x - (i32.sub - (local.get $x) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $various-conditions-3 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $various-conditions-3 (param $x i32) - (if - (i32.reinterpret_f32 (f32.const 0)) - (local.set $x - (i32.sub - (local.get $x) - (i32.const 4) - ) - ) - ) - ) - ;; CHECK: (func $various-conditions-4 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $various-conditions-4 (param $x i32) - (if - (unreachable) - (local.set $x - (i32.add - (local.get $x) - (i32.const 3) - ) - ) - ) - ) - ;; CHECK: (func $unaries (param $x i32) (param $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.popcnt - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unaries (param $x i32) (param $y i32) - (if - (i32.eqz - (local.get $x) - ) - (local.set $x - (i32.add - (i32.ctz - (local.get $y) - ) - (i32.sub - (i32.clz - (local.get $x) - ) - (i32.popcnt - (local.get $y) - ) - ) - ) - ) - ) - ) - ;; CHECK: (func $unary-condition (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unary-condition (param $x i32) - (if - (i32.ctz - (i32.gt_u - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $unary-condition-2 (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unary-condition-2 (param $x i32) - (if - (i32.eqz - (i32.gt_u - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $if-else-cond (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else-cond (param $x i32) (result i32) - (if - (i32.lt_s - (local.get $x) - (i32.const 1) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - (return - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $trivial-ret (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial-ret (result i32) - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - ;; CHECK: (func $trivial-const (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial-const (result i32) - (i32.const 0) - ) - ;; CHECK: (func $trivial-const-block (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $trivial-const-block (result i32) - (nop) - (i32.const 0) - ) - ;; CHECK: (func $bad-phi-value (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bad-phi-value (result i32) - (if (result i32) - (if (result i32) - (i32.const 1) - (i32.load - (i32.const 0) - ) - (i32.const 0) - ) - (i32.const 0) - (i32.const 1) - ) - ) - ;; CHECK: (func $bad-phi-value-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bad-phi-value-2 (param $x i32) (result i32) - (if - (if (result i32) - (i32.const 1) - (i32.load - (i32.const 0) - ) - (i32.const 0) - ) - (local.set $x (i32.const 1)) - (local.set $x (i32.const 2)) - ) - (local.get $x) - ) - ;; CHECK: (func $select (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $select (param $x i32) (result i32) - (return - (select - (i32.const 1) - (i32.const 2) - (i32.const 3) - ) - ) - ) - ;; CHECK: (func $select-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $select-2 (param $x i32) (param $y i32) (result i32) - (return - (select - (i32.add - (local.get $x) - (local.get $y) - ) - (i32.add - (local.get $x) - (i32.const 1) - ) - (i32.add - (i32.const 2) - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $block-phi-1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block-phi-1 (param $x i32) (param $y i32) (result i32) - (block $out - (local.set $x - (i32.add - (local.get $x) - (i32.const 1) - ) - ) - (br_if $out (local.get $y)) - (local.set $x - (i32.add - (local.get $x) - (i32.const 2) - ) - ) - ) - (i32.add - (local.get $x) - (i32.const 3) - ) - ) - ;; CHECK: (func $block-phi-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block-phi-2 (param $x i32) (param $y i32) (result i32) - (block $out - (local.set $x - (i32.const 1) - ) - (br_if $out (local.get $y)) - (local.set $x - (i32.const 2) - ) - ) - (i32.add - (local.get $x) - (i32.const 3) - ) - ) - ;; CHECK: (func $zero_init-phi-bad_type (result f64) - ;; CHECK-NEXT: (local $x f64) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero_init-phi-bad_type (result f64) - (local $x f64) - (if - (i32.const 0) - (local.set $x - (f64.const 1) - ) - ) - (local.get $x) - ) - ;; CHECK: (func $phi-bad-type (result f64) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $phi-bad-type (result f64) - (block $label$1 (result f64) - (if (result f64) - (i32.const 0) - (f64.const 0) - (f64.const 1) - ) - ) - ) - ;; CHECK: (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $i i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $i - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $i - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) - (local $i i32) - (if - (i32.le_s - (local.get $x) - (local.get $y) - ) - (local.set $i - (i32.eq - (local.get $x) - (local.get $y) - ) - ) - (local.set $i - (i32.add - (local.get $x) - (local.get $y) - ) - ) - ) - (local.get $i) - ) - ;; CHECK: (func $call (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $call) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $call) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $call) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $call (result i32) - (return - (i32.mul - (i32.add - (call $call) - (call $call) - ) - (i32.add - (i32.const 10) - (call $call) - ) - ) - ) - ) - ;; CHECK: (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (return (local.get $x)) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (unreachable) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $out) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) - (block $out - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (br $out) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $out $out $out - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) - (block $out - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (br_table $out $out $out (i32.const 1)) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; no phi here! - (return - (local.get $x) - ) - ) - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) - (block $out - (if - (local.get $x) - (block - (local.set $x - (i32.const 1) - ) - (br_if $out - (local.get $x) - ) - ) - (local.set $x - (i32.const 2) - ) - ) - ;; there *IS* a phi here since it was a br_if - (return - (local.get $x) - ) - ) - (return - (local.get $x) - ) - ) - ;; CHECK: (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const -8531) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$3) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const -8531) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$2) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const -8531) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) - (block $label$1 - (block $label$2 - (block $label$3 - (if - (local.get $2) - (if - (local.get $0) - (block - (local.set $1 - (i32.const -8531) - ) - (br $label$3) - ) - (block - (local.set $1 - (i32.const -8531) - ) - (br $label$1) - ) - ) - ) - (br $label$2) - ) - (drop - (i32.load - (i32.const 0) - ) - ) - (br $label$1) - ) - (i32.store16 - (i32.const 1) - (local.get $1) - ) - (unreachable) - ) - (i32.store16 - (i32.const 0) - (i32.const -8531) - ) - ) - ;; CHECK: (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) - (block - (unreachable) - (if - (local.get $x) - (local.set $x - (i32.const 1) - ) - (local.set $x - (i32.const 2) - ) - ) - (return - (local.get $x) - ) - ) - ) - ;; CHECK: (func $merge-with-one-less (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (block $label$5 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_table $label$5 $label$4 $label$3 $label$2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $merge-with-one-less (param $var$0 i32) (result i32) - (block $label$1 - (block $label$2 - (block $label$3 - (block $label$4 - (block $label$5 - (br_table $label$5 $label$4 $label$3 $label$2 - (i32.load - (i32.const 1) - ) - ) - ) - (unreachable) - ) - (br $label$1) - ) - (f64.store - (i32.load - (local.tee $var$0 - (i32.const 8) - ) - ) - (f64.const 0) - ) - (br $label$1) - ) - (unreachable) - ) - (i32.store - (local.get $var$0) - (i32.const 16) - ) - (i32.const 1) - ) - ;; CHECK: (func $deep (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i32) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i32) - ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (local $24 i32) - ;; CHECK-NEXT: (local $25 i32) - ;; CHECK-NEXT: (local $26 i32) - ;; CHECK-NEXT: (local $27 i32) - ;; CHECK-NEXT: (local $28 i32) - ;; CHECK-NEXT: (local $29 i32) - ;; CHECK-NEXT: (local $30 i32) - ;; CHECK-NEXT: (local $31 i32) - ;; CHECK-NEXT: (local $32 i32) - ;; CHECK-NEXT: (local $33 i32) - ;; CHECK-NEXT: (local $34 i32) - ;; CHECK-NEXT: (local $35 i32) - ;; CHECK-NEXT: (local $36 i32) - ;; CHECK-NEXT: (local $37 i32) - ;; CHECK-NEXT: (local $38 i32) - ;; CHECK-NEXT: (local $39 i32) - ;; CHECK-NEXT: (local $40 i32) - ;; CHECK-NEXT: (local $41 i32) - ;; CHECK-NEXT: (local $42 i32) - ;; CHECK-NEXT: (local $43 i32) - ;; CHECK-NEXT: (local $44 i32) - ;; CHECK-NEXT: (local $45 i32) - ;; CHECK-NEXT: (local $46 i32) - ;; CHECK-NEXT: (local $47 i32) - ;; CHECK-NEXT: (local $48 i32) - ;; CHECK-NEXT: (local $49 i32) - ;; CHECK-NEXT: (local $50 i32) - ;; CHECK-NEXT: (local $51 i32) - ;; CHECK-NEXT: (local $52 i32) - ;; CHECK-NEXT: (local $53 i32) - ;; CHECK-NEXT: (local $54 i32) - ;; CHECK-NEXT: (local $55 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $deep (param $x i32) (result i32) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.set $x (i32.xor (local.get $x) (i32.const 1234))) - (local.set $x (i32.mul (local.get $x) (i32.const 1234))) - (local.get $x) - ) - ;; CHECK: (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i64) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i64) - ;; CHECK-NEXT: (local $9 i64) - ;; CHECK-NEXT: (local $10 i64) - ;; CHECK-NEXT: (local $11 i64) - ;; CHECK-NEXT: (local $12 i64) - ;; CHECK-NEXT: (local $13 i64) - ;; CHECK-NEXT: (local $14 i64) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i64) - ;; CHECK-NEXT: (local $17 i64) - ;; CHECK-NEXT: (local $18 i64) - ;; CHECK-NEXT: (local $19 i64) - ;; CHECK-NEXT: (local $20 i64) - ;; CHECK-NEXT: (local $21 i64) - ;; CHECK-NEXT: (local $22 i64) - ;; CHECK-NEXT: (local $23 i64) - ;; CHECK-NEXT: (local $24 i64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (i64.div_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) - (if - (i64.lt_s - (local.get $x) - (local.get $y) - ) - (if - (i64.eqz - (local.get $x) - ) - (local.set $t - (i64.add - (local.get $x) - (local.get $y) - ) - ) - (local.set $t - (i64.sub - (local.get $x) - (local.get $y) - ) - ) - ) - (if - (i64.eqz - (local.get $y) - ) - (local.set $t - (i64.mul - (local.get $x) - (local.get $y) - ) - ) - (local.set $t - (i64.div_s - (local.get $x) - (local.get $y) - ) - ) - ) - ) - (return (local.get $t)) - ) - ;; CHECK: (func $loop-1 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-1 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - ) - ;; neither needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-2 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-2 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.add (local.get $y) (i32.const 4))) - ) - ;; neither needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-3 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-3 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.add (local.get $y) (i32.const 4))) - (br_if $loopy (local.get $y)) - ) - ;; both needed - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-4 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-4 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (br_if $loopy (local.get $y)) - ) - ;; only x needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-5 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-5 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.const 2)) ;; same value - (br_if $loopy (local.get $y)) - ) - ;; only x needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-6 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-6 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (local.get $y)) ;; same value - (br_if $loopy (local.get $y)) - ) - ;; only x needed a phi - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-7 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-7 (param $x i32) (param $y i32) (result i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 3))) - (local.set $y (i32.const 5)) ;; different! - (br_if $loopy (local.get $y)) - ) - ;; y changed but we don't need a phi for it - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-8 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $z i32) - ;; CHECK-NEXT: (local $w i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-8 (param $x i32) (param $y i32) (result i32) - (local $z i32) - (local $w i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $z (local.get $x)) - (local.set $w (local.get $y)) - (local.set $x (i32.const 1)) ;; same! - (local.set $y (i32.const 4)) ;; different! - (br_if $loopy (local.get $y)) - ) - ;; x is always 3, and y needs a phi. - ;; each is also copied to another local, which we need - ;; to handle properly - (return - (i32.mul - (i32.add - (local.get $x) - (local.get $y) - ) - (i32.sub - (local.get $z) - (local.get $w) - ) - ) - ) - ) - ;; CHECK: (func $loop-9 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-9 (param $x i32) (param $y i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (loop $loopy - (local.set $t (local.get $x)) - (local.set $x (local.get $y)) - (local.set $y (local.get $t)) - (br_if $loopy (local.get $t)) - ) - ;; x and y swapped, so both need phis - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-10 (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $t - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-10 (param $x i32) (param $y i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 1)) - (loop $loopy ;; we swap the values. but we need a deeper analysis to figure that out... - (local.set $t (local.get $x)) - (local.set $x (local.get $y)) - (local.set $y (local.get $t)) - (br_if $loopy (local.get $t)) - ) - ;; x and y swapped, but the same constant was swapped - (return (i32.add (local.get $x) (local.get $y))) - ) - ;; CHECK: (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (loop $loopy - (local.set $x (i32.const 4)) - (br_if $loopy (local.get $t)) - (local.set $y (i32.const 5)) - (br_if $loopy (local.get $t)) - (local.set $z (i32.const 6)) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loopy - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 4))) - (br_if $loopy (local.get $t)) - (local.set $y (i32.add (local.get $y) (i32.const 5))) - (br_if $loopy (local.get $t)) - (local.set $z (i32.add (local.get $z) (i32.const 6))) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $loopy) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (loop $loopy - (block $out - (local.set $x (i32.add (local.get $x) (i32.const 4))) - (br_if $out (local.get $t)) - (local.set $y (i32.add (local.get $y) (i32.const 5))) - (br_if $out (local.get $t)) - (local.set $z (i32.add (local.get $z) (i32.const 6))) - (br $loopy) - ) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (local $t i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $out - ;; CHECK-NEXT: (loop $loopy - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (local.get $t) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $loopy) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - (local $t i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 2)) - (local.set $z (i32.const 3)) - (block $out - (loop $loopy - (local.set $x (i32.add (local.get $x) (i32.const 4))) - (br_if $out (local.get $t)) - (local.set $y (i32.add (local.get $y) (i32.const 5))) - (br_if $out (local.get $t)) - (local.set $z (i32.add (local.get $z) (i32.const 6))) - (br $loopy) - ) - ) - (return (select (local.get $x) (local.get $y) (local.get $z))) - ) - ;; CHECK: (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 f64) - ;; CHECK-NEXT: (local $9 f64) - ;; CHECK-NEXT: (local $10 f64) - ;; CHECK-NEXT: (local $11 f64) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (loop $label$2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) - (if - (local.get $var$2) - (drop - (loop $label$2 (result f64) - (if - (block $label$3 (result i32) - (if - (i32.const 0) - (unreachable) - ) - (nop) - (i32.const 0) - ) - (unreachable) - ) - (br_if $label$2 - (local.get $var$2) - ) - (f64.const 0) - ) - ) - ) - ) - ;; CHECK: (func $loop-unreachable - ;; CHECK-NEXT: (local $var$0 i32) - ;; CHECK-NEXT: (local $var$1 f64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 f64) - ;; CHECK-NEXT: (local $12 f64) - ;; CHECK-NEXT: (local $13 f64) - ;; CHECK-NEXT: (loop $label$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (loop $label$6 - ;; CHECK-NEXT: (block $label$7 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$7 - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$7 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $label$6 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $loop-unreachable - (local $var$0 i32) - (local $var$1 f64) - (loop $label$1 - (local.set $var$1 - (block $label$2 (result f64) - (block $label$3 - (local.set $var$0 - (block $label$4 (result i32) - (if - (i32.const 1337) - (unreachable) - ) - (local.get $var$0) - ) - ) - (loop $label$6 - (br_if $label$6 - (block $label$7 (result i32) - (drop - (br_if $label$7 - (local.get $var$0) - (i32.const 65535) - ) - ) - (drop - (br_if $label$7 - (local.get $var$0) - (i32.const 0) - ) - ) - (unreachable) - ) - ) - ) - ) - (local.get $var$1) - ) - ) - (br $label$1) - ) - ) - ;; CHECK: (func $phi-value-turns-bad (result f64) - ;; CHECK-NEXT: (local $var$0 i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $var$2 f32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 f32) - ;; CHECK-NEXT: (local $13 f32) - ;; CHECK-NEXT: (local $14 f32) - ;; CHECK-NEXT: (local $15 f32) - ;; CHECK-NEXT: (local $16 f64) - ;; CHECK-NEXT: (local $17 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (i32.atomic.rmw16.sub_u offset=22 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (loop $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $phi-value-turns-bad (result f64) - (local $var$0 i32) - (local $var$1 i32) - (local $var$2 f32) - (local.set $var$2 - (if (result f32) - (local.tee $var$0 - (i32.atomic.rmw16.sub_u offset=22 - (i32.const 0) - (i32.const 0) - ) - ) - (unreachable) - (block (result f32) - (if - (loop $label$3 (result i32) - (block $label$4 (result i32) - (i32.clz - (br_if $label$4 - (local.get $var$0) - (i32.const 1) - ) - ) - ) - ) - (nop) - ) - (f32.const 1) - ) - ) - ) - (unreachable) - ) - ;; CHECK: (func $multi-use (param $x i32) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multi-use (param $x i32) (result i32) - (local $temp i32) - (local.set $temp (i32.add (local.get $x) (i32.const 1))) - (i32.add (local.get $temp) (local.get $temp)) - ) - ;; CHECK: (func $multi-use-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multi-use-2 (param $x i32) (result i32) - (local $temp i32) - (local.set $temp (i32.add (local.get $x) (i32.const 1))) - (local.set $x (i32.mul (local.get $temp) (i32.const 2))) - (i32.sub (local.get $x) (local.get $temp)) - ) - ;; CHECK: (func $many-single-uses-with-param (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $many-single-uses-with-param (param $x i32) (result i32) - (return - (i32.eqz - (i32.add - (i32.mul - (i32.const 10) - (local.get $x) - ) - (i32.sub - (i32.ctz - (local.get $x) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (func "replaced-print-internal" (param $var$0 i32) - (local $var$1 i32) - (local $var$2 i32) - (local $var$3 i32) - (if - (local.tee $var$0 - (i32.add - (local.get $var$0) - (i32.const -7) - ) - ) - (block $label$2 - (block $label$3 - (local.set $var$1 - (local.get $var$0) - ) - (br_if $label$3 - (local.tee $var$3 - (i32.const 12) - ) - ) - (unreachable) - ) - (br_if $label$2 - (i32.eqz - (local.get $var$1) - ) - ) - (if - (i32.ne - (i32.load - (i32.const 0) - ) - (local.get $var$0) - ) - (unreachable) - ) - (unreachable) - ) - ) - ) - ;; CHECK: (func $55 (param $var$0 i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $var$2 i32) - ;; CHECK-NEXT: (local $var$3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (i32.const -7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (block $label$3 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$3 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - - ;; CHECK: (func $multiple-uses-to-non-expression (param $x i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multiple-uses-to-non-expression (param $x i32) - (local $temp i32) - (local.set $x - (i32.add - (local.get $x) - (i32.const 10) - ) - ) - (i32.store - (i32.const 1) - (local.get $x) ;; x+10 has two uses! - ) - (i32.store - (i32.const 2) - (i32.add - (local.get $x) - (i32.const 20) - ) - ) - ) - ;; CHECK: (func $nested-phi-forwarding (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $var$2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (block $label$2 - ;; CHECK-NEXT: (loop $label$3 - ;; CHECK-NEXT: (block $label$4 - ;; CHECK-NEXT: (block $label$5 - ;; CHECK-NEXT: (block $label$6 - ;; CHECK-NEXT: (block $label$7 - ;; CHECK-NEXT: (block $label$8 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 - ;; CHECK-NEXT: (local.get $var$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$4) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $label$3 - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$9 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$9 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store offset=176 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $var$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-phi-forwarding (param $var$0 i32) (result i32) - (local $var$1 i32) - (local $var$2 i32) - (block $label$1 - (block $label$2 - (loop $label$3 - (block $label$4 - (block $label$5 - (block $label$6 - (block $label$7 - (block $label$8 - (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 - (local.get $var$0) - ) - ) - (local.set $var$1 - (i32.const 1) - ) - ) - (br $label$4) - ) - (unreachable) - ) - (br $label$1) - ) - (br_if $label$3 - (local.tee $var$2 - (i32.const 1) - ) - ) - ) - ) - (block $label$9 - (br_if $label$9 - (i32.or - (i32.const 1) - (local.get $var$1) - ) - ) - ) - (unreachable) - ) - (i32.store offset=176 - (i32.const 0) - (local.get $var$2) - ) - (i32.const 0) - ) - ;; CHECK: (func $zext-numGets (param $var$0 i32) (param $var$1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zext-numGets (param $var$0 i32) (param $var$1 i32) - (if - (i32.ctz - (block $label$1 (result i32) - (drop - (br_if $label$1 - (i32.const 1) - (i32.load - (i32.const -8) - ) - ) - ) - (i32.eqz - (i32.load - (i32.const -16) - ) - ) - ) - ) - (unreachable) - ) - ) - ;; CHECK: (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) - (local $temp i32) - (if - (i32.ctz - (block $label$1 (result i32) - (drop - (br_if $label$1 - (i32.const 1) - (i32.load - (i32.const -8) - ) - ) - ) - (local.set $temp - (i32.eqz - (i32.load - (i32.const -16) - ) - ) - ) - (drop - (local.get $temp) - ) - (local.get $temp) - ) - ) - (unreachable) - ) - ) - ;; CHECK: (func $flipped-needs-right-origin (param $var$0 i32) (result i32) - ;; CHECK-NEXT: (local $var$1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $flipped-needs-right-origin (param $var$0 i32) (result i32) - (local $var$1 i32) - (block $label$1 - (br_if $label$1 - (i32.load - (i32.const 1) - ) - ) - (local.set $var$1 - (i32.const 2) - ) - ) - (if - (i32.gt_s - (i32.const 3) - (i32.add - (local.get $var$1) - (i32.const 4) - ) - ) - (unreachable) - ) - (i32.const 5) - ) - ;; CHECK: (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - (i32.store - (local.tee $var$1 - (i32.gt_u - (local.get $var$1) - (i32.const 1) - ) - ) - (i32.const 2) - ) - (i32.store offset=8 - (i32.const 3) - (i32.sub - (i32.const 4) - (local.get $var$1) - ) - ) - (unreachable) - ) - ;; CHECK: (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (loop $label$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br $label$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) - (loop $label$1 - (if - (i32.const 0) - (block - (local.set $var$2 - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - (br $label$1) - ) - ) - (local.set $var$3 - (local.get $var$2) - ) - (local.set $var$2 - (local.get $var$3) - ) - (br $label$1) - ) - ) - ;; CHECK: (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - ;; CHECK-NEXT: (local $var$3 i32) - ;; CHECK-NEXT: (local $var$4 i32) - ;; CHECK-NEXT: (local $var$5 i32) - ;; CHECK-NEXT: (local $var$6 i32) - ;; CHECK-NEXT: (local $var$7 i32) - ;; CHECK-NEXT: (local $var$8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (loop $label$2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $var$3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $var$1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $var$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $var$1) - ;; CHECK-NEXT: (local.set $var$3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $var$3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) - (local $var$3 i32) - (local $var$4 i32) - (local $var$5 i32) - (local $var$6 i32) - (local $var$7 i32) - (local $var$8 i32) - (local.set $var$1 - (i32.const 1) - ) - (if - (i32.const 0) - (loop $label$2 - (if - (local.get $var$1) - (nop) - ) - (local.set $var$1 - (i32.sub - (i32.const 0) - (local.tee $var$3 - (i32.const 1) - ) - ) - ) - (br_if $label$2 - (i32.const 0) - ) - ) - ) - (if - (local.get $var$1) - (local.set $var$3 - (i32.const 1) - ) - ) - (i32.store - (i32.const 8) - (i32.add - (local.get $var$3) - (i32.const 16) - ) - ) - (i32.store - (i32.const 8) - (i32.const 64) - ) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/passes/flatten.wast binaryen-99/test/lit/passes/flatten.wast --- binaryen-108/test/lit/passes/flatten.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/flatten.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --flatten -S -o - | filecheck %s - -(module - ;; CHECK: (type $simplefunc (func)) - (type $simplefunc (func)) - ;; CHECK: (func $0 (param $0 (ref $simplefunc)) (result (ref $simplefunc)) - ;; CHECK-NEXT: (local $1 (ref null $simplefunc)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (param $0 (ref $simplefunc)) (result (ref $simplefunc)) - ;; a local.get of a non-nullable param is ok, and does not need to be - ;; modified - (local.get $0) - ) -) diff -Nru binaryen-108/test/lit/passes/fpcast-emu.wast binaryen-99/test/lit/passes/fpcast-emu.wast --- binaryen-108/test/lit/passes/fpcast-emu.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/fpcast-emu.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,408 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --fpcast-emu -S -o - | filecheck %s - -(module - ;; CHECK: (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) (result i64))) - - ;; CHECK: (type $i32_i64_f32_f64_=>_f32 (func (param i32 i64 f32 f64) (result f32))) - - ;; CHECK: (type $vijfd (func (param i32 i64 f32 f64))) - (type $vijfd (func (param i32) (param i64) (param f32) (param f64))) - ;; CHECK: (type $jii (func (param i32 i32) (result i64))) - (type $jii (func (param i32) (param i32) (result i64))) - ;; CHECK: (type $fjj (func (param i64 i64) (result f32))) - (type $fjj (func (param i64) (param i64) (result f32))) - ;; CHECK: (type $dff (func (param f32 f32) (result f64))) - (type $dff (func (param f32) (param f32) (result f64))) - ;; CHECK: (type $idd (func (param f64 f64) (result i32))) - (type $idd (func (param f64) (param f64) (result i32))) - ;; CHECK: (import "env" "imported_func" (func $imported-func (param i32 i64 f32 f64) (result f32))) - (import "env" "imported_func" (func $imported-func (param i32 i64 f32 f64) (result f32))) - (table 10 10 funcref) - (elem (i32.const 0) $a $b $c $d $e $e $imported-func) - ;; CHECK: (table $0 10 10 funcref) - - ;; CHECK: (elem (i32.const 0) $byn$fpcast-emu$a $byn$fpcast-emu$b $byn$fpcast-emu$c $byn$fpcast-emu$d $byn$fpcast-emu$e $byn$fpcast-emu$e $byn$fpcast-emu$imported-func) - - ;; CHECK: (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) - (call_indirect (type $vijfd) - (i32.const 1) - (i64.const 2) - (f32.const 3) - (f64.const 4) - (i32.const 1337) - ) - ) - ;; CHECK: (func $b (param $x i32) (param $y i32) (result i64) - ;; CHECK-NEXT: (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b (param $x i32) (param $y i32) (result i64) - (call_indirect (type $jii) - (i32.const 1) - (i32.const 2) - (i32.const 1337) - ) - ) - ;; CHECK: (func $c (param $x i64) (param $y i64) (result f32) - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $c (param $x i64) (param $y i64) (result f32) - (call_indirect (type $fjj) - (i64.const 1) - (i64.const 2) - (i32.const 1337) - ) - ) - ;; CHECK: (func $d (param $x f32) (param $y f32) (result f64) - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $d (param $x f32) (param $y f32) (result f64) - (call_indirect (type $dff) - (f32.const 1) - (f32.const 2) - (i32.const 1337) - ) - ) - ;; CHECK: (func $e (param $x f64) (param $y f64) (result i32) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $e (param $x f64) (param $y f64) (result i32) - (call_indirect (type $idd) - (f64.const 1) - (f64.const 2) - (i32.const 1337) - ) - ) -) -;; CHECK: (func $byn$fpcast-emu$a (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (call $a -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: (f32.reinterpret_i32 -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (f64.reinterpret_i64 -;; CHECK-NEXT: (local.get $3) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i64.const 0) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$fpcast-emu$b (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (call $b -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$fpcast-emu$c (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (i64.extend_i32_u -;; CHECK-NEXT: (i32.reinterpret_f32 -;; CHECK-NEXT: (call $c -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$fpcast-emu$d (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (i64.reinterpret_f64 -;; CHECK-NEXT: (call $d -;; CHECK-NEXT: (f32.reinterpret_i32 -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (f32.reinterpret_i32 -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$fpcast-emu$e (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (i64.extend_i32_u -;; CHECK-NEXT: (call $e -;; CHECK-NEXT: (f64.reinterpret_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (f64.reinterpret_i64 -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$fpcast-emu$imported-func (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (i64.extend_i32_u -;; CHECK-NEXT: (i32.reinterpret_f32 -;; CHECK-NEXT: (call $imported-func -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: (f32.reinterpret_i32 -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (f64.reinterpret_i64 -;; CHECK-NEXT: (local.get $3) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - (type $0 (func (param i64))) - ;; CHECK: (type $1 (func (param f32) (result i64))) - (type $1 (func (param f32) (result i64))) - ;; CHECK: (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) (result i64))) - - ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) - (global $global$0 (mut i32) (i32.const 10)) - (table 42 42 funcref) - ;; CHECK: (table $0 42 42 funcref) - - ;; CHECK: (export "func_106" (func $0)) - (export "func_106" (func $0)) - ;; CHECK: (func $0 (param $0 f32) (result i64) - ;; CHECK-NEXT: (block $label$1 (result i64) - ;; CHECK-NEXT: (loop $label$2 - ;; CHECK-NEXT: (global.set $global$0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) - ;; CHECK-NEXT: (br $label$1 - ;; CHECK-NEXT: (i64.const 4294967295) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (; 0 ;) (type $1) (param $0 f32) (result i64) - (block $label$1 (result i64) - (loop $label$2 - (global.set $global$0 - (i32.const 0) - ) - (call_indirect (type $0) - (br $label$1 - (i64.const 4294967295) - ) - (i32.const 18) - ) - ) - ) - ) -) -(module - (table 42 42 funcref) - (elem (i32.const 0) $a $b) - ;; CHECK: (type $f32_=>_none (func (param f32))) - - ;; CHECK: (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) (result i64))) - - ;; CHECK: (type $f64_=>_none (func (param f64))) - - ;; CHECK: (table $0 42 42 funcref) - - ;; CHECK: (elem (i32.const 0) $byn$fpcast-emu$a $byn$fpcast-emu$b) - - ;; CHECK: (export "dynCall_vf" (func $dynCall_vf)) - (export "dynCall_vf" (func $dynCall_vf)) - ;; CHECK: (export "dynCall_vd" (func $min_vd)) - (export "dynCall_vd" (func $min_vd)) - ;; CHECK: (func $a (param $0 f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $a (param $0 f32)) - ;; CHECK: (func $b (param $0 f64) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $b (param $0 f64)) - ;; CHECK: (func $dynCall_vf (param $0 f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $dynCall_vf (param $0 f32)) - ;; CHECK: (func $min_vd (param $0 f32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $min_vd (param $0 f32)) -) - -;; CHECK: (func $byn$fpcast-emu$a (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (call $a -;; CHECK-NEXT: (f32.reinterpret_i32 -;; CHECK-NEXT: (i32.wrap_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i64.const 0) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$fpcast-emu$b (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) -;; CHECK-NEXT: (call $b -;; CHECK-NEXT: (f64.reinterpret_i64 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i64.const 0) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/generate-dyncalls_all-features.wast binaryen-99/test/lit/passes/generate-dyncalls_all-features.wast --- binaryen-108/test/lit/passes/generate-dyncalls_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/generate-dyncalls_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,105 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --generate-dyncalls --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i64 (func (param i32) (result i64))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $f1 $f2) - - ;; CHECK: (export "dynCall_i" (func $dynCall_i)) - - ;; CHECK: (export "dynCall_ji" (func $dynCall_ji)) - - ;; CHECK: (export "dynCall_vii" (func $dynCall_vii)) - - ;; CHECK: (func $f1 (result i32) - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - (func $f1 (result i32) - (i32.const 1024) - ) - ;; CHECK: (func $f2 (param $0 i32) (result i64) - ;; CHECK-NEXT: (i64.const 42) - ;; CHECK-NEXT: ) - (func $f2 (param i32) (result i64) - (i64.const 42) - ) - (table 2 2 funcref) - (elem (i32.const 0) $f1 $f2) -) -;; CHECK: (func $dynCall_i (param $fptr i32) (result i32) -;; CHECK-NEXT: (call_indirect $0 (type $none_=>_i32) -;; CHECK-NEXT: (local.get $fptr) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $dynCall_ji (param $fptr i32) (param $0 i32) (result i64) -;; CHECK-NEXT: (call_indirect $0 (type $i32_=>_i64) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $fptr) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $dynCall_vii (param $fptr i32) (param $0 i32) (param $1 i32) -;; CHECK-NEXT: (call_indirect $0 (type $i32_i32_=>_none) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: (local.get $fptr) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (import "env" "table" (table $timport$0 1 1 funcref)) - (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - ;; CHECK: (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - (import "env" "table" (table 1 1 funcref)) - (elem (i32.const 0) $f) - ;; CHECK: (elem (i32.const 0) $f) - - ;; CHECK: (export "dynCall_i" (func $dynCall_i)) - - ;; CHECK: (export "dynCall_vii" (func $dynCall_vii)) - - ;; CHECK: (func $f (result i32) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - (func $f (result i32) - (i32.const 42) - ) -) -;; CHECK: (func $dynCall_i (param $fptr i32) (result i32) -;; CHECK-NEXT: (call_indirect $timport$0 (type $none_=>_i32) -;; CHECK-NEXT: (local.get $fptr) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $dynCall_vii (param $fptr i32) (param $0 i32) (param $1 i32) -;; CHECK-NEXT: (call_indirect $timport$0 (type $i32_i32_=>_none) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: (local.get $fptr) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/generate-i64-dyncalls.wast binaryen-99/test/lit/passes/generate-i64-dyncalls.wast --- binaryen-108/test/lit/passes/generate-i64-dyncalls.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/generate-i64-dyncalls.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --generate-i64-dyncalls -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_=>_i64 (func (param i32) (result i64))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) - - ;; CHECK: (table $0 2 2 funcref) - - ;; CHECK: (elem (i32.const 0) $f1 $f2) - - ;; CHECK: (export "dynCall_ji" (func $dynCall_ji)) - - ;; CHECK: (func $f1 (result i32) - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - (func $f1 (result i32) - (i32.const 1024) - ) - ;; CHECK: (func $f2 (param $0 i32) (result i64) - ;; CHECK-NEXT: (i64.const 42) - ;; CHECK-NEXT: ) - (func $f2 (param i32) (result i64) - (i64.const 42) - ) - (table 2 2 funcref) - (elem (i32.const 0) $f1 $f2) -) -;; CHECK: (func $dynCall_ji (param $fptr i32) (param $0 i32) (result i64) -;; CHECK-NEXT: (call_indirect (type $i32_=>_i64) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $fptr) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/global-refining.wast binaryen-99/test/lit/passes/global-refining.wast --- binaryen-108/test/lit/passes/global-refining.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/global-refining.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --global-refining -all -S -o - | filecheck %s - -(module - ;; Globals with no assignments aside from their initial values. The first is - ;; a null, so we have nothing concrete to improve with (though we could use - ;; the type of the null perhaps, TODO). The second is a ref.func which lets - ;; us refine. - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $func-null-init (mut anyref) (ref.null func)) - (global $func-null-init (mut anyref) (ref.null func)) - ;; CHECK: (global $func-func-init (mut (ref $none_=>_none)) (ref.func $foo)) - (global $func-func-init (mut anyref) (ref.func $foo)) - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo) -) - -(module - ;; Globals with later assignments of null. The global with a function in its - ;; init will update the null to allow it to refine. - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $func-null-init (mut anyref) (ref.null func)) - (global $func-null-init (mut anyref) (ref.null func)) - ;; CHECK: (global $func-func-init (mut (ref null $none_=>_none)) (ref.func $foo)) - (global $func-func-init (mut anyref) (ref.func $foo)) - - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (global.set $func-null-init - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $func-func-init - ;; CHECK-NEXT: (ref.null $none_=>_none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (global.set $func-null-init (ref.null any)) - (global.set $func-func-init (ref.null any)) - ) -) - -(module - ;; Globals with later assignments of something non-null. Both can be refined, - ;; and the one with a non-null initial value can even become non-nullable. - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $func-null-init (mut (ref null $none_=>_none)) (ref.null $none_=>_none)) - (global $func-null-init (mut anyref) (ref.null func)) - ;; CHECK: (global $func-func-init (mut (ref $none_=>_none)) (ref.func $foo)) - (global $func-func-init (mut anyref) (ref.func $foo)) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (global.set $func-null-init - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $func-func-init - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (global.set $func-null-init (ref.func $foo)) - (global.set $func-func-init (ref.func $foo)) - ) -) - -(module - ;; A global with multiple later assignments. The refined type is more - ;; specific than the original, but less than each of the non-null values. - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func)) - - ;; CHECK: (global $global (mut funcref) (ref.null func)) - (global $global (mut anyref) (ref.null any)) - - ;; CHECK: (elem declare func $bar $foo) - - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (ref.func $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (global.set $global (ref.func $foo)) - (global.set $global (ref.func $bar)) - (global.set $global (ref.null func)) - ;; These nulls will be updated. - (global.set $global (ref.null eq)) - (global.set $global (ref.null data)) - ) - - ;; CHECK: (func $bar (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $bar (param $x i32) - ;; A function with a different signature, whose reference is also assigned - ;; to the global. - ) -) diff -Nru binaryen-108/test/lit/passes/gto_and_cfp_in_O.wast binaryen-99/test/lit/passes/gto_and_cfp_in_O.wast --- binaryen-108/test/lit/passes/gto_and_cfp_in_O.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/gto_and_cfp_in_O.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: foreach %s %t wasm-opt -O -all --nominal -S -o - | filecheck %s - -;; Test that -O, with nominal typing + GC enabled, will run global type -;; optimization in conjunction with constant field propagation etc. - -(module - (type $struct (struct_subtype (field (mut funcref)) (field (mut i32)) data)) - - (global $glob (ref $struct) (struct.new $struct - (ref.func $by-ref) - (i32.const 100) - )) - - (func $by-ref - ;; This function is kept alive by the reference in $glob. After we remove - ;; the field that the funcref is written to, we remove the funcref, which - ;; means this function can be removed. - ;; - ;; Once it is removed, this write no longer exists, and does not hamper - ;; constant field propagation from inferring the value of the i32 field. - (struct.set $struct 1 - (global.get $glob) - (i32.const 200) - ) - ) - - ;; CHECK: (type $none_=>_i32 (func_subtype (result i32) func)) - - ;; CHECK: (export "main" (func $main)) - - ;; CHECK: (func $main (type $none_=>_i32) (; has Stack IR ;) (result i32) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - (func $main (export "main") (result i32) - ;; After all the above optimizations, we can infer that $main should simply - ;; return 100. - (struct.get $struct 1 - (global.get $glob) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/gto-mutability.wast binaryen-99/test/lit/passes/gto-mutability.wast --- binaryen-108/test/lit/passes/gto-mutability.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/gto-mutability.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,572 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --gto -all -S -o - | filecheck %s -;; (remove-unused-names is added to test fallthrough values without a block -;; name getting in the way) - -(module - ;; The struct here has three fields, and the second of them has no struct.set - ;; which means we can make it immutable. - - ;; CHECK: (type $struct (struct_subtype (field (mut funcref)) (field funcref) (field (mut funcref)) data)) - (type $struct (struct (field (mut funcref)) (field (mut funcref)) (field (mut funcref)))) - - ;; CHECK: (type $two-params (func_subtype (param (ref $struct) (ref $struct)) func)) - (type $two-params (func (param (ref $struct)) (param (ref $struct)))) - - ;; Test that we update tag types properly. - (table 0 funcref) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (type $none_=>_ref?|$struct| (func_subtype (result (ref null $struct)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (table $0 0 funcref) - - ;; CHECK: (elem declare func $func-two-params) - - ;; CHECK: (tag $tag (param (ref $struct))) - (tag $tag (param (ref $struct))) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - (local $temp (ref null $struct)) - ;; The presence of a struct.new does not prevent this optimization: we just - ;; care about writes using struct.set. - (drop - (struct.new $struct - (ref.null func) - (ref.null func) - (ref.null func) - ) - ) - (struct.set $struct 0 - (local.get $x) - (ref.null func) - ) - (struct.set $struct 2 - (local.get $x) - (ref.null func) - ) - ;; Test that local types remain valid after our work (otherwise, we'd get a - ;; validation error). - (local.set $temp - (local.get $x) - ) - ;; Test that struct.get types remain valid after our work. - (drop - (struct.get $struct 0 - (local.get $x) - ) - ) - (drop - (struct.get $struct 1 - (local.get $x) - ) - ) - ) - - ;; CHECK: (func $foo (type $none_=>_ref?|$struct|) (result (ref null $struct)) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (pop (ref $struct)) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - (func $foo (result (ref null $struct)) - ;; Use a tag so that we test proper updating of its type after making - ;; changes. - (try - (do - (nop) - ) - (catch $tag - (return - (pop (ref $struct)) - ) - ) - ) - (ref.null $struct) - ) - - ;; CHECK: (func $func-two-params (type $two-params) (param $x (ref $struct)) (param $y (ref $struct)) - ;; CHECK-NEXT: (local $z (ref null $two-params)) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (ref.func $func-two-params) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_indirect $0 (type $two-params) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func-two-params (param $x (ref $struct)) (param $y (ref $struct)) - ;; This function has two params, which means a tuple type is used for its - ;; signature, which we must also update. To verify the update is correct, - ;; assign it to a local. - (local $z (ref null $two-params)) - (local.set $z - (ref.func $func-two-params) - ) - ;; Also check that a call_indirect still validates after the rewriting. - (call_indirect (type $two-params) - (local.get $x) - (local.get $y) - (i32.const 0) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 2 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - ;; --gto will remove fields that are not read from, so add reads to any - ;; that don't already have them. - (drop (struct.get $struct 2 (ref.null $struct))) - ) -) - -(module - ;; Test recursion between structs where we only modify one. Specifically $B - ;; has no writes to either of its fields. - - ;; CHECK: (type $A (struct_subtype (field (mut (ref null $B))) (field (mut i32)) data)) - (type $A (struct (field (mut (ref null $B))) (field (mut i32)) )) - ;; CHECK: (type $B (struct_subtype (field (ref null $A)) (field f64) data)) - (type $B (struct (field (mut (ref null $A))) (field (mut f64)) )) - - ;; CHECK: (type $ref|$A|_=>_none (func_subtype (param (ref $A)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $ref|$A|_=>_none) (param $x (ref $A)) - ;; CHECK-NEXT: (struct.set $A 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $A 1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $A)) - (struct.set $A 0 - (local.get $x) - (ref.null $B) - ) - (struct.set $A 1 - (local.get $x) - (i32.const 20) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $A 1 - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 0 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 1 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $A 0 (ref.null $A))) - (drop (struct.get $A 1 (ref.null $A))) - (drop (struct.get $B 0 (ref.null $B))) - (drop (struct.get $B 1 (ref.null $B))) - ) -) - -(module - ;; As before, but flipped so that $A's fields can become immutable. - - ;; CHECK: (type $B (struct_subtype (field (mut (ref null $A))) (field (mut f64)) data)) - (type $B (struct (field (mut (ref null $A))) (field (mut f64)) )) - - ;; CHECK: (type $A (struct_subtype (field (ref null $B)) (field i32) data)) - (type $A (struct (field (mut (ref null $B))) (field (mut i32)) )) - - ;; CHECK: (type $ref|$B|_=>_none (func_subtype (param (ref $B)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $ref|$B|_=>_none) (param $x (ref $B)) - ;; CHECK-NEXT: (struct.set $B 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $B 1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $B)) - (struct.set $B 0 - (local.get $x) - (ref.null $A) - ) - (struct.set $B 1 - (local.get $x) - (f64.const 3.14159) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $A 1 - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 0 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 1 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $A 0 (ref.null $A))) - (drop (struct.get $A 1 (ref.null $A))) - (drop (struct.get $B 0 (ref.null $B))) - (drop (struct.get $B 1 (ref.null $B))) - ) -) - -(module - ;; As before, but now one field in each can become immutable. - - ;; CHECK: (type $B (struct_subtype (field (ref null $A)) (field (mut f64)) data)) - (type $B (struct (field (mut (ref null $A))) (field (mut f64)) )) - - ;; CHECK: (type $A (struct_subtype (field (mut (ref null $B))) (field i32) data)) - (type $A (struct (field (mut (ref null $B))) (field (mut i32)) )) - - ;; CHECK: (type $ref|$A|_ref|$B|_=>_none (func_subtype (param (ref $A) (ref $B)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $ref|$A|_ref|$B|_=>_none) (param $x (ref $A)) (param $y (ref $B)) - ;; CHECK-NEXT: (struct.set $A 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $B 1 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $A)) (param $y (ref $B)) - (struct.set $A 0 - (local.get $x) - (ref.null $B) - ) - (struct.set $B 1 - (local.get $y) - (f64.const 3.14159) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $A 1 - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 0 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 1 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $A 0 (ref.null $A))) - (drop (struct.get $A 1 (ref.null $A))) - (drop (struct.get $B 0 (ref.null $B))) - (drop (struct.get $B 1 (ref.null $B))) - ) -) - -(module - ;; Field #0 is already immutable. - ;; Field #1 is mutable and can become so. - ;; Field #2 is mutable and must remain so. - - ;; CHECK: (type $struct (struct_subtype (field i32) (field i32) (field (mut i32)) data)) - (type $struct (struct (field i32) (field (mut i32)) (field (mut i32)))) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (struct.set $struct 2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - (struct.set $struct 2 - (local.get $x) - (i32.const 1) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 1 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 2 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $struct 0 (ref.null $struct))) - (drop (struct.get $struct 1 (ref.null $struct))) - (drop (struct.get $struct 2 (ref.null $struct))) - ) -) - -(module - ;; Subtyping. Without a write in either supertype or subtype, we can - ;; optimize the field to be immutable. - - ;; CHECK: (type $super (struct_subtype (field i32) data)) - (type $super (struct (field (mut i32)))) - ;; CHECK: (type $sub (struct_subtype (field i32) $super)) - (type $sub (struct_subtype (field (mut i32)) $super)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $super - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $sub - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func - ;; The presence of struct.new do not prevent us optimizing - (drop - (struct.new $super - (i32.const 1) - ) - ) - (drop - (struct.new $sub - (i32.const 1) - ) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $super 0 - ;; CHECK-NEXT: (ref.null $super) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $sub 0 - ;; CHECK-NEXT: (ref.null $sub) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $super 0 (ref.null $super))) - (drop (struct.get $sub 0 (ref.null $sub))) - ) -) - -(module - ;; As above, but add a write in the super, which prevents optimization. - - ;; CHECK: (type $super (struct_subtype (field (mut i32)) data)) - (type $super (struct (field (mut i32)))) - ;; CHECK: (type $sub (struct_subtype (field (mut i32)) $super)) - (type $sub (struct_subtype (field (mut i32)) $super)) - - ;; CHECK: (type $ref|$super|_=>_none (func_subtype (param (ref $super)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $ref|$super|_=>_none) (param $x (ref $super)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $super - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $sub - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $super 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $super)) - ;; The presence of struct.new do not prevent us optimizing - (drop - (struct.new $super - (i32.const 1) - ) - ) - (drop - (struct.new $sub - (i32.const 1) - ) - ) - (struct.set $super 0 - (local.get $x) - (i32.const 2) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $super 0 - ;; CHECK-NEXT: (ref.null $super) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $sub 0 - ;; CHECK-NEXT: (ref.null $sub) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $super 0 (ref.null $super))) - (drop (struct.get $sub 0 (ref.null $sub))) - ) -) - -(module - ;; As above, but add a write in the sub, which prevents optimization. - - - ;; CHECK: (type $super (struct_subtype (field (mut i32)) data)) - (type $super (struct (field (mut i32)))) - ;; CHECK: (type $sub (struct_subtype (field (mut i32)) $super)) - (type $sub (struct_subtype (field (mut i32)) $super)) - - ;; CHECK: (type $ref|$sub|_=>_none (func_subtype (param (ref $sub)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $ref|$sub|_=>_none) (param $x (ref $sub)) - ;; CHECK-NEXT: (struct.set $sub 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $sub)) - (struct.set $sub 0 - (local.get $x) - (i32.const 2) - ) - ) - - ;; CHECK: (func $field-keepalive (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $super 0 - ;; CHECK-NEXT: (ref.null $super) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $sub 0 - ;; CHECK-NEXT: (ref.null $sub) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $field-keepalive - (drop (struct.get $super 0 (ref.null $super))) - (drop (struct.get $sub 0 (ref.null $sub))) - ) -) diff -Nru binaryen-108/test/lit/passes/gto-removals.wast binaryen-99/test/lit/passes/gto-removals.wast --- binaryen-108/test/lit/passes/gto-removals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/gto-removals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,800 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --gto -all -S -o - | filecheck %s -;; (remove-unused-names is added to test fallthrough values without a block -;; name getting in the way) - -(module - ;; A struct with a field that is never read or written, so it can be - ;; removed. - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype (field (mut funcref)) data)) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - ) -) - -(module - ;; A write does not keep a field from being removed. - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype (field (mut funcref)) data)) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - ;; The fields of this set will be dropped, as we do not need to perform - ;; the write. - (struct.set $struct 0 - (local.get $x) - (ref.null func) - ) - ) -) - -(module - ;; A new does not keep a field from being removed. - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype (field (mut funcref)) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - ;; The fields in this new will be removed. - (drop - (struct.new $struct - (ref.null func) - ) - ) - ) -) - -(module - ;; A new_default does not keep a field from being removed. - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype (field (mut funcref)) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - ;; The fields in this new will be removed. - (drop - (struct.new_default $struct - ) - ) - ) -) - -(module - ;; A read *does* keep a field from being removed. - - ;; CHECK: (type $struct (struct_subtype (field funcref) data)) - (type $struct (struct_subtype (field (mut funcref)) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $func (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $struct)) - (drop - (struct.get $struct 0 - (local.get $x) - ) - ) - ) -) - -(module - ;; Different struct types with different situations: some fields are read, - ;; some written, and some both. (Note that this also tests the interaction - ;; of removing with the immutability inference that --gto does.) - - ;; A struct with all fields marked mutable. - ;; CHECK: (type $mut-struct (struct_subtype (field $r i32) (field $rw (mut i32)) (field $r-2 i32) (field $rw-2 (mut i32)) data)) - (type $mut-struct (struct_subtype (field $r (mut i32)) (field $w (mut i32)) (field $rw (mut i32)) (field $r-2 (mut i32)) (field $w-2 (mut i32)) (field $rw-2 (mut i32)) data)) - - ;; A similar struct but with all fields marked immutable, and the only - ;; writes are from during creation (so all fields are at least writeable). - ;; CHECK: (type $imm-struct (struct_subtype (field $rw i32) (field $rw-2 i32) data)) - (type $imm-struct (struct_subtype (field $w i32) (field $rw i32) (field $w-2 i32) (field $rw-2 i32) data)) - - ;; CHECK: (type $ref|$mut-struct|_=>_none (func_subtype (param (ref $mut-struct)) func)) - - ;; CHECK: (type $ref|$imm-struct|_=>_none (func_subtype (param (ref $imm-struct)) func)) - - ;; CHECK: (func $func-mut (type $ref|$mut-struct|_=>_none) (param $x (ref $mut-struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $mut-struct $r - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $mut-struct $rw - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $mut-struct $rw - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $mut-struct $r-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $mut-struct $rw-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $mut-struct $rw-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func-mut (param $x (ref $mut-struct)) - ;; $r is only read - (drop - (struct.get $mut-struct $r - (local.get $x) - ) - ) - ;; $w is only written - (struct.set $mut-struct $w - (local.get $x) - (i32.const 0) - ) - ;; $rw is both - (struct.set $mut-struct $rw - (local.get $x) - (i32.const 1) - ) - (drop - (struct.get $mut-struct $rw - (local.get $x) - ) - ) - ;; The same, for the $*-2 fields - (drop - (struct.get $mut-struct $r-2 - (local.get $x) - ) - ) - (struct.set $mut-struct $w-2 - (local.get $x) - (i32.const 2) - ) - (struct.set $mut-struct $rw-2 - (local.get $x) - (i32.const 3) - ) - (drop - (struct.get $mut-struct $rw-2 - (local.get $x) - ) - ) - ) - - ;; CHECK: (func $func-imm (type $ref|$imm-struct|_=>_none) (param $x (ref $imm-struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $imm-struct - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $imm-struct $rw - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $imm-struct $rw-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func-imm (param $x (ref $imm-struct)) - ;; create an instance - (drop - (struct.new $imm-struct - (i32.const 0) - (i32.const 1) - (i32.const 2) - (i32.const 3) - ) - ) - ;; $rw and $rw-2 are also read - (drop - (struct.get $imm-struct $rw - (local.get $x) - ) - ) - (drop - (struct.get $imm-struct $rw-2 - (local.get $x) - ) - ) - ) -) - -(module - ;; A vtable-like structure created in a global location. Only some of the - ;; fields are accessed. - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $vtable (struct_subtype (field $v1 funcref) (field $v2 funcref) data)) - (type $vtable (struct_subtype (field $v0 funcref) (field $v1 funcref) (field $v2 funcref) (field $v3 funcref) (field $v4 funcref) data)) - - ;; CHECK: (global $vtable (ref $vtable) (struct.new $vtable - ;; CHECK-NEXT: (ref.func $func-1) - ;; CHECK-NEXT: (ref.func $func-2) - ;; CHECK-NEXT: )) - (global $vtable (ref $vtable) (struct.new $vtable - (ref.func $func-0) - (ref.func $func-1) - (ref.func $func-2) - (ref.func $func-3) - (ref.func $func-4) - )) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $vtable $v1 - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $vtable $v2 - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - ;; To differ from previous tests, do not read the very first field. - (drop - (struct.get $vtable 1 - (global.get $vtable) - ) - ) - ;; To differ from previous tests, do reads in two adjacent fields. - (drop - (struct.get $vtable 2 - (global.get $vtable) - ) - ) - ;; To differ from previous tests, do not read the very last field, and the - ;; one before it. - ) - - ;; CHECK: (func $func-0 (type $none_=>_none) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-0) - ;; CHECK: (func $func-1 (type $none_=>_none) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-1) - ;; CHECK: (func $func-2 (type $none_=>_none) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-2) - ;; CHECK: (func $func-3 (type $none_=>_none) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-3) - ;; CHECK: (func $func-4 (type $none_=>_none) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-4) -) - -(module - ;; Similar to the above, but with different types in each field, to verify - ;; that we emit valid code and are not confused by the names being right - ;; by coincidence. - - - ;; CHECK: (type $vtable (struct_subtype (field $v1 i64) (field $v2 f32) data)) - (type $vtable (struct_subtype (field $v0 i32) (field $v1 i64) (field $v2 f32) (field $v3 f64) (field $v4 anyref) data)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (global $vtable (ref $vtable) (struct.new $vtable - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2.200000047683716) - ;; CHECK-NEXT: )) - (global $vtable (ref $vtable) (struct.new $vtable - (i32.const 0) - (i64.const 1) - (f32.const 2.2) - (f64.const 3.3) - (ref.null data) - )) - - ;; CHECK: (func $test (type $none_=>_none) - ;; CHECK-NEXT: (local $i64 i64) - ;; CHECK-NEXT: (local $f32 f32) - ;; CHECK-NEXT: (local.set $i64 - ;; CHECK-NEXT: (struct.get $vtable $v1 - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $f32 - ;; CHECK-NEXT: (struct.get $vtable $v2 - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (local $i64 i64) - (local $f32 f32) - (local.set $i64 - (struct.get $vtable 1 - (global.get $vtable) - ) - ) - (local.set $f32 - (struct.get $vtable 2 - (global.get $vtable) - ) - ) - ) -) - -(module - ;; A new with side effects - - ;; CHECK: (type $struct (struct_subtype (field i32) (field (rtt $struct)) data)) - (type $struct (struct i32 f64 (ref any) (rtt $struct))) - - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $ref|any|_=>_none (func_subtype (param (ref any)) func)) - - ;; CHECK: (type $i32_=>_i32 (func_subtype (param i32) (result i32) func)) - - ;; CHECK: (type $i32_=>_f64 (func_subtype (param i32) (result f64) func)) - - ;; CHECK: (type $i32_=>_ref|any| (func_subtype (param i32) (result (ref any)) func)) - - ;; CHECK: (global $imm-i32 i32 (i32.const 1234)) - (global $imm-i32 i32 (i32.const 1234)) - - ;; CHECK: (global $mut-i32 (mut i32) (i32.const 5678)) - (global $mut-i32 (mut i32) (i32.const 5678)) - - ;; CHECK: (func $gets (type $ref|any|_=>_none) (param $x (ref any)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 1 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $gets (param $x (ref any)) - ;; Gets to keep certain fields alive. - (drop - (struct.get $struct 0 - (ref.null $struct) - ) - ) - (drop - (struct.get $struct 3 - (ref.null $struct) - ) - ) - ) - - ;; CHECK: (func $new-side-effect (type $none_=>_none) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $struct)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $helper0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $helper1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (call $helper2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $new-side-effect - ;; The 2nd&3rd fields here will be removed, since those fields have no - ;; reads. They has side effects, though, so the operands will be saved in - ;; locals. Note that we can't save the rtt.canon in locals, but it has - ;; no effects, and we leave such arguments as they are. - ;; Note also that one of the fields is non-nullable, and we need to use a - ;; nullable local for it. - (drop - (struct.new $struct - (call $helper0 (i32.const 0)) - (call $helper1 (i32.const 1)) - (call $helper2 (i32.const 2)) - (rtt.canon $struct) - ) - ) - ) - - ;; CHECK: (func $new-side-effect-global-imm (type $none_=>_none) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $struct)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $helper1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $helper2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (global.get $imm-i32) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $new-side-effect-global-imm - ;; As above, the 2nd&3rd fields here will be removed. The first field does - ;; a global.get, which has effects, but those effects do not interact with - ;; anything else (since it is an immutable global), so we do not need a - ;; local for it. - (drop - (struct.new $struct - (global.get $imm-i32) - (call $helper1 (i32.const 0)) - (call $helper2 (i32.const 1)) - (rtt.canon $struct) - ) - ) - ) - - ;; CHECK: (func $new-side-effect-global-mut (type $none_=>_none) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $struct)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $mut-i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (call $helper1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (call $helper2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $new-side-effect-global-mut - ;; As above, but the global is mutable, so we will use a local: the calls - ;; might alter that global, in theory. - (drop - (struct.new $struct - (global.get $mut-i32) - (call $helper1 (i32.const 0)) - (call $helper2 (i32.const 1)) - (rtt.canon $struct) - ) - ) - ) - - ;; CHECK: (func $new-unreachable (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper2 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $new-unreachable - ;; Another case with side effects. We stop at the unreachable param before - ;; it, however. - (drop - (struct.new $struct - (i32.const 2) - (unreachable) - (call $helper2 (i32.const 3)) - (rtt.canon $struct) - ) - ) - ) - - ;; CHECK: (func $new-side-effect-in-kept (type $ref|any|_=>_none) (param $any (ref any)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (call $helper0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $new-side-effect-in-kept (param $any (ref any)) - ;; Side effects appear in fields that we do *not* remove. In that case, - ;; we do not need to use locals. - (drop - (struct.new $struct - (call $helper0 (i32.const 0)) - (f64.const 3.14159) - (local.get $any) - (rtt.canon $struct) - ) - ) - ) - - ;; CHECK: (func $helper0 (type $i32_=>_i32) (param $x i32) (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $helper0 (param $x i32) (result i32) - (unreachable) - ) - - ;; CHECK: (func $helper1 (type $i32_=>_f64) (param $x i32) (result f64) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $helper1 (param $x i32) (result f64) - (unreachable) - ) - - ;; CHECK: (func $helper2 (type $i32_=>_ref|any|) (param $x i32) (result (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $helper2 (param $x i32) (result (ref any)) - (unreachable) - ) -) - -;; We can remove fields from the end if they are only used in subtypes, because -;; the subtypes can always add fields at the end (and only at the end). -(module - ;; CHECK: (type $parent (struct_subtype (field i32) (field i64) data)) - - ;; CHECK: (type $child (struct_subtype (field i32) (field i64) (field f32) (field f64) (field anyref) $parent)) - (type $child (struct_subtype (field i32) (field i64) (field f32) (field f64) (field anyref) $parent)) - - (type $parent (struct_subtype (field i32) (field i64) (field f32) (field f64) data)) - - ;; CHECK: (type $ref|$parent|_ref|$child|_=>_none (func_subtype (param (ref $parent) (ref $child)) func)) - - ;; CHECK: (func $func (type $ref|$parent|_ref|$child|_=>_none) (param $x (ref $parent)) (param $y (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $parent 1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 0 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 2 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 3 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 4 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $parent)) (param $y (ref $child)) - ;; The parent has fields 0, 1, 2, 3 and the child adds 4. - ;; Use fields only 1 in the parent, and all the rest in the child. We can - ;; only remove from the end in the child, which means we can remove 2 and 3 - ;; in the parent, but not 0. - (drop (struct.get $parent 1 (local.get $x))) - (drop (struct.get $child 0 (local.get $y))) - (drop (struct.get $child 2 (local.get $y))) - (drop (struct.get $child 3 (local.get $y))) - (drop (struct.get $child 4 (local.get $y))) - ) -) - -(module - ;; CHECK: (type $parent (struct_subtype (field i32) (field i64) (field (mut f32)) data)) - - ;; CHECK: (type $child (struct_subtype (field i32) (field i64) (field (mut f32)) (field f64) (field anyref) $parent)) - (type $child (struct_subtype (field (mut i32)) (field (mut i64)) (field (mut f32)) (field (mut f64)) (field (mut anyref)) $parent)) - - (type $parent (struct_subtype (field (mut i32)) (field (mut i64)) (field (mut f32)) (field (mut f64)) data)) - - ;; CHECK: (type $ref|$parent|_ref|$child|_=>_none (func_subtype (param (ref $parent) (ref $child)) func)) - - ;; CHECK: (func $func (type $ref|$parent|_ref|$child|_=>_none) (param $x (ref $parent)) (param $y (ref $child)) - ;; CHECK-NEXT: (struct.set $parent 2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $parent 1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 0 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 2 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 3 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child 4 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $x (ref $parent)) (param $y (ref $child)) - ;; As above, but add a write in the parent of field 2. That prevents us from - ;; removing it from the parent. - (struct.set $parent 2 (local.get $x) (f32.const 0)) - - (drop (struct.get $parent 1 (local.get $x))) - (drop (struct.get $child 0 (local.get $y))) - (drop (struct.get $child 2 (local.get $y))) - (drop (struct.get $child 3 (local.get $y))) - (drop (struct.get $child 4 (local.get $y))) - ) -) - -;; A parent with two children, and there are only reads of the parent. Those -;; reads might be of data of either child, of course (as a refernce to the -;; parent might point to them), so we cannot optimize here. -(module - ;; CHECK: (type $parent (struct_subtype (field i32) data)) - (type $parent (struct_subtype (field i32) data)) - ;; CHECK: (type $ref|$parent|_ref|$child1|_ref|$child2|_=>_none (func_subtype (param (ref $parent) (ref $child1) (ref $child2)) func)) - - ;; CHECK: (type $child1 (struct_subtype (field i32) $parent)) - (type $child1 (struct_subtype (field i32) $parent)) - ;; CHECK: (type $child2 (struct_subtype (field i32) $parent)) - (type $child2 (struct_subtype (field i32) $parent)) - - ;; CHECK: (func $func (type $ref|$parent|_ref|$child1|_ref|$child2|_=>_none) (param $parent (ref $parent)) (param $child1 (ref $child1)) (param $child2 (ref $child2)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $parent 0 - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $parent (ref $parent)) (param $child1 (ref $child1)) (param $child2 (ref $child2)) - (drop (struct.get $parent 0 (local.get $parent))) - ) -) - -;; As above, but now the read is just of one child. We can remove the field -;; from the parent and the other child. -(module - ;; CHECK: (type $parent (struct_subtype data)) - - ;; CHECK: (type $child1 (struct_subtype (field i32) $parent)) - (type $child1 (struct_subtype (field i32) $parent)) - - (type $parent (struct_subtype (field i32) data)) - ;; CHECK: (type $ref|$parent|_ref|$child1|_ref|$child2|_=>_none (func_subtype (param (ref $parent) (ref $child1) (ref $child2)) func)) - - ;; CHECK: (type $child2 (struct_subtype $parent)) - (type $child2 (struct_subtype (field i32) $parent)) - - ;; CHECK: (func $func (type $ref|$parent|_ref|$child1|_ref|$child2|_=>_none) (param $parent (ref $parent)) (param $child1 (ref $child1)) (param $child2 (ref $child2)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $child1 0 - ;; CHECK-NEXT: (local.get $child1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (param $parent (ref $parent)) (param $child1 (ref $child1)) (param $child2 (ref $child2)) - (drop (struct.get $child1 0 (local.get $child1))) - ) -) diff -Nru binaryen-108/test/lit/passes/heap2local.wast binaryen-99/test/lit/passes/heap2local.wast --- binaryen-108/test/lit/passes/heap2local.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/heap2local.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,3181 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; (remove-unused-names allows the pass to see that blocks flow values) -;; RUN: wasm-opt %s -all --remove-unused-names --heap2local -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --remove-unused-names --heap2local --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $struct.A (struct (field (mut i32)) (field (mut f64)))) - ;; NOMNL: (type $struct.A (struct_subtype (field (mut i32)) (field (mut f64)) data)) - (type $struct.A (struct (field (mut i32)) (field (mut f64)))) - - ;; CHECK: (type $struct.recursive (struct (field (mut (ref null $struct.recursive))))) - - ;; CHECK: (type $struct.nonnullable (struct (field (ref $struct.A)))) - - ;; CHECK: (type $struct.packed (struct (field (mut i8)))) - ;; NOMNL: (type $struct.recursive (struct_subtype (field (mut (ref null $struct.recursive))) data)) - - ;; NOMNL: (type $struct.nonnullable (struct_subtype (field (ref $struct.A)) data)) - - ;; NOMNL: (type $struct.packed (struct_subtype (field (mut i8)) data)) - (type $struct.packed (struct (field (mut i8)))) - - ;; CHECK: (type $struct.nondefaultable (struct (field (rtt $struct.A)))) - ;; NOMNL: (type $struct.nondefaultable (struct_subtype (field (rtt $struct.A)) data)) - (type $struct.nondefaultable (struct (field (rtt $struct.A)))) - - (type $struct.recursive (struct (field (mut (ref null $struct.recursive))))) - - (type $struct.nonnullable (struct (field (ref $struct.A)))) - - ;; CHECK: (func $simple - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $simple (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $simple - ;; Other passes can remove such a trivial case of an unused allocation, but - ;; we still optimize it. - (drop - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - - ;; CHECK: (func $to-local - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $to-local (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $to-local - (local $ref (ref null $struct.A)) - ;; While set to a local, this allocation has no get/set operations. Other - ;; optimizations can remove it, but so can we, turning the set into a - ;; drop (and adding some unnecessary code to allocate the values, which we - ;; depend on other passes to remove). - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - - ;; CHECK: (func $one-get - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $one-get (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $one-get - ;; An allocation followed by an immediate get of a field. This is a non- - ;; escaping allocation, with a use, so we can optimize it out. The - ;; allocation is dropped (letting later opts remove it), and the - ;; allocation's data is moved to locals: we write the initial value to the - ;; locals, and we read from the locals instead of the struct.get. - (drop - (struct.get $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - ) - - ;; CHECK: (func $one-get-b - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $one-get-b (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $one-get-b - ;; Similar to the above, but using a different field index. - (drop - (struct.get $struct.A 1 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - ) - - ;; CHECK: (func $one-set - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $one-set (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $one-set - ;; A simple optimizable allocation only used in one set. - (struct.set $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - (i32.const 1) - ) - ) - - ;; CHECK: (func $packed - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get_u $struct.packed 0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.packed - ;; CHECK-NEXT: (rtt.canon $struct.packed) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $packed (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get_u $struct.packed 0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.packed - ;; NOMNL-NEXT: (rtt.canon $struct.packed) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $packed - ;; We do not optimize packed structs yet. - (drop - (struct.get $struct.packed 0 - (struct.new_default_with_rtt $struct.packed - (rtt.canon $struct.packed) - ) - ) - ) - ) - - ;; CHECK: (func $with-init-values - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $with-init-values (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (local $2 i32) - ;; NOMNL-NEXT: (local $3 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (f64.const 3.14159) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $with-init-values - ;; When we get values to initialize the struct with, assign them to the - ;; proper locals. - (drop - (struct.get $struct.A 0 - (struct.new_with_rtt $struct.A - (i32.const 2) - (f64.const 3.14159) - (rtt.canon $struct.A) - ) - ) - ) - ) - - ;; CHECK: (func $ignore-unreachable - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ignore-unreachable (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ignore-unreachable - ;; An unreachable allocation is not worth trying to process; DCE should - ;; remove it. - (drop - (struct.get $struct.A 0 - (struct.new_with_rtt $struct.A - (i32.const 2) - (unreachable) - (rtt.canon $struct.A) - ) - ) - ) - ) - - ;; CHECK: (func $nondefaultable - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct.nondefaultable 0 - ;; CHECK-NEXT: (struct.new_with_rtt $struct.nondefaultable - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: (rtt.canon $struct.nondefaultable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $nondefaultable (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get $struct.nondefaultable 0 - ;; NOMNL-NEXT: (struct.new_with_rtt $struct.nondefaultable - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: (rtt.canon $struct.nondefaultable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $nondefaultable - ;; We do not optimize structs with nondefaultable types that we cannot - ;; handle, like rtts. - (drop - (struct.get $struct.nondefaultable 0 - (struct.new_with_rtt $struct.nondefaultable - (rtt.canon $struct.A) - (rtt.canon $struct.nondefaultable) - ) - ) - ) - ) - - ;; CHECK: (func $simple-one-local-set - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $simple-one-local-set (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $simple-one-local-set - (local $ref (ref null $struct.A)) - ;; A simple optimizable allocation only used in one set, and also stored - ;; to a local. The local.set should not prevent our optimization, and the - ;; local.set can be turned into a drop. - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.set $struct.A 0 - (local.get $ref) - (i32.const 1) - ) - ) - - ;; CHECK: (func $simple-one-local-get (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $simple-one-local-get (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $simple-one-local-get (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; A simple optimizable allocation only used in one get, via a local. - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $send-ref (param $0 (ref null $struct.A)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $send-ref (type $ref?|$struct.A|_=>_none) (param $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $send-ref (param (ref null $struct.A)) - ) - - ;; CHECK: (func $safe-to-drop (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $safe-to-drop (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $safe-to-drop (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; An extra drop does not let the allocation escape. - (drop - (local.get $ref) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $escape-via-call (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $send-ref - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $escape-via-call (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $send-ref - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $escape-via-call (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; The allocation escapes into a call. - (call $send-ref - (local.get $ref) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $safe-to-drop-multiflow (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $safe-to-drop-multiflow (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $safe-to-drop-multiflow (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; An extra drop + multiple flows through things do not stop us. - (drop - (block (result (ref null $struct.A)) - (block (result (ref null $struct.A)) - (loop (result (ref null $struct.A)) - (local.get $ref) - ) - ) - ) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $escape-after-multiflow (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $send-ref - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $escape-after-multiflow (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $send-ref - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $escape-after-multiflow (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; An escape after multiple flows. - (call $send-ref - (block (result (ref null $struct.A)) - (block (result (ref null $struct.A)) - (loop (result (ref null $struct.A)) - (local.get $ref) - ) - ) - ) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $non-exclusive-set (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (select (result (ref $struct.A)) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $non-exclusive-set (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (select (result (ref $struct.A)) - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $non-exclusive-set (result f64) - (local $ref (ref null $struct.A)) - ;; A set that receives two different allocations, and so we should not try - ;; to optimize it. - (local.set $ref - (select - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - (i32.const 1) - ) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $local-copies (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $local-copies (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $local-copies (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; Copying our allocation through locals does not bother us. - (local.set $ref - (local.get $ref) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $local-copies-2 - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $ref-2 (ref null $struct.A)) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $local-copies-2 (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $ref-2 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $2 i32) - ;; NOMNL-NEXT: (local $3 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $local-copies-2 - (local $ref (ref null $struct.A)) - (local $ref-2 (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; Copying our allocation through locals does not bother us, even if it's - ;; another local. - (local.set $ref-2 - (local.get $ref) - ) - (drop - (struct.get $struct.A 0 - (local.get $ref) - ) - ) - (drop - (struct.get $struct.A 1 - (local.get $ref-2) - ) - ) - ) - - ;; CHECK: (func $local-copies-conditional (param $x i32) (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $local-copies-conditional (type $i32_=>_f64) (param $x i32) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $2 i32) - ;; NOMNL-NEXT: (local $3 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $local-copies-conditional (param $x i32) (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; Possibly copying our allocation through locals does not bother us. Note - ;; that as a result of this the final local.get has two sets that send it - ;; values, but we know they are both the same allocation. - (if (local.get $x) - (local.set $ref - (local.get $ref) - ) - ) - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $block-value (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (call $send-ref - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $block-value (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (call $send-ref - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $block-value (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; Returning our allocation from a block does not bother us. - (struct.get $struct.A 1 - (block (result (ref null $struct.A)) - ;; This call in the block should not bother us either. - (call $send-ref - (ref.null $struct.A) - ) - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $non-exclusive-get (param $x i32) (result f64) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $non-exclusive-get (type $i32_=>_f64) (param $x i32) (result f64) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $non-exclusive-get (param $x i32) (result f64) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (if (local.get $x) - (local.set $ref - (ref.null $struct.A) - ) - ) - ;; A get that receives two different allocations, and so we should not try - ;; to optimize it. - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - - ;; CHECK: (func $tee (result i32) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tee (type $none_=>_i32) (result i32) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - (func $tee (result i32) - (local $ref (ref null $struct.A)) - (struct.get $struct.A 0 - ;; A tee flows out the value, and we can optimize this allocation. - (local.tee $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - ) - - ;; CHECK: (func $tee-set - ;; CHECK-NEXT: (local $ref (ref null $struct.recursive)) - ;; CHECK-NEXT: (local $1 (ref null $struct.recursive)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.recursive)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $tee-set (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.recursive)) - ;; NOMNL-NEXT: (local $1 (ref null $struct.recursive)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (ref.null $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (ref.null $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $tee-set - (local $ref (ref null $struct.recursive)) - ;; As above, but with a set, and also a recursive type. - (struct.set $struct.recursive 0 - (local.tee $ref - (struct.new_default_with_rtt $struct.recursive - (rtt.canon $struct.recursive) - ) - ) - (ref.null $struct.recursive) - ) - ) - - ;; CHECK: (func $set-value - ;; CHECK-NEXT: (local $ref (ref null $struct.recursive)) - ;; CHECK-NEXT: (struct.set $struct.recursive 0 - ;; CHECK-NEXT: (ref.null $struct.recursive) - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $set-value (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.recursive)) - ;; NOMNL-NEXT: (struct.set $struct.recursive 0 - ;; NOMNL-NEXT: (ref.null $struct.recursive) - ;; NOMNL-NEXT: (local.tee $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $set-value - (local $ref (ref null $struct.recursive)) - (struct.set $struct.recursive 0 - (ref.null $struct.recursive) - ;; As above, but operands reversed: the allocation is now the value, not - ;; the reference, and so it escapes. - (local.tee $ref - (struct.new_default_with_rtt $struct.recursive - (rtt.canon $struct.recursive) - ) - ) - ) - ) - - ;; CHECK: (func $initialize-with-reference - ;; CHECK-NEXT: (local $0 (ref null $struct.recursive)) - ;; CHECK-NEXT: (local $1 (ref null $struct.recursive)) - ;; CHECK-NEXT: (local $2 (ref null $struct.recursive)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.recursive)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.recursive)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.recursive) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $initialize-with-reference (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 (ref null $struct.recursive)) - ;; NOMNL-NEXT: (local $1 (ref null $struct.recursive)) - ;; NOMNL-NEXT: (local $2 (ref null $struct.recursive)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.recursive - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.recursive)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.recursive) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $initialize-with-reference - (local $0 (ref null $struct.recursive)) - (local.set $0 - ;; The outer allocation can be optimized, as it does not escape. - (struct.new_with_rtt $struct.recursive - ;; The inner allocation should not prevent the outer one from being - ;; optimized through some form of confusion. - ;; After the outer one is optimized, the inner one can be optimized in - ;; principle, as it can be seen to no longer escape. However, we depend - ;; on other optimizations to actually remove the outer allocation (like - ;; vacuum), and so it cannot be optimized. If we ran vaccum, and then - ;; additional iterations, this might be handled. - (struct.new_default_with_rtt $struct.recursive - (rtt.canon $struct.recursive) - ) - (rtt.canon $struct.recursive) - ) - ) - (drop - (struct.get $struct.recursive 0 - (local.get $0) - ) - ) - ) - - ;; CHECK: (func $escape-flow-out (result anyref) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (struct.set $struct.A 0 - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $escape-flow-out (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (struct.set $struct.A 0 - ;; NOMNL-NEXT: (local.tee $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - (func $escape-flow-out (result anyref) - (local $ref (ref null $struct.A)) - (struct.set $struct.A 0 - (local.tee $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (i32.const 1) - ) - ;; The allocation escapes out to the caller by flowing out. - (local.get $ref) - ) - - ;; CHECK: (func $escape-return (result anyref) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (struct.set $struct.A 0 - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $escape-return (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (struct.set $struct.A 0 - ;; NOMNL-NEXT: (local.tee $ref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $escape-return (result anyref) - (local $ref (ref null $struct.A)) - (struct.set $struct.A 0 - (local.tee $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (i32.const 1) - ) - ;; The allocation escapes out to the caller by a return. - (return - (local.get $ref) - ) - ) - - ;; CHECK: (func $non-nullable (param $a (ref $struct.A)) - ;; CHECK-NEXT: (local $1 (ref null $struct.A)) - ;; CHECK-NEXT: (local $2 (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.nonnullable)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.nonnullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.nonnullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $non-nullable (type $ref|$struct.A|_=>_none) (param $a (ref $struct.A)) - ;; NOMNL-NEXT: (local $1 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $2 (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.nonnullable)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (local.get $a) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.nonnullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.nonnullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $non-nullable (param $a (ref $struct.A)) - (drop - ;; An optimizable case where the type is non-nullable, which requires - ;; special handling in locals. - (struct.get $struct.nonnullable 0 - (struct.new_with_rtt $struct.nonnullable - (local.get $a) - (rtt.canon $struct.nonnullable) - ) - ) - ) - ) - - ;; CHECK: (func $before-loop-use-multi (param $x i32) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 f64) - ;; CHECK-NEXT: (loop $outer - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.const 2.1828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f64.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $inner - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $inner - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $before-loop-use-multi (type $i32_=>_none) (param $x i32) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $2 i32) - ;; NOMNL-NEXT: (local $3 f64) - ;; NOMNL-NEXT: (local $4 i32) - ;; NOMNL-NEXT: (local $5 f64) - ;; NOMNL-NEXT: (loop $outer - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $4 - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $5 - ;; NOMNL-NEXT: (f64.const 2.1828) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (local.get $4) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (local.get $5) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (f64.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (loop $inner - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (i32.add - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br_if $inner - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br $outer) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $before-loop-use-multi (param $x i32) - (local $ref (ref null $struct.A)) - ;; Allocate in a loop, and use that allocation multiple times in that loop - ;; in various ways inside. - (loop $outer - (local.set $ref - (struct.new_with_rtt $struct.A - (i32.const 2) - (f64.const 2.1828) - (rtt.canon $struct.A) - ) - ) - (drop - (struct.get $struct.A 0 - (local.get $ref) - ) - ) - (if (local.get $x) - (drop - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - (struct.set $struct.A 1 - (local.get $ref) - (f64.const 42) - ) - ) - (loop $inner - (struct.set $struct.A 0 - (local.get $ref) - (i32.add - (struct.get $struct.A 0 - (local.get $ref) - ) - (i32.const 1) - ) - ) - (br_if $inner - (local.get $x) - ) - ) - (if (local.get $x) - (drop - (struct.get $struct.A 0 - (local.get $ref) - ) - ) - (drop - (struct.get $struct.A 1 - (local.get $ref) - ) - ) - ) - (br $outer) - ) - ) - - ;; CHECK: (func $multi-separate - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $multi-separate (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (local $2 i32) - ;; NOMNL-NEXT: (local $3 f64) - ;; NOMNL-NEXT: (local $4 i32) - ;; NOMNL-NEXT: (local $5 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $4 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $5 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $5) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $multi-separate - ;; Multiple independent things we can optimize. - (drop - (struct.get $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - (drop - (struct.get $struct.A 0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - (drop - (struct.get $struct.A 1 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - ) - - ;; CHECK: (func $multi-separate-same-local-index - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $multi-separate-same-local-index (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (local $3 i32) - ;; NOMNL-NEXT: (local $4 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $4 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $multi-separate-same-local-index - (local $ref (ref null $struct.A)) - ;; Multiple independent things we can optimize that use the same local - ;; index, but they do not conflict in their live ranges. - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (drop - (struct.get $struct.A 0 - (local.get $ref) - ) - ) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (drop - (struct.get $struct.A 0 - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $multi-separate-different-local-index-overlapping-lifetimes - ;; CHECK-NEXT: (local $ref1 (ref null $struct.A)) - ;; CHECK-NEXT: (local $ref2 (ref null $struct.A)) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $multi-separate-different-local-index-overlapping-lifetimes (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref1 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $ref2 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $2 i32) - ;; NOMNL-NEXT: (local $3 f64) - ;; NOMNL-NEXT: (local $4 i32) - ;; NOMNL-NEXT: (local $5 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $4 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $5 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $4) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $multi-separate-different-local-index-overlapping-lifetimes - (local $ref1 (ref null $struct.A)) - (local $ref2 (ref null $struct.A)) - ;; Multiple independent things we can optimize that use different local - ;; indexes, but whose lifetimes overlap. We should not be confused by that. - (local.set $ref1 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (local.set $ref2 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (drop - (struct.get $struct.A 0 - (local.get $ref1) - ) - ) - (drop - (struct.get $struct.A 0 - (local.get $ref2) - ) - ) - ) - - ;; CHECK: (func $get-through-block (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get-through-block (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $get-through-block (result f64) - (local $0 (ref null $struct.A)) - (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - (drop - ;; A branch to the block. This ensures its name is not removable. And - ;; it indicates that the block does not have a single value that - ;; flows out, which means we do not have exclusive use of the - ;; allocation on this path, and must give up. - (br_if $block - (ref.null $struct.A) - (i32.const 0) - ) - ) - (local.get $0) - ) - ) - ) - - ;; CHECK: (func $branch-to-block (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $branch-to-block (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $branch-to-block (result f64) - (local $0 (ref null $struct.A)) - (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - (drop - ;; A branch to the block of our allocation. However, there is also - ;; a fallthrough value as well, so we must give up. - (br_if $block - (local.get $0) - (i32.const 0) - ) - ) - (ref.null $struct.A) - ) - ) - ) - - ;; CHECK: (func $branch-to-block-no-fallthrough (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (f64.const 2.1828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $branch-to-block-no-fallthrough (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (f64.const 2.1828) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $branch-to-block-no-fallthrough (result f64) - (local $0 (ref null $struct.A)) - (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - (drop - ;; A branch to the block of our allocation. In this case there is no - ;; other value reaching the block, and so our branch is the sole value - ;; which means there is no mixing, and we can optimize this. - (br_if $block - (local.get $0) - (i32.const 0) - ) - ) - (return (f64.const 2.1828)) - ) - ) - ) - - ;; CHECK: (func $two-branches (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (f64.const 2.1828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $two-branches (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (f64.const 2.1828) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $two-branches (result f64) - (local $0 (ref null $struct.A)) - (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - (drop - ;; A branch to the block of our allocation. - (br_if $block - (local.get $0) - (i32.const 0) - ) - ) - (drop - ;; Another branch, causing mixing that prevents optimizations. - (br_if $block - (ref.null $struct.A) - (i32.const 0) - ) - ) - (return (f64.const 2.1828)) - ) - ) - ) - - ;; CHECK: (func $two-branches-b (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (f64.const 2.1828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $two-branches-b (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (f64.const 2.1828) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $two-branches-b (result f64) - (local $0 (ref null $struct.A)) - (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - (drop - (br_if $block - (local.get $0) - (i32.const 0) - ) - ) - (drop - ;; As in $two-branches, but the value here is our allocation, the same - ;; as in the first branch above us. We do not yet optimize such merges - ;; of our allocation, but we could in the future. - (br_if $block - (local.get $0) - (i32.const 0) - ) - ) - (return (f64.const 2.1828)) - ) - ) - ) - - ;; CHECK: (func $br_if_flow (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct.A - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct.A 1 - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (call $send-ref - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (f64.const 2.1828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $br_if_flow (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct.A - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct.A 1 - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (call $send-ref - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (f64.const 2.1828) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $br_if_flow (result f64) - (local $0 (ref null $struct.A)) - (local.set $0 - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - ;; If it were not for the call here then we would be able to optimize - ;; the allocation in this function. (The branch with the allocation is - ;; ok, but the br_if also flows the value into a call, that escapes it.) - (call $send-ref - (br_if $block - (local.get $0) - (i32.const 0) - ) - ) - (return (f64.const 2.1828)) - ) - ) - ) - - ;; CHECK: (func $ref-as-non-null - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-as-non-null (type $none_=>_none) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-as-non-null - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - (struct.set $struct.A 0 - ;; We can see that the input to this RefAsNonNull is always non-null, as - ;; it is our allocation, and so it does not prevent us from optimizing - ;; here. - (ref.as_non_null - (local.get $ref) - ) - (i32.const 1) - ) - ;; Another RefAsNonNull, to check we do not modify irrelevant ones. - (drop - (ref.as_non_null - (ref.null any) - ) - ) - ) - - ;; CHECK: (func $ref-as-non-null-through-local (result i32) - ;; CHECK-NEXT: (local $ref (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-as-non-null-through-local (type $none_=>_i32) (result i32) - ;; NOMNL-NEXT: (local $ref (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-as-non-null-through-local (result i32) - (local $ref (ref null $struct.A)) - (local.set $ref - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ;; Copy the allocation through a ref.as_non_null. This must not trap: it may - ;; trap if we leave the ref.as_non_null there and also we do not assign - ;; anything to the local (if we skip assignments to the local when we - ;; optimize). To avoid that, we should remove the ref.as_non_null, which is - ;; safe since we know our allocation is passed into it, which is not null, - ;; and will not trap. - (local.set $ref - (ref.as_non_null - (local.get $ref) - ) - ) - (struct.get $struct.A 0 - (local.get $ref) - ) - ) - - ;; CHECK: (func $br_if-allocation (result f64) - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result (ref null $struct.A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.const 13.37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (f64.const 2.1828) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $br_if-allocation (type $none_=>_f64) (result f64) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (local $3 i32) - ;; NOMNL-NEXT: (local $4 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block $block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_if $block - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $3 - ;; NOMNL-NEXT: (i32.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $4 - ;; NOMNL-NEXT: (f64.const 13.37) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (local.get $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (local.get $4) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (return - ;; NOMNL-NEXT: (f64.const 2.1828) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - (func $br_if-allocation (result f64) - (local $0 (ref null $struct.A)) - (struct.get $struct.A 1 - (block $block (result (ref null $struct.A)) - (drop - ;; Our allocation flows into a br_if, which therefore has non-nullable - ;; type, which we must update after optimizing. - (br_if $block - (struct.new_with_rtt $struct.A - (i32.const 42) - (f64.const 13.37) - (rtt.canon $struct.A) - ) - (i32.const 0) - ) - ) - (return (f64.const 2.1828)) - ) - ) - ) - - ;; CHECK: (func $simple-no-rtt - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $simple-no-rtt (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 i32) - ;; NOMNL-NEXT: (local $1 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $simple-no-rtt - (drop - ;; This allocation has no rtt, so we have nothing to drop from it when - ;; we optimize. - (struct.new_default $struct.A) - ) - ) - - ;; CHECK: (func $pass-through-loop - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (loop $loop (result (ref null $struct.A)) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $pass-through-loop (type $none_=>_none) - ;; NOMNL-NEXT: (local $0 (ref null $struct.A)) - ;; NOMNL-NEXT: (local $1 i32) - ;; NOMNL-NEXT: (local $2 f64) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (loop $loop (result (ref null $struct.A)) - ;; NOMNL-NEXT: (br_if $loop - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result (ref null $struct.A)) - ;; NOMNL-NEXT: (local.set $1 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (f64.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $struct.A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $pass-through-loop - (local $0 (ref null $struct.A)) - ;; The allocation pass through a loop, which should change type to be - ;; nullable. - (drop - (loop $loop (result (ref $struct.A)) - ;; Include a branch to the loop, so that the testcase does not become - ;; trivial (remove-unused-names will turn a loop with no name into a - ;; block). - (br_if $loop (i32.const 0)) - ;; The allocation that will be turned into locals. - (struct.new_default_with_rtt $struct.A - (rtt.canon $struct.A) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inline-main.wast binaryen-99/test/lit/passes/inline-main.wast --- binaryen-108/test/lit/passes/inline-main.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inline-main.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,125 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --inline-main -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (export "main" (func $main)) - (export "main" (func $main)) - ;; CHECK: (func $__original_main (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $__original_main (result i32) - (i32.const 0) - ) - ;; CHECK: (func $main (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (block $__inlined_func$__original_main (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (call $__original_main) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (export "main" (func $main)) - (export "main" (func $main)) - ;; CHECK: (func $__original_main (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $__original_main (result i32) - (i32.const 0) - ) - ;; CHECK: (func $main (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (i32.const 0) - ) -) -(module - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (export "main" (func $main)) - (export "main" (func $main)) - ;; CHECK: (func $main (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (i32.const 0) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (export "main" (func $main)) - (export "main" (func $main)) - ;; CHECK: (func $__original_main (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $__original_main (result i32) - (i32.const 0) - ) - ;; CHECK: (func $main (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $__original_main) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $__original_main) - ;; CHECK-NEXT: ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (drop (call $__original_main)) - (call $__original_main) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (func $__original_main (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $__original_main (result i32) - (i32.const 0) - ) -) -(module - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (import "env" "main" (func $main (param i32 i32) (result i32))) - (import "env" "main" (func $main (param i32 i32) (result i32))) - ;; CHECK: (export "main" (func $main)) - (export "main" (func $main)) - ;; CHECK: (func $__original_main (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $__original_main (result i32) - (i32.const 0) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "original_main" (func $__original_main (result i32))) - (import "env" "original_main" (func $__original_main (result i32))) - ;; CHECK: (export "main" (func $main)) - (export "main" (func $main)) - ;; CHECK: (func $main (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (call $__original_main) - ;; CHECK-NEXT: ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (call $__original_main) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining_all-features.wast binaryen-99/test/lit/passes/inlining_all-features.wast --- binaryen-108/test/lit/passes/inlining_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,248 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: foreach %s %t wasm-opt --inlining --all-features -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --inlining --all-features --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_funcref (func (result funcref))) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (export "ref_func_test" (func $ref_func_test)) - ;; NOMNL: (type $none_=>_none (func_subtype func)) - - ;; NOMNL: (type $none_=>_funcref (func_subtype (result funcref) func)) - - ;; NOMNL: (elem declare func $foo) - - ;; NOMNL: (export "ref_func_test" (func $ref_func_test)) - (export "ref_func_test" (func $ref_func_test)) - - ;; $foo should not be removed after being inlined, because there is 'ref.func' - ;; instruction that refers to it - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $foo) - - ;; CHECK: (func $ref_func_test (result funcref) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref_func_test (type $none_=>_funcref) (result funcref) - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (block $__inlined_func$foo - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.func $foo) - ;; NOMNL-NEXT: ) - (func $ref_func_test (result funcref) - (call $foo) - (ref.func $foo) - ) -) - -(module - ;; a function reference in a global's init should be noticed, and prevent us - ;; from removing an inlined function - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (global $global$0 (mut funcref) (ref.func $0)) - ;; NOMNL: (type $none_=>_i32 (func_subtype (result i32) func)) - - ;; NOMNL: (global $global$0 (mut funcref) (ref.func $0)) - (global $global$0 (mut funcref) (ref.func $0)) - - ;; CHECK: (func $0 (result i32) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $0 (type $none_=>_i32) (result i32) - ;; NOMNL-NEXT: (i32.const 1337) - ;; NOMNL-NEXT: ) - (func $0 (result i32) - (i32.const 1337) - ) - - ;; CHECK: (func $1 (result i32) - ;; CHECK-NEXT: (block $__inlined_func$0 (result i32) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $none_=>_i32) (result i32) - ;; NOMNL-NEXT: (block $__inlined_func$0 (result i32) - ;; NOMNL-NEXT: (i32.const 1337) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 (result i32) - (call $0) - ) -) - -(module - ;; a function reference in the start should be noticed, and prevent us - ;; from removing an inlined function - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (start $0) - ;; NOMNL: (type $none_=>_none (func_subtype func)) - - ;; NOMNL: (start $0) - (start $0) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $0 (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $0 - (nop) - ) - - ;; CHECK: (func $1 - ;; CHECK-NEXT: (block $__inlined_func$0 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $none_=>_none) - ;; NOMNL-NEXT: (block $__inlined_func$0 - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 - (call $0) - ) -) - -;; inline a return_call_ref -(module - ;; CHECK: (type $none_=>_none (func)) - ;; NOMNL: (type $none_=>_none (func_subtype func)) - (type $none_=>_none (func)) - - ;; CHECK: (export "func_36_invoker" (func $1)) - ;; NOMNL: (export "func_36_invoker" (func $1)) - (export "func_36_invoker" (func $1)) - - (func $0 - (return_call_ref - (ref.null $none_=>_none) - ) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (block $__inlined_func$0 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $none_=>_none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $none_=>_none) - ;; NOMNL-NEXT: (block $__inlined_func$0 - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (call_ref - ;; NOMNL-NEXT: (ref.null $none_=>_none) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br $__inlined_func$0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br $__inlined_func$0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 - (call $0) - ) -) - -;; handle non-nullable parameter types (which turn into local types after -;; inlining) -(module - (func $0 (param $non-null (ref func)) (result (ref func)) - (local.get $non-null) - ) - ;; CHECK: (type $none_=>_ref|func| (func (result (ref func)))) - - ;; CHECK: (elem declare func $1) - - ;; CHECK: (func $1 (result (ref func)) - ;; CHECK-NEXT: (local $0 funcref) - ;; CHECK-NEXT: (block $__inlined_func$0 (result (ref func)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.func $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (type $none_=>_ref|func| (func_subtype (result (ref func)) func)) - - ;; NOMNL: (elem declare func $1) - - ;; NOMNL: (func $1 (type $none_=>_ref|func|) (result (ref func)) - ;; NOMNL-NEXT: (local $0 funcref) - ;; NOMNL-NEXT: (block $__inlined_func$0 (result (ref func)) - ;; NOMNL-NEXT: (local.set $0 - ;; NOMNL-NEXT: (ref.func $1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 (result (ref func)) - (call $0 - (ref.func $1) - ) - ) -) - -;; never inline an rtt parameter, as those cannot be handled as locals -(module - ;; CHECK: (type $struct (struct )) - ;; NOMNL: (type $struct (struct_subtype data)) - (type $struct (struct)) - ;; CHECK: (type $rtt_$struct_=>_none (func (param (rtt $struct)))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 (param $rtt (rtt $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (type $rtt_$struct_=>_none (func_subtype (param (rtt $struct)) func)) - - ;; NOMNL: (type $none_=>_none (func_subtype func)) - - ;; NOMNL: (func $0 (type $rtt_$struct_=>_none) (param $rtt (rtt $struct)) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $0 (param $rtt (rtt $struct)) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (call $0 - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $none_=>_none) - ;; NOMNL-NEXT: (call $0 - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 - (call $0 - (rtt.canon $struct) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining-eh.wast binaryen-99/test/lit/passes/inlining-eh.wast --- binaryen-108/test/lit/passes/inlining-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --inlining -all -S -o - | filecheck %s - -(module - ;; --------------------------------------------------------------------------- - ;; CHECK: (import "a" "b" (func $foo (result i32))) - (import "a" "b" (func $foo (result i32))) - ;; CHECK: (tag $tag$0 (param i32)) - (tag $tag$0 (param i32)) - (func $callee-with-label - (try $label - (do) - (catch $tag$0 - (drop - (pop i32) - ) - ) - ) - ) - - ;; Properly ensure unique try labels after an inlining - - ;; CHECK: (func $caller-with-label (param $x i32) - ;; CHECK-NEXT: (loop $label - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$callee-with-label - ;; CHECK-NEXT: (try $label0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller-with-label (param $x i32) - (loop $label ;; The same label as the try that will be inlined into here - (call $callee-with-label) - (br_if $label - (call $foo) - ) - ) - ) - - ;; --------------------------------------------------------------------------- - ;; CHECK: (func $callee-with-try-delegate - ;; CHECK-NEXT: (try $label$3 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $callee-with-try-delegate - (try $label$3 - (do) - (delegate 0) - ) - ) - - ;; For now, do not inline a try-delegate - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $callee-with-try-delegate) - ;; CHECK-NEXT: ) - (func $caller - (call $callee-with-try-delegate) - ) - - ;; --------------------------------------------------------------------------- - (func $callee-a (result i32) - (i32.const 42) - ) - - ;; Properly support inlining into a function with a try-delegate - - ;; CHECK: (func $caller-with-try-delegate (result i32) - ;; CHECK-NEXT: (try $label$3 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$callee-a (result i32) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller-with-try-delegate (result i32) - (try $label$3 - (do) - (delegate 0) - ) - (call $callee-a) - ) - - - ;; --------------------------------------------------------------------------- - (func $callee-b (param i32)) - - ;; CHECK: (func $caller-with-pop - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$callee-b - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller-with-pop - (try - (do) - (catch $tag$0 - ;; After this $callee-b is inlined, there will be additional 'block's - ;; surrouding this 'pop', which makes its location invalid. We fix it by - ;; creating a new local to set the result of 'pop' and later use - ;; local.get to get the value within the inlined function body. - (call $callee-b - (pop i32) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining_enable-tail-call.wast binaryen-99/test/lit/passes/inlining_enable-tail-call.wast --- binaryen-108/test/lit/passes/inlining_enable-tail-call.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining_enable-tail-call.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,769 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --inlining --enable-tail-call -S -o - | filecheck %s - -(module - (table 1 1 funcref) - (elem (i32.const 0) $tabled) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (table $0 1 1 funcref) - - ;; CHECK: (elem (i32.const 0) $tabled) - - ;; CHECK: (export "user" (func $user)) - - ;; CHECK: (export "exported" (func $exported)) - - ;; CHECK: (func $user - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y f64) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 f32) - ;; CHECK-NEXT: (local $5 i64) - ;; CHECK-NEXT: (local $6 f32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$exported - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$tabled - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$multi - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$multi0 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$ok - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$int (result i32) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (block $__inlined_func$double (result f64) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$int2 (result i32) - ;; CHECK-NEXT: (i32.const 112) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (block $__inlined_func$double2 (result f64) - ;; CHECK-NEXT: (f64.const 113.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$with-local - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f32.const 2.1418280601501465) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$with-local2 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$return (result i32) - ;; CHECK-NEXT: (br $__inlined_func$return - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$multipass - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$multipass2 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$param - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f32.const 12.34000015258789) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i64.const 890005350012) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $user (export "user") - (local $x i32) - (local $y f64) - (call $exported) - (call $tabled) - (call $multi) - (call $multi) - (call $ok) - (drop (call $int)) - (drop (call $double)) - (local.set $x (call $int2)) - (local.set $y (call $double2)) - (call $with-local) - (call $with-local2) - (drop (call $return)) - (call $multipass) - (call $param (f32.const 12.34) (i64.const 890005350012)) - ) - ;; CHECK: (func $exported - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $exported (export "exported") - (nop) - ) - ;; CHECK: (func $recursive - ;; CHECK-NEXT: (call $recursive) - ;; CHECK-NEXT: ) - (func $recursive - (call $recursive) - ) - ;; CHECK: (func $tabled - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $tabled - (nop) - ) - ;; CHECK: (func $cycle1 - ;; CHECK-NEXT: (block $__inlined_func$cycle2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $cycle1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $cycle1 - (call $cycle2) - ) - (func $cycle2 - (call $cycle1) - ) - (func $multi - (nop) - ) - (func $ok - (drop (i32.const 1)) - ) - (func $int (result i32) - (i32.const 2) - ) - (func $double (result f64) - (f64.const 3.14159) - ) - (func $int2 (result i32) - (i32.const 112) - ) - (func $double2 (result f64) - (f64.const 113.14159) - ) - (func $with-local - (local $x f32) - (local.set $x (f32.const 2.141828)) - ) - (func $with-local2 - (local $y i64) - (local.set $y (i64.const 4)) - ) - (func $return (result i32) - (return (i32.const 5)) - ) - (func $multipass - (call $multipass2) - ) - (func $multipass2 - (drop (i32.const 6)) - ) - (func $param (param $x f32) (param $y i64) - (local $z f32) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - ) -) -(module - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (func $child (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - (func $child (param i32) (result i32) - (i32.const 1234) - ) - ;; CHECK: (func $parent (result i32) - ;; CHECK-NEXT: (call $child - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $parent (result i32) - (call $child - (unreachable) ;; call is not performed, no sense to inline - ) - ) -) -(module - ;; CHECK: (type $f32_i32_=>_i32 (func (param f32 i32) (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $hangLimit (mut i32) (i32.const 25)) - (global $hangLimit (mut i32) (i32.const 25)) - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - ;; CHECK: (export "hangLimitInitializer" (func $hangLimitInitializer)) - (export "hangLimitInitializer" (func $hangLimitInitializer)) - (func $func_3 (result i32) - (local $0 i32) - (select - (local.get $0) ;; we depend on the zero-init value here, so it must be set when inlining! - (local.tee $0 - (i32.const -1) - ) - (i32.const 1) - ) - ) - ;; CHECK: (func $func_4 (param $0 f32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (local $4 f32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 f64) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (loop $label$0 (result i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $hangLimit) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 54) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $hangLimit - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (global.get $hangLimit) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$func_3 (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func_4 (param $0 f32) (param $1 i32) (result i32) - (local $2 i64) - (local $3 f64) - (local $4 f32) - (local $5 i32) - (local $6 i32) - (local $7 f64) - (loop $label$0 (result i32) - (block - (if - (i32.eqz - (global.get $hangLimit) - ) - (return - (i32.const 54) - ) - ) - (global.set $hangLimit - (i32.sub - (global.get $hangLimit) - (i32.const 1) - ) - ) - ) - (i32.eqz - (if (result i32) - (i32.const 1) - (if (result i32) - (i32.eqz - (call $func_3) - ) - (br $label$0) - (i32.const 0) - ) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $hangLimitInitializer - ;; CHECK-NEXT: (global.set $hangLimit - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $hangLimitInitializer - (global.set $hangLimit - (i32.const 25) - ) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $T (func (param i32))) - (type $T (func (param i32))) - (table 10 funcref) - ;; CHECK: (table $0 10 funcref) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (block $__inlined_func$1 - ;; CHECK-NEXT: (call_indirect (type $T) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (call $1) - ) - (func $1 - (call_indirect (type $T) - (if (result i32) ;; if copy must preserve the forced type - (i32.const 0) - (unreachable) - (unreachable) - ) - (i32.const 1) - ) - ) -) -(module - (func $0 - (block $label$1 ;; copy this name - (br_table $label$1 $label$1 - (i32.const 0) - ) - ) - ) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $1 - ;; CHECK-NEXT: (block $__inlined_func$0 - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (br_table $label$1 $label$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $1 - (call $0) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (func $0 (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (block $__inlined_func$1 (result i32) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (result i32) - (return_call $1) - ) - (func $1 (result i32) - (i32.const 42) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$1 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (return_call $1 - (i32.const 42) - ) - ) - (func $1 (param i32) - (drop - (local.get 0) - ) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (func $0 (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (block $__inlined_func$1 (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (result i32) - (return_call $1 - (i32.const 42) - ) - ) - (func $1 (param i32) (result i32) - (local.get 0) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$1 (result i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br $__inlined_func$1 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$2 (result i32) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (drop - (call $1) - ) - ) - (func $1 (result i32) - (return_call $2) - ) - (func $2 (result i32) - (i32.const 42) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block $__inlined_func$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$2 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (call $1) - ) - (func $1 - (return_call $2 - (i32.const 42) - ) - ) - (func $2 (param i32) - (drop - (local.get 0) - ) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $T (func (param i32) (result i32))) - (type $T (func (param i32) (result i32))) - (table 10 funcref) - ;; CHECK: (table $0 10 funcref) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$1 (result i32) - ;; CHECK-NEXT: (br $__inlined_func$1 - ;; CHECK-NEXT: (call_indirect (type $T) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (drop - (call $1) - ) - ) - (func $1 (result i32) - (return_call_indirect (type $T) - (i32.const 42) - (i32.const 0) - ) - ) -) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $T (func (param i32))) - (type $T (func (param i32))) - (table 10 funcref) - ;; CHECK: (table $0 10 funcref) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (block $__inlined_func$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call_indirect (type $T) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (call $1) - ) - (func $1 - (return_call_indirect (type $T) - (i32.const 42) - (i32.const 0) - ) - ) -) -(module - ;; CHECK: (type $6 (func)) - (type $6 (func)) - ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (global $global$0 (mut i32) (i32.const 10)) - ;; CHECK: (export "func_102_invoker" (func $19)) - (export "func_102_invoker" (func $19)) - (func $2 (; 2 ;) (type $6) - (if - (global.get $global$0) - (return) - ) - (global.set $global$0 - (i32.const 1) - ) - ) - (func $13 (; 13 ;) (type $6) - (if - (global.get $global$0) - (unreachable) - ) - (return_call $2) - ) - ;; CHECK: (func $19 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$13 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$2 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (br $__inlined_func$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global$0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $19 (; 19 ;) (type $6) - (call $13) - (unreachable) - ) -) - -(module - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (export "is_even" (func $is_even)) - (export "is_even" (func $is_even)) - ;; CHECK: (func $is_even (param $i i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (block $__inlined_func$is_odd (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (return_call $is_even - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $is_even (param $i i32) (result i32) - (if (result i32) - (i32.eqz (local.get $i)) - (i32.const 1) - (return_call $is_odd - (i32.sub - (local.get $i) - (i32.const 1) - ) - ) - ) - ) - (func $is_odd (param $i i32) (result i32) - (if (result i32) - (i32.eqz (local.get $i)) - (i32.const 0) - (return_call $is_even - (i32.sub - (local.get $i) - (i32.const 1) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining-gc.wast binaryen-99/test/lit/passes/inlining-gc.wast --- binaryen-108/test/lit/passes/inlining-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --inlining --enable-gc-nn-locals -all -S -o - | filecheck %s - -(module - ;; CHECK: (func $caller-nullable - ;; CHECK-NEXT: (local $0 funcref) - ;; CHECK-NEXT: (block $__inlined_func$target-nullable - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller-nullable - ;; Call a function with a nullable local. After the inlining there will - ;; be a new local in this function for the use of the inlined code, and also - ;; we assign the null value to that local in the inlined block (which does - ;; not matter much here, but in general if we had a loop that the inlined - ;; block was inside of, that would be important to get the right behavior). - (call $target-nullable) - ) - - (func $target-nullable - (local $1 (ref null func)) - ) - - ;; CHECK: (func $caller-non-nullable - ;; CHECK-NEXT: (local $0 (ref func)) - ;; CHECK-NEXT: (block $__inlined_func$target-non-nullable - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller-non-nullable - ;; Call a function with a non-nullable local. After the inlining there will - ;; be a new local in this function for the use of the inlined code. We do not - ;; need to zero it out (such locals cannot be used before being set anyhow, so - ;; no zero is needed; and we cannot set a zero anyhow as none exists for the - ;; type). - (call $target-non-nullable) - ) - - (func $target-non-nullable - (local $1 (ref func)) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining_memory64.wat binaryen-99/test/lit/passes/inlining_memory64.wat --- binaryen-108/test/lit/passes/inlining_memory64.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining_memory64.wat 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: foreach %s %t wasm-opt --inlining --enable-memory64 -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_i64 (func (result i64))) - - ;; CHECK: (memory $0 i64 256 256) - (memory $0 i64 256 256) - - ;; CHECK: (func $call-size (result i64) - ;; CHECK-NEXT: (block $__inlined_func$size (result i64) - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-size (result i64) - (call $size) - ) - - (func $size (result i64) - ;; Upon inlining this code is copied, and as the memory is 64-bit the copied - ;; instruction must remain 64-bit (and not have the default 32-bit size). If - ;; we get that wrong then validation would fail here. - (memory.size) - ) - - ;; CHECK: (func $call-grow (result i64) - ;; CHECK-NEXT: (block $__inlined_func$grow (result i64) - ;; CHECK-NEXT: (memory.grow - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-grow (result i64) - ;; As above, but for grow instead of size. - (call $grow) - ) - - (func $grow (result i64) - (memory.grow - (i64.const 1) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining_optimize-level=3.wast binaryen-99/test/lit/passes/inlining_optimize-level=3.wast --- binaryen-108/test/lit/passes/inlining_optimize-level=3.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining_optimize-level=3.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,453 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --inlining --optimize-level=3 -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (table $0 1 1 funcref) - - ;; CHECK: (elem (i32.const 0) $no-loops-but-one-use-but-tabled) - - ;; CHECK: (export "yes" (func $yes)) - (export "yes" (func $yes)) - ;; CHECK: (export "no-loops-but-one-use-but-exported" (func $no-loops-but-one-use-but-exported)) - (export "no-loops-but-one-use-but-exported" (func $no-loops-but-one-use-but-exported)) - (table 1 1 funcref) - (elem (i32.const 0) $no-loops-but-one-use-but-tabled) - - ;; CHECK: (export "A" (func $recursive-inlining-1)) - - ;; CHECK: (export "B" (func $recursive-inlining-2)) - - ;; CHECK: (export "BA" (func $b-recursive-inlining-1)) - - ;; CHECK: (export "BB" (func $b-recursive-inlining-2)) - - ;; CHECK: (func $yes (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $yes (result i32) ;; inlinable: small, lightweight, even with multi uses and a global use, ok when opt-level=3 - (i32.const 1) - ) - (func $yes-big-but-single-use (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.const 1) - ) - (func $no-calls (result i32) - (call $yes) - ) - (func $yes-calls-but-one-use (result i32) - (call $yes) - ) - (func $no-loops (result i32) - (loop (result i32) - (i32.const 1) - ) - ) - (func $yes-loops-but-one-use (result i32) - (loop (result i32) - (i32.const 1) - ) - ) - ;; CHECK: (func $no-loops-but-one-use-but-exported (result i32) - ;; CHECK-NEXT: (loop $loop-in (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-loops-but-one-use-but-exported (result i32) - (loop (result i32) - (i32.const 1) - ) - ) - ;; CHECK: (func $no-loops-but-one-use-but-tabled (result i32) - ;; CHECK-NEXT: (loop $loop-in (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-loops-but-one-use-but-tabled (result i32) - (loop (result i32) - (i32.const 1) - ) - ) - ;; CHECK: (func $intoHere - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes-big-but-single-use (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$no-calls (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes0 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$no-calls1 (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes2 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes-calls-but-one-use (result i32) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes3 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$no-loops (result i32) - ;; CHECK-NEXT: (loop $loop-in (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$no-loops0 (result i32) - ;; CHECK-NEXT: (loop $loop-in1 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$yes-loops-but-one-use (result i32) - ;; CHECK-NEXT: (loop $loop-in2 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$no-loops-but-one-use-but-exported (result i32) - ;; CHECK-NEXT: (loop $loop-in3 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$no-loops-but-one-use-but-tabled (result i32) - ;; CHECK-NEXT: (loop $loop-in4 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $intoHere - (drop (call $yes)) - (drop (call $yes-big-but-single-use)) - (drop (call $no-calls)) - (drop (call $no-calls)) - (drop (call $yes-calls-but-one-use)) - (drop (call $no-loops)) - (drop (call $no-loops)) - (drop (call $yes-loops-but-one-use)) - (drop (call $no-loops-but-one-use-but-exported)) - (drop (call $no-loops-but-one-use-but-tabled)) - ) - - ;; Two functions that call each other. (Exported, so that they are not removed - ;; after inlining.) We should only perform a limited amount of inlining here - - ;; a little might help, but like loop unrolling it loses its benefit quickly. - ;; Specifically here we will see the infinite recursion after one inlining, - ;; and stop (since we do not inline a method into itself). - - ;; CHECK: (func $recursive-inlining-1 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $__inlined_func$recursive-inlining-2 (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (call $recursive-inlining-1 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $recursive-inlining-1 (export "A") (param $x i32) (result i32) - (call $recursive-inlining-2 - (local.get $x) - ) - ) - - ;; CHECK: (func $recursive-inlining-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (call $recursive-inlining-1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $recursive-inlining-2 (export "B") (param $x i32) (result i32) - (call $recursive-inlining-1 - (local.get $x) - ) - ) - - ;; As above, but both call the second. The first will inline the second - ;; several times before hitting the limit (of around 5). - - ;; CHECK: (func $b-recursive-inlining-1 (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block $__inlined_func$b-recursive-inlining-2 (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$b-recursive-inlining-20 (result i32) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$b-recursive-inlining-21 (result i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$b-recursive-inlining-22 (result i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (block $__inlined_func$b-recursive-inlining-23 (result i32) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $b-recursive-inlining-2 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b-recursive-inlining-1 (export "BA") (param $x i32) (result i32) - (call $b-recursive-inlining-2 - (local.get $x) - ) - ) - - ;; CHECK: (func $b-recursive-inlining-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (call $b-recursive-inlining-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b-recursive-inlining-2 (export "BB") (param $x i32) (result i32) - (call $b-recursive-inlining-2 - (local.get $x) - ) - ) - - ;; Verify that we can do a large number (larger than the limit of ~5 we just - ;; saw for recursion) of calls into a single function, if we can do it all in - ;; a single iteration (which is the usual case, and the case here). - - ;; CHECK: (func $call-many-getters - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter2 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter3 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter4 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter5 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter6 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter7 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$getter8 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-many-getters - (call $getter) - (call $getter) - (call $getter) - (call $getter) - (call $getter) - (call $getter) - (call $getter) - (call $getter) - (call $getter) - (call $getter) - ) - - (func $getter - (drop (i32.const 1)) - ) -) - -(module - (func $bar - (drop - (block $__inlined_func$bar (result i32) - (return) ;; After inlining, this return will be replaced with a br to a - ;; new block. That block's name must not collide with the name - ;; of the outer block here, which has been chosen so as to - ;; potentially collide. If it collides, we will fail to validate - ;; as the new outer block will have type none. - ) - ) - ) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (block $__inlined_func$bar_0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $__inlined_func$bar (result i32) - ;; CHECK-NEXT: (br $__inlined_func$bar_0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (call $bar) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining-optimizing_enable-threads.wast binaryen-99/test/lit/passes/inlining-optimizing_enable-threads.wast --- binaryen-108/test/lit/passes/inlining-optimizing_enable-threads.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining-optimizing_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,279 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --inlining-optimizing --enable-threads -S -o - | filecheck %s - -(module - (table 1 1 funcref) - (elem (i32.const 0) $tabled) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (table $0 1 1 funcref) - - ;; CHECK: (elem (i32.const 0) $tabled) - - ;; CHECK: (export "user" (func $user)) - - ;; CHECK: (export "exported" (func $exported)) - - ;; CHECK: (export "exported_small" (func $exported_small)) - - ;; CHECK: (func $user - ;; CHECK-NEXT: (call $exported) - ;; CHECK-NEXT: (call $tabled) - ;; CHECK-NEXT: (call $multi) - ;; CHECK-NEXT: (call $multi) - ;; CHECK-NEXT: ) - (func $user (export "user") - (local $x i32) - (local $y f64) - (call $exported) - (call $exported_small) - (call $tabled) - (call $tabled_small) - (call $multi) - (call $multi) - (call $multi_small) - (call $multi_small) - (call $ok) - (drop (call $int)) - (drop (call $double)) - (local.set $x (call $int2)) - (local.set $y (call $double2)) - (call $with-local) - (call $with-local2) - (drop (call $return)) - (call $multipass) - (call $param (f32.const 12.34) (i64.const 890005350012)) - ) - ;; CHECK: (func $exported - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $exported (export "exported") - (nop) - (nop) - ) - ;; CHECK: (func $exported_small - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $exported_small (export "exported_small") - (nop) - ) - ;; CHECK: (func $recursive - ;; CHECK-NEXT: (call $recursive) - ;; CHECK-NEXT: ) - (func $recursive - (call $recursive) - ) - ;; CHECK: (func $tabled - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $tabled - (nop) - (nop) - ) - (func $tabled_small - (nop) - ) - ;; CHECK: (func $cycle1 - ;; CHECK-NEXT: (call $cycle1) - ;; CHECK-NEXT: ) - (func $cycle1 - (call $cycle2) - ) - (func $cycle2 - (call $cycle1) - ) - ;; CHECK: (func $multi - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $multi - (nop) - (nop) - ) - (func $multi_small - (nop) - ) - (func $ok - (drop (i32.const 1)) - ) - (func $int (result i32) - (i32.const 2) - ) - (func $double (result f64) - (f64.const 3.14159) - ) - (func $int2 (result i32) - (i32.const 112) - ) - (func $double2 (result f64) - (f64.const 113.14159) - ) - (func $with-local - (local $x f32) - (local.set $x (f32.const 2.141828)) - ) - (func $with-local2 - (local $y i64) - (local.set $y (i64.const 4)) - ) - (func $return (result i32) - (return (i32.const 5)) - ) - (func $multipass - (call $multipass2) - ) - (func $multipass2 - (drop (i32.const 6)) - ) - (func $param (param $x f32) (param $y i64) - (local $z f32) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - ) -) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (func $main (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $main (result i32) - (call $func_51) - (i32.const 0) - ) - (func $func_51 - (unreachable) ;; void function but having unreachable body, when inlined, type must be fixed - ) -) -(module - ;; CHECK: (type $none_=>_i64 (func (result i64))) - - ;; CHECK: (memory $0 (shared 1 1)) - (memory $0 (shared 1 1)) - (func $0 (result i32) - (i32.atomic.store16 - (i32.const 0) - (i32.const 0) - ) - (i32.const 1) - ) - ;; CHECK: (func $1 (result i64) - ;; CHECK-NEXT: (i32.atomic.store16 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - (func $1 (result i64) - (drop - (call $0) - ) - (i64.const 0) - ) -) -;; potential infinite recursion -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $main - ;; CHECK-NEXT: (call $one) - ;; CHECK-NEXT: (call $one) - ;; CHECK-NEXT: ) - (func $main - (call $one) - (call $one) - ) - ;; CHECK: (func $one - ;; CHECK-NEXT: (call $one) - ;; CHECK-NEXT: ) - (func $one - (call $one) - ) -) -;; potential infinite cycling recursion -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $main - ;; CHECK-NEXT: (call $two) - ;; CHECK-NEXT: (call $two) - ;; CHECK-NEXT: ) - (func $main - (call $one) - (call $one) - ) - (func $one - (call $two) - ) - ;; CHECK: (func $two - ;; CHECK-NEXT: (call $two) - ;; CHECK-NEXT: ) - (func $two - (call $one) - ) -) -;; make sure to dce, as we may be combining unreachable code with others -(module - ;; CHECK: (type $0 (func)) - (type $0 (func)) - (type $1 (func (param i32 i32) (result i32))) - (table 89 89 funcref) - ;; CHECK: (memory $0 17) - (memory $0 17) - ;; CHECK: (table $0 89 89 funcref) - - ;; CHECK: (start $1) - (start $1) - (func $0 (; 0 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) - (i32.store - (i32.const 4) - (local.tee $0 - (i32.const 0) - ) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 56) - ) - (i32.const 0) - ) - (i64.store - (i32.const 49) - (i64.load - (i32.const 24) - ) - ) - (unreachable) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 56) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.const 49) - ;; CHECK-NEXT: (i64.load - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $1 (; 1 ;) (type $0) - (drop - (call $0 - (i32.const 0) - (i32.const 0) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining-optimizing_optimize-level=3.wast binaryen-99/test/lit/passes/inlining-optimizing_optimize-level=3.wast --- binaryen-108/test/lit/passes/inlining-optimizing_optimize-level=3.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining-optimizing_optimize-level=3.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,31024 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --inlining-optimizing --optimize-level=3 -S -o - | filecheck %s - -;; similar to test/emcc_hello_world.fromasm.clamp ;; -(module - ;; CHECK: (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - ;; CHECK: (type $FUNCSIG$vi (func (param i32))) - - ;; CHECK: (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$ii (func (param i32) (result i32))) - (type $FUNCSIG$vi (func (param i32))) - ;; CHECK: (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - - ;; CHECK: (type $FUNCSIG$i (func (result i32))) - - ;; CHECK: (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (type $FUNCSIG$vii (func (param i32 i32))) - - ;; CHECK: (type $FUNCSIG$v (func)) - (type $FUNCSIG$v (func)) - (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - (type $FUNCSIG$vii (func (param i32 i32))) - ;; CHECK: (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) - - ;; CHECK: (type $f64_i32_=>_f64 (func (param f64 i32) (result f64))) - - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - - ;; CHECK: (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) - - ;; CHECK: (import "env" "memory" (memory $0 256 256)) - (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) - ;; CHECK: (data (i32.const 1024) "emcc_hello_world.asm.js") - - ;; CHECK: (import "env" "table" (table $timport$0 18 18 funcref)) - (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) - ;; CHECK: (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) - (import "env" "tempDoublePtr" (global $tempDoublePtr$asm2wasm$import i32)) - ;; CHECK: (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) - (import "env" "abort" (func $abort)) - ;; CHECK: (import "env" "tempDoublePtr" (global $tempDoublePtr$asm2wasm$import i32)) - (import "env" "nullFunc_ii" (func $nullFunc_ii (param i32))) - ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) - (import "env" "nullFunc_iiii" (func $nullFunc_iiii (param i32))) - ;; CHECK: (import "env" "tableBase" (global $tableBase i32)) - (import "env" "nullFunc_vi" (func $nullFunc_vi (param i32))) - ;; CHECK: (import "env" "abort" (func $abort)) - (import "env" "_pthread_cleanup_pop" (func $_pthread_cleanup_pop (param i32))) - ;; CHECK: (import "env" "nullFunc_ii" (func $nullFunc_ii (param i32))) - (import "env" "___lock" (func $___lock (param i32))) - ;; CHECK: (import "env" "nullFunc_iiii" (func $nullFunc_iiii (param i32))) - (import "env" "_pthread_self" (func $_pthread_self (result i32))) - ;; CHECK: (import "env" "nullFunc_vi" (func $nullFunc_vi (param i32))) - (import "env" "_abort" (func $_abort)) - ;; CHECK: (import "env" "_pthread_cleanup_pop" (func $_pthread_cleanup_pop (param i32))) - (import "env" "___syscall6" (func $___syscall6 (param i32 i32) (result i32))) - ;; CHECK: (import "env" "___lock" (func $___lock (param i32))) - (import "env" "_sbrk" (func $_sbrk (param i32) (result i32))) - ;; CHECK: (import "env" "_pthread_self" (func $_pthread_self (result i32))) - (import "env" "_time" (func $_time (param i32) (result i32))) - ;; CHECK: (import "env" "_abort" (func $_abort)) - (import "env" "_emscripten_memcpy_big" (func $_emscripten_memcpy_big (param i32 i32 i32) (result i32))) - ;; CHECK: (import "env" "___syscall6" (func $___syscall6 (param i32 i32) (result i32))) - (import "env" "___syscall54" (func $___syscall54 (param i32 i32) (result i32))) - ;; CHECK: (import "env" "_sbrk" (func $_sbrk (param i32) (result i32))) - (import "env" "___unlock" (func $___unlock (param i32))) - ;; CHECK: (import "env" "_time" (func $_time (param i32) (result i32))) - (import "env" "___syscall140" (func $___syscall140 (param i32 i32) (result i32))) - ;; CHECK: (import "env" "_emscripten_memcpy_big" (func $_emscripten_memcpy_big (param i32 i32 i32) (result i32))) - (import "env" "_pthread_cleanup_push" (func $_pthread_cleanup_push (param i32 i32))) - ;; CHECK: (import "env" "___syscall54" (func $___syscall54 (param i32 i32) (result i32))) - (import "env" "_sysconf" (func $_sysconf (param i32) (result i32))) - ;; CHECK: (import "env" "___unlock" (func $___unlock (param i32))) - (import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32))) - ;; CHECK: (import "env" "___syscall140" (func $___syscall140 (param i32 i32) (result i32))) - (import "env" "memory" (memory $0 256 256)) - ;; CHECK: (import "env" "_pthread_cleanup_push" (func $_pthread_cleanup_push (param i32 i32))) - (import "env" "table" (table 18 18 funcref)) - ;; CHECK: (import "env" "_sysconf" (func $_sysconf (param i32) (result i32))) - (import "env" "memoryBase" (global $memoryBase i32)) - ;; CHECK: (import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32))) - (import "env" "tableBase" (global $tableBase i32)) - ;; CHECK: (global $STACKTOP (mut i32) (global.get $STACKTOP$asm2wasm$import)) - (global $STACKTOP (mut i32) (global.get $STACKTOP$asm2wasm$import)) - ;; CHECK: (global $STACK_MAX (mut i32) (global.get $STACK_MAX$asm2wasm$import)) - (global $STACK_MAX (mut i32) (global.get $STACK_MAX$asm2wasm$import)) - ;; CHECK: (global $tempDoublePtr (mut i32) (global.get $tempDoublePtr$asm2wasm$import)) - (global $tempDoublePtr (mut i32) (global.get $tempDoublePtr$asm2wasm$import)) - ;; CHECK: (global $__THREW__ (mut i32) (i32.const 0)) - (global $__THREW__ (mut i32) (i32.const 0)) - ;; CHECK: (global $threwValue (mut i32) (i32.const 0)) - (global $threwValue (mut i32) (i32.const 0)) - ;; CHECK: (global $tempRet0 (mut i32) (i32.const 0)) - (global $tempRet0 (mut i32) (i32.const 0)) - (elem (global.get $tableBase) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) - (data (i32.const 1024) "emcc_hello_world.asm.js") - ;; CHECK: (elem (global.get $tableBase) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) - - ;; CHECK: (export "_i64Subtract" (func $_i64Subtract)) - (export "_i64Subtract" (func $_i64Subtract)) - ;; CHECK: (export "_free" (func $_free)) - (export "_free" (func $_free)) - ;; CHECK: (export "_main" (func $_main)) - (export "_main" (func $_main)) - ;; CHECK: (export "_i64Add" (func $_i64Add)) - (export "_i64Add" (func $_i64Add)) - ;; CHECK: (export "_memset" (func $_memset)) - (export "_memset" (func $_memset)) - ;; CHECK: (export "_malloc" (func $_malloc)) - (export "_malloc" (func $_malloc)) - ;; CHECK: (export "_memcpy" (func $_memcpy)) - (export "_memcpy" (func $_memcpy)) - ;; CHECK: (export "_bitshift64Lshr" (func $_bitshift64Lshr)) - (export "_bitshift64Lshr" (func $_bitshift64Lshr)) - ;; CHECK: (export "_fflush" (func $_fflush)) - (export "_fflush" (func $_fflush)) - ;; CHECK: (export "___errno_location" (func $___errno_location)) - (export "___errno_location" (func $___errno_location)) - ;; CHECK: (export "_bitshift64Shl" (func $_bitshift64Shl)) - (export "_bitshift64Shl" (func $_bitshift64Shl)) - ;; CHECK: (export "runPostSets" (func $runPostSets)) - (export "runPostSets" (func $runPostSets)) - ;; CHECK: (export "stackAlloc" (func $stackAlloc)) - (export "stackAlloc" (func $stackAlloc)) - ;; CHECK: (export "stackSave" (func $stackSave)) - (export "stackSave" (func $stackSave)) - ;; CHECK: (export "stackRestore" (func $stackRestore)) - (export "stackRestore" (func $stackRestore)) - ;; CHECK: (export "establishStackSpace" (func $establishStackSpace)) - (export "establishStackSpace" (func $establishStackSpace)) - ;; CHECK: (export "setThrew" (func $setThrew)) - (export "setThrew" (func $setThrew)) - ;; CHECK: (export "setTempRet0" (func $setTempRet0)) - (export "setTempRet0" (func $setTempRet0)) - ;; CHECK: (export "getTempRet0" (func $getTempRet0)) - (export "getTempRet0" (func $getTempRet0)) - ;; CHECK: (export "dynCall_ii" (func $dynCall_ii)) - (export "dynCall_ii" (func $dynCall_ii)) - ;; CHECK: (export "dynCall_iiii" (func $dynCall_iiii)) - (export "dynCall_iiii" (func $dynCall_iiii)) - ;; CHECK: (export "dynCall_vi" (func $dynCall_vi)) - (export "dynCall_vi" (func $dynCall_vi)) - ;; CHECK: (export "___udivmoddi4" (func $___udivmoddi4)) - (export "___udivmoddi4" (func $___udivmoddi4)) - ;; CHECK: (func $stackAlloc (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - (func $stackAlloc (param $0 i32) (result i32) - (local $1 i32) - (local.set $1 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (local.get $0) - ) - ) - (global.set $STACKTOP - (i32.and - (i32.add - (global.get $STACKTOP) - (i32.const 15) - ) - (i32.const -16) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (local.get $1) - ) - ;; CHECK: (func $stackSave (result i32) - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - (func $stackSave (result i32) - (global.get $STACKTOP) - ) - ;; CHECK: (func $stackRestore (param $0 i32) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $stackRestore (param $0 i32) - (global.set $STACKTOP - (local.get $0) - ) - ) - ;; CHECK: (func $establishStackSpace (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACK_MAX - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $establishStackSpace (param $0 i32) (param $1 i32) - (global.set $STACKTOP - (local.get $0) - ) - (global.set $STACK_MAX - (local.get $1) - ) - ) - ;; CHECK: (func $setThrew (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $__THREW__) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (global.set $__THREW__ - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $threwValue - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $setThrew (param $0 i32) (param $1 i32) - (if - (i32.eqz - (global.get $__THREW__) - ) - (block - (global.set $__THREW__ - (local.get $0) - ) - (global.set $threwValue - (local.get $1) - ) - ) - ) - ) - ;; CHECK: (func $setTempRet0 (param $0 i32) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $setTempRet0 (param $0 i32) - (global.set $tempRet0 - (local.get $0) - ) - ) - ;; CHECK: (func $getTempRet0 (result i32) - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - (func $getTempRet0 (result i32) - (global.get $tempRet0) - ) - ;; CHECK: (func $_main (result i32) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 224) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 120) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 136) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 80) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $do-in - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-in - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (call $_printf_core - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 672) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=76 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (i32.load8_s offset=74 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const -33) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $_printf_core - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 672) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 80) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $13 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 80) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (call $_printf_core - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 672) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$iiii) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=36 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $_main (result i32) - (local $0 i32) - (local.set $0 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 16) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (drop - (call $_printf - (i32.const 672) - (local.get $0) - ) - ) - (global.set $STACKTOP - (local.get $0) - ) - (i32.const 0) - ) - ;; CHECK: (func $_frexp (param $0 f64) (param $1 i32) (result f64) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch - ;; CHECK-NEXT: (block $switch-default - ;; CHECK-NEXT: (block $switch-case0 - ;; CHECK-NEXT: (block $switch-case - ;; CHECK-NEXT: (br_table $switch-case $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case0 $switch-default - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (call $_bitshift64Lshr - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 52) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2047) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $_frexp - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.const 18446744073709551615) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $switch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $switch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const -1022) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const -2146435073) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1071644672) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $_frexp (param $0 f64) (param $1 i32) (result f64) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (f64.store - (global.get $tempDoublePtr) - (local.get $0) - ) - (block $switch - (block $switch-default - (block $switch-case0 - (block $switch-case - (br_table $switch-case $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case0 $switch-default - (local.tee $3 - (i32.and - (local.tee $3 - (call $_bitshift64Lshr - (local.tee $2 - (i32.load - (global.get $tempDoublePtr) - ) - ) - (local.tee $4 - (i32.load offset=4 - (global.get $tempDoublePtr) - ) - ) - (i32.const 52) - ) - ) - (i32.const 2047) - ) - ) - ) - ) - (i32.store - (local.get $1) - (local.tee $2 - (if (result i32) - (f64.ne - (local.get $0) - (f64.const 0) - ) - (block (result i32) - (local.set $0 - (call $_frexp - (f64.mul - (local.get $0) - (f64.const 18446744073709551615) - ) - (local.get $1) - ) - ) - (i32.add - (i32.load - (local.get $1) - ) - (i32.const -64) - ) - ) - (i32.const 0) - ) - ) - ) - (br $switch) - ) - (br $switch) - ) - (i32.store - (local.get $1) - (i32.add - (local.get $3) - (i32.const -1022) - ) - ) - (i32.store - (global.get $tempDoublePtr) - (local.get $2) - ) - (i32.store offset=4 - (global.get $tempDoublePtr) - (i32.or - (i32.and - (local.get $4) - (i32.const -2146435073) - ) - (i32.const 1071644672) - ) - ) - (local.set $0 - (f64.load - (global.get $tempDoublePtr) - ) - ) - ) - (local.get $0) - ) - (func $_strerror (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (i32.const 0) - ) - (block $__rjto$1 - (block $__rjti$1 - (block $__rjti$0 - (loop $while-in - (br_if $__rjti$0 - (i32.eq - (i32.load8_u offset=687 - (local.get $1) - ) - (local.get $0) - ) - ) - (br_if $while-in - (i32.ne - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (i32.const 87) - ) - ) - (local.set $1 - (i32.const 87) - ) - (br $__rjti$1) - ) - ) - (br_if $__rjti$1 - (local.get $1) - ) - (local.set $0 - (i32.const 775) - ) - (br $__rjto$1) - ) - (local.set $0 - (i32.const 775) - ) - (loop $while-in1 - (loop $while-in3 - (local.set $2 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (if - (i32.load8_s - (local.get $0) - ) - (block - (local.set $0 - (local.get $2) - ) - (br $while-in3) - ) - (local.set $0 - (local.get $2) - ) - ) - ) - (br_if $while-in1 - (local.tee $1 - (i32.add - (local.get $1) - (i32.const -1) - ) - ) - ) - ) - ) - (local.get $0) - ) - ;; CHECK: (func $___errno_location (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=60 - ;; CHECK-NEXT: (call $_pthread_self) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 60) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $___errno_location (result i32) - (if (result i32) - (i32.load - (i32.const 16) - ) - (i32.load offset=60 - (call $_pthread_self) - ) - (i32.const 60) - ) - ) - ;; CHECK: (func $___stdio_close (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=60 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $___syscall_ret - ;; CHECK-NEXT: (call $___syscall6 - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $___stdio_close (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 16) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (i32.store - (local.tee $2 - (local.get $1) - ) - (i32.load offset=60 - (local.get $0) - ) - ) - (local.set $0 - (call $___syscall_ret - (call $___syscall6 - (i32.const 6) - (local.get $2) - ) - ) - ) - (global.set $STACKTOP - (local.get $1) - ) - (local.get $0) - ) - ;; CHECK: (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 80) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=36 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.load offset=60 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 21505) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $___syscall54 - ;; CHECK-NEXT: (i32.const 54) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=75 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $___stdio_write - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $4 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 80) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (local.set $3 - (local.get $4) - ) - (local.set $5 - (i32.add - (local.get $4) - (i32.const 12) - ) - ) - (i32.store offset=36 - (local.get $0) - (i32.const 4) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 64) - ) - ) - (block - (i32.store - (local.get $3) - (i32.load offset=60 - (local.get $0) - ) - ) - (i32.store offset=4 - (local.get $3) - (i32.const 21505) - ) - (i32.store offset=8 - (local.get $3) - (local.get $5) - ) - (if - (call $___syscall54 - (i32.const 54) - (local.get $3) - ) - (i32.store8 offset=75 - (local.get $0) - (i32.const -1) - ) - ) - ) - ) - (local.set $0 - (call $___stdio_write - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - (global.set $STACKTOP - (local.get $4) - ) - (local.get $0) - ) - ;; CHECK: (func $___stdio_seek (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=60 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (call $___syscall_ret - ;; CHECK-NEXT: (call $___syscall140 - ;; CHECK-NEXT: (i32.const 140) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $___stdio_seek (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local.set $4 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 32) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (i32.store - (local.tee $3 - (local.get $4) - ) - (i32.load offset=60 - (local.get $0) - ) - ) - (i32.store offset=4 - (local.get $3) - (i32.const 0) - ) - (i32.store offset=8 - (local.get $3) - (local.get $1) - ) - (i32.store offset=12 - (local.get $3) - (local.tee $0 - (i32.add - (local.get $4) - (i32.const 20) - ) - ) - ) - (i32.store offset=16 - (local.get $3) - (local.get $2) - ) - (local.set $0 - (if (result i32) - (i32.lt_s - (call $___syscall_ret - (call $___syscall140 - (i32.const 140) - (local.get $3) - ) - ) - (i32.const 0) - ) - (block (result i32) - (i32.store - (local.get $0) - (i32.const -1) - ) - (i32.const -1) - ) - (i32.load - (local.get $0) - ) - ) - ) - (global.set $STACKTOP - (local.get $4) - ) - (local.get $0) - ) - ;; CHECK: (func $_fflush (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $do-once (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.load offset=76 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once - ;; CHECK-NEXT: (call $___fflush_unlocked - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (call $___fflush_unlocked - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_fflush - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $___lock - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=76 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.load offset=20 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=28 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $___fflush_unlocked - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=56 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $___unlock - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $_fflush (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (block $do-once - (if - (local.get $0) - (block - (if - (i32.le_s - (i32.load offset=76 - (local.get $0) - ) - (i32.const -1) - ) - (block - (local.set $0 - (call $___fflush_unlocked - (local.get $0) - ) - ) - (br $do-once) - ) - ) - (local.set $2 - (i32.eqz - (call $___lockfile - (local.get $0) - ) - ) - ) - (local.set $1 - (call $___fflush_unlocked - (local.get $0) - ) - ) - (local.set $0 - (if (result i32) - (local.get $2) - (local.get $1) - (block (result i32) - (call $___unlockfile - (local.get $0) - ) - (local.get $1) - ) - ) - ) - ) - (block - (local.set $0 - (if (result i32) - (i32.load - (i32.const 12) - ) - (call $_fflush - (i32.load - (i32.const 12) - ) - ) - (i32.const 0) - ) - ) - (call $___lock - (i32.const 44) - ) - (if - (local.tee $1 - (i32.load - (i32.const 40) - ) - ) - (loop $while-in - (local.set $2 - (if (result i32) - (i32.gt_s - (i32.load offset=76 - (local.get $1) - ) - (i32.const -1) - ) - (call $___lockfile - (local.get $1) - ) - (i32.const 0) - ) - ) - (if - (i32.gt_u - (i32.load offset=20 - (local.get $1) - ) - (i32.load offset=28 - (local.get $1) - ) - ) - (local.set $0 - (i32.or - (call $___fflush_unlocked - (local.get $1) - ) - (local.get $0) - ) - ) - ) - (if - (local.get $2) - (call $___unlockfile - (local.get $1) - ) - ) - (br_if $while-in - (local.tee $1 - (i32.load offset=56 - (local.get $1) - ) - ) - ) - ) - ) - (call $___unlock - (i32.const 44) - ) - ) - ) - ) - (local.get $0) - ) - (func $_printf (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local.set $2 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 16) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (i32.store - (local.tee $3 - (local.get $2) - ) - (local.get $1) - ) - (local.set $0 - (call $_vfprintf - (i32.load - (i32.const 8) - ) - (local.get $0) - (local.get $3) - ) - ) - (global.set $STACKTOP - (local.get $2) - ) - (local.get $0) - ) - (func $___lockfile (param $0 i32) (result i32) - (i32.const 0) - ) - (func $___unlockfile (param $0 i32) - (nop) - ) - ;; CHECK: (func $___stdio_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 60) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$1 - ;; CHECK-NEXT: (block $__rjti$1 - ;; CHECK-NEXT: (block $__rjti$0 - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (call $_pthread_cleanup_push - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $___syscall_ret - ;; CHECK-NEXT: (call $___syscall146 - ;; CHECK-NEXT: (i32.const 146) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pthread_cleanup_pop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block14 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call $___syscall_ret - ;; CHECK-NEXT: (call $___syscall146 - ;; CHECK-NEXT: (i32.const 146) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$0 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$1 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block16 (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block17 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block19 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=48 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - (func $___stdio_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local $10 i32) - (local $11 i32) - (local $12 i32) - (local $13 i32) - (local $14 i32) - (local.set $8 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 48) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (local.set $9 - (i32.add - (local.get $8) - (i32.const 16) - ) - ) - (local.set $10 - (local.get $8) - ) - (i32.store - (local.tee $4 - (i32.add - (local.get $8) - (i32.const 32) - ) - ) - (local.tee $3 - (i32.load - (local.tee $6 - (i32.add - (local.get $0) - (i32.const 28) - ) - ) - ) - ) - ) - (i32.store offset=4 - (local.get $4) - (local.tee $3 - (i32.sub - (i32.load - (local.tee $11 - (i32.add - (local.get $0) - (i32.const 20) - ) - ) - ) - (local.get $3) - ) - ) - ) - (i32.store offset=8 - (local.get $4) - (local.get $1) - ) - (i32.store offset=12 - (local.get $4) - (local.get $2) - ) - (local.set $13 - (i32.add - (local.get $0) - (i32.const 60) - ) - ) - (local.set $14 - (i32.add - (local.get $0) - (i32.const 44) - ) - ) - (local.set $1 - (local.get $4) - ) - (local.set $4 - (i32.const 2) - ) - (local.set $12 - (i32.add - (local.get $3) - (local.get $2) - ) - ) - (block $__rjto$1 - (block $__rjti$1 - (block $__rjti$0 - (loop $while-in - (if - (i32.load - (i32.const 16) - ) - (block - (call $_pthread_cleanup_push - (i32.const 5) - (local.get $0) - ) - (i32.store - (local.get $10) - (i32.load - (local.get $13) - ) - ) - (i32.store offset=4 - (local.get $10) - (local.get $1) - ) - (i32.store offset=8 - (local.get $10) - (local.get $4) - ) - (local.set $3 - (call $___syscall_ret - (call $___syscall146 - (i32.const 146) - (local.get $10) - ) - ) - ) - (call $_pthread_cleanup_pop - (i32.const 0) - ) - ) - (block - (i32.store - (local.get $9) - (i32.load - (local.get $13) - ) - ) - (i32.store offset=4 - (local.get $9) - (local.get $1) - ) - (i32.store offset=8 - (local.get $9) - (local.get $4) - ) - (local.set $3 - (call $___syscall_ret - (call $___syscall146 - (i32.const 146) - (local.get $9) - ) - ) - ) - ) - ) - (br_if $__rjti$0 - (i32.eq - (local.get $12) - (local.get $3) - ) - ) - (br_if $__rjti$1 - (i32.lt_s - (local.get $3) - (i32.const 0) - ) - ) - (local.set $5 - (if (result i32) - (i32.gt_u - (local.get $3) - (local.tee $5 - (i32.load offset=4 - (local.get $1) - ) - ) - ) - (block (result i32) - (i32.store - (local.get $6) - (local.tee $7 - (i32.load - (local.get $14) - ) - ) - ) - (i32.store - (local.get $11) - (local.get $7) - ) - (local.set $7 - (i32.load offset=12 - (local.get $1) - ) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - (local.set $4 - (i32.add - (local.get $4) - (i32.const -1) - ) - ) - (i32.sub - (local.get $3) - (local.get $5) - ) - ) - (block (result i32) - (if - (i32.eq - (local.get $4) - (i32.const 2) - ) - (block - (i32.store - (local.get $6) - (i32.add - (i32.load - (local.get $6) - ) - (local.get $3) - ) - ) - (local.set $7 - (local.get $5) - ) - (local.set $4 - (i32.const 2) - ) - ) - (local.set $7 - (local.get $5) - ) - ) - (local.get $3) - ) - ) - ) - (i32.store - (local.get $1) - (i32.add - (i32.load - (local.get $1) - ) - (local.get $5) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.sub - (local.get $7) - (local.get $5) - ) - ) - (local.set $12 - (i32.sub - (local.get $12) - (local.get $3) - ) - ) - (br $while-in) - ) - ) - (i32.store offset=16 - (local.get $0) - (i32.add - (local.tee $1 - (i32.load - (local.get $14) - ) - ) - (i32.load offset=48 - (local.get $0) - ) - ) - ) - (i32.store - (local.get $6) - (local.get $1) - ) - (i32.store - (local.get $11) - (local.get $1) - ) - (br $__rjto$1) - ) - (i32.store offset=16 - (local.get $0) - (i32.const 0) - ) - (i32.store - (local.get $6) - (i32.const 0) - ) - (i32.store - (local.get $11) - (i32.const 0) - ) - (i32.store - (local.get $0) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (local.set $2 - (if (result i32) - (i32.eq - (local.get $4) - (i32.const 2) - ) - (i32.const 0) - (i32.sub - (local.get $2) - (i32.load offset=4 - (local.get $1) - ) - ) - ) - ) - ) - (global.set $STACKTOP - (local.get $8) - ) - (local.get $2) - ) - (func $_vfprintf (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local $10 i32) - (local $11 i32) - (local $12 i32) - (local $13 i32) - (local $14 i32) - (local.set $4 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 224) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (local.set $5 - (i32.add - (local.get $4) - (i32.const 120) - ) - ) - (local.set $7 - (local.get $4) - ) - (local.set $6 - (i32.add - (local.get $4) - (i32.const 136) - ) - ) - (local.set $9 - (i32.add - (local.tee $3 - (local.tee $8 - (i32.add - (local.get $4) - (i32.const 80) - ) - ) - ) - (i32.const 40) - ) - ) - (loop $do-in - (i32.store - (local.get $3) - (i32.const 0) - ) - (br_if $do-in - (i32.lt_s - (local.tee $3 - (i32.add - (local.get $3) - (i32.const 4) - ) - ) - (local.get $9) - ) - ) - ) - (i32.store - (local.get $5) - (i32.load - (local.get $2) - ) - ) - (local.set $0 - (if (result i32) - (i32.lt_s - (call $_printf_core - (i32.const 0) - (local.get $1) - (local.get $5) - (local.get $7) - (local.get $8) - ) - (i32.const 0) - ) - (i32.const -1) - (block (result i32) - (local.set $14 - (if (result i32) - (i32.gt_s - (i32.load offset=76 - (local.get $0) - ) - (i32.const -1) - ) - (call $___lockfile - (local.get $0) - ) - (i32.const 0) - ) - ) - (local.set $10 - (i32.load - (local.get $0) - ) - ) - (if - (i32.lt_s - (i32.load8_s offset=74 - (local.get $0) - ) - (i32.const 1) - ) - (i32.store - (local.get $0) - (i32.and - (local.get $10) - (i32.const -33) - ) - ) - ) - (if - (i32.load - (local.tee $11 - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - ) - (local.set $1 - (call $_printf_core - (local.get $0) - (local.get $1) - (local.get $5) - (local.get $7) - (local.get $8) - ) - ) - (block - (local.set $13 - (i32.load - (local.tee $12 - (i32.add - (local.get $0) - (i32.const 44) - ) - ) - ) - ) - (i32.store - (local.get $12) - (local.get $6) - ) - (i32.store - (local.tee $9 - (i32.add - (local.get $0) - (i32.const 28) - ) - ) - (local.get $6) - ) - (i32.store - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 20) - ) - ) - (local.get $6) - ) - (i32.store - (local.get $11) - (i32.const 80) - ) - (i32.store - (local.tee $2 - (i32.add - (local.get $0) - (i32.const 16) - ) - ) - (i32.add - (local.get $6) - (i32.const 80) - ) - ) - (local.set $1 - (call $_printf_core - (local.get $0) - (local.get $1) - (local.get $5) - (local.get $7) - (local.get $8) - ) - ) - (if - (local.get $13) - (block - (drop - (call_indirect (type $FUNCSIG$iiii) - (local.get $0) - (i32.const 0) - (i32.const 0) - (i32.add - (i32.and - (i32.load offset=36 - (local.get $0) - ) - (i32.const 7) - ) - (i32.const 2) - ) - ) - ) - (local.set $1 - (select - (local.get $1) - (i32.const -1) - (i32.load - (local.get $3) - ) - ) - ) - (i32.store - (local.get $12) - (local.get $13) - ) - (i32.store - (local.get $11) - (i32.const 0) - ) - (i32.store - (local.get $2) - (i32.const 0) - ) - (i32.store - (local.get $9) - (i32.const 0) - ) - (i32.store - (local.get $3) - (i32.const 0) - ) - ) - ) - ) - ) - (i32.store - (local.get $0) - (i32.or - (local.tee $2 - (i32.load - (local.get $0) - ) - ) - (i32.and - (local.get $10) - (i32.const 32) - ) - ) - ) - (if - (local.get $14) - (call $___unlockfile - (local.get $0) - ) - ) - (select - (i32.const -1) - (local.get $1) - (i32.and - (local.get $2) - (i32.const 32) - ) - ) - ) - ) - ) - (global.set $STACKTOP - (local.get $4) - ) - (local.get $0) - ) - ;; CHECK: (func $___fwritex (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (block $label$break$L5 - ;; CHECK-NEXT: (block $__rjti$0 - ;; CHECK-NEXT: (br_if $__rjti$0 - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 74) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=28 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load offset=44 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.load offset=48 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$iiii) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=36 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.load8_s offset=75 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L10 (result i32) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $label$break$L10 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$break$L5 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$iiii) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=36 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $_memcpy - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - (func $___fwritex (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (block $label$break$L5 - (block $__rjti$0 - (br_if $__rjti$0 - (local.tee $3 - (i32.load - (local.tee $4 - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - ) - ) - ) - (if - (call $___towrite - (local.get $2) - ) - (local.set $3 - (i32.const 0) - ) - (block - (local.set $3 - (i32.load - (local.get $4) - ) - ) - (br $__rjti$0) - ) - ) - (br $label$break$L5) - ) - (if - (i32.lt_u - (i32.sub - (local.get $3) - (local.tee $4 - (i32.load - (local.tee $5 - (i32.add - (local.get $2) - (i32.const 20) - ) - ) - ) - ) - ) - (local.get $1) - ) - (block - (local.set $3 - (call_indirect (type $FUNCSIG$iiii) - (local.get $2) - (local.get $0) - (local.get $1) - (i32.add - (i32.and - (i32.load offset=36 - (local.get $2) - ) - (i32.const 7) - ) - (i32.const 2) - ) - ) - ) - (br $label$break$L5) - ) - ) - (local.set $2 - (block $label$break$L10 (result i32) - (if (result i32) - (i32.gt_s - (i32.load8_s offset=75 - (local.get $2) - ) - (i32.const -1) - ) - (block (result i32) - (local.set $3 - (local.get $1) - ) - (loop $while-in - (drop - (br_if $label$break$L10 - (i32.const 0) - (i32.eqz - (local.get $3) - ) - ) - ) - (if - (i32.ne - (i32.load8_s - (i32.add - (local.get $0) - (local.tee $6 - (i32.add - (local.get $3) - (i32.const -1) - ) - ) - ) - ) - (i32.const 10) - ) - (block - (local.set $3 - (local.get $6) - ) - (br $while-in) - ) - ) - ) - (br_if $label$break$L5 - (i32.lt_u - (call_indirect (type $FUNCSIG$iiii) - (local.get $2) - (local.get $0) - (local.get $3) - (i32.add - (i32.and - (i32.load offset=36 - (local.get $2) - ) - (i32.const 7) - ) - (i32.const 2) - ) - ) - (local.get $3) - ) - ) - (local.set $4 - (i32.load - (local.get $5) - ) - ) - (local.set $1 - (i32.sub - (local.get $1) - (local.get $3) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (local.get $3) - ) - ) - (local.get $3) - ) - (i32.const 0) - ) - ) - ) - (drop - (call $_memcpy - (local.get $4) - (local.get $0) - (local.get $1) - ) - ) - (i32.store - (local.get $5) - (i32.add - (i32.load - (local.get $5) - ) - (local.get $1) - ) - ) - (local.set $3 - (i32.add - (local.get $2) - (local.get $1) - ) - ) - ) - (local.get $3) - ) - (func $___towrite (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (i32.load8_s - (local.tee $2 - (i32.add - (local.get $0) - (i32.const 74) - ) - ) - ) - ) - (i32.store8 - (local.get $2) - (i32.or - (i32.add - (local.get $1) - (i32.const 255) - ) - (local.get $1) - ) - ) - (local.tee $0 - (if (result i32) - (i32.and - (local.tee $1 - (i32.load - (local.get $0) - ) - ) - (i32.const 8) - ) - (block (result i32) - (i32.store - (local.get $0) - (i32.or - (local.get $1) - (i32.const 32) - ) - ) - (i32.const -1) - ) - (block (result i32) - (i32.store offset=8 - (local.get $0) - (i32.const 0) - ) - (i32.store offset=4 - (local.get $0) - (i32.const 0) - ) - (i32.store offset=28 - (local.get $0) - (local.tee $1 - (i32.load offset=44 - (local.get $0) - ) - ) - ) - (i32.store offset=20 - (local.get $0) - (local.get $1) - ) - (i32.store offset=16 - (local.get $0) - (i32.add - (local.get $1) - (i32.load offset=48 - (local.get $0) - ) - ) - ) - (i32.const 0) - ) - ) - ) - ) - (func $_wcrtomb (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (block $do-once (result i32) - (if (result i32) - (local.get $0) - (block (result i32) - (if - (i32.lt_u - (local.get $1) - (i32.const 128) - ) - (block - (i32.store8 - (local.get $0) - (local.get $1) - ) - (br $do-once - (i32.const 1) - ) - ) - ) - (if - (i32.lt_u - (local.get $1) - (i32.const 2048) - ) - (block - (i32.store8 - (local.get $0) - (i32.or - (i32.shr_u - (local.get $1) - (i32.const 6) - ) - (i32.const 192) - ) - ) - (i32.store8 offset=1 - (local.get $0) - (i32.or - (i32.and - (local.get $1) - (i32.const 63) - ) - (i32.const 128) - ) - ) - (br $do-once - (i32.const 2) - ) - ) - ) - (if - (i32.or - (i32.lt_u - (local.get $1) - (i32.const 55296) - ) - (i32.eq - (i32.and - (local.get $1) - (i32.const -8192) - ) - (i32.const 57344) - ) - ) - (block - (i32.store8 - (local.get $0) - (i32.or - (i32.shr_u - (local.get $1) - (i32.const 12) - ) - (i32.const 224) - ) - ) - (i32.store8 offset=1 - (local.get $0) - (i32.or - (i32.and - (i32.shr_u - (local.get $1) - (i32.const 6) - ) - (i32.const 63) - ) - (i32.const 128) - ) - ) - (i32.store8 offset=2 - (local.get $0) - (i32.or - (i32.and - (local.get $1) - (i32.const 63) - ) - (i32.const 128) - ) - ) - (br $do-once - (i32.const 3) - ) - ) - ) - (if (result i32) - (i32.lt_u - (i32.add - (local.get $1) - (i32.const -65536) - ) - (i32.const 1048576) - ) - (block (result i32) - (i32.store8 - (local.get $0) - (i32.or - (i32.shr_u - (local.get $1) - (i32.const 18) - ) - (i32.const 240) - ) - ) - (i32.store8 offset=1 - (local.get $0) - (i32.or - (i32.and - (i32.shr_u - (local.get $1) - (i32.const 12) - ) - (i32.const 63) - ) - (i32.const 128) - ) - ) - (i32.store8 offset=2 - (local.get $0) - (i32.or - (i32.and - (i32.shr_u - (local.get $1) - (i32.const 6) - ) - (i32.const 63) - ) - (i32.const 128) - ) - ) - (i32.store8 offset=3 - (local.get $0) - (i32.or - (i32.and - (local.get $1) - (i32.const 63) - ) - (i32.const 128) - ) - ) - (i32.const 4) - ) - (block (result i32) - (i32.store - (call $___errno_location) - (i32.const 84) - ) - (i32.const -1) - ) - ) - ) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $_wctomb (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (block $do-once (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 2048) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 57344) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 55296) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 224) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 65536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 240) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (call $___errno_location) - ;; CHECK-NEXT: (i32.const 84) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_wctomb (param $0 i32) (param $1 i32) (result i32) - (if (result i32) - (local.get $0) - (call $_wcrtomb - (local.get $0) - (local.get $1) - (i32.const 0) - ) - (i32.const 0) - ) - ) - (func $_memchr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $5 - (i32.and - (local.get $1) - (i32.const 255) - ) - ) - (block $label$break$L8 - (block $__rjti$2 - (if - (i32.and - (local.tee $4 - (i32.ne - (local.get $2) - (i32.const 0) - ) - ) - (i32.ne - (i32.and - (local.get $0) - (i32.const 3) - ) - (i32.const 0) - ) - ) - (block - (local.set $4 - (i32.and - (local.get $1) - (i32.const 255) - ) - ) - (local.set $3 - (local.get $2) - ) - (local.set $2 - (local.get $0) - ) - (loop $while-in - (br_if $__rjti$2 - (i32.eq - (i32.load8_u - (local.get $2) - ) - (i32.and - (local.get $4) - (i32.const 255) - ) - ) - ) - (br_if $while-in - (i32.and - (local.tee $0 - (i32.ne - (local.tee $3 - (i32.add - (local.get $3) - (i32.const -1) - ) - ) - (i32.const 0) - ) - ) - (i32.ne - (i32.and - (local.tee $2 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (i32.const 3) - ) - (i32.const 0) - ) - ) - ) - ) - ) - (block - (local.set $3 - (local.get $2) - ) - (local.set $2 - (local.get $0) - ) - (local.set $0 - (local.get $4) - ) - ) - ) - (br_if $__rjti$2 - (local.get $0) - ) - (local.set $0 - (i32.const 0) - ) - (br $label$break$L8) - ) - (local.set $0 - (local.get $3) - ) - (if - (i32.ne - (i32.load8_u - (local.get $2) - ) - (local.tee $1 - (i32.and - (local.get $1) - (i32.const 255) - ) - ) - ) - (block - (local.set $3 - (i32.mul - (local.get $5) - (i32.const 16843009) - ) - ) - (block $__rjto$0 - (block $__rjti$0 - (br_if $__rjti$0 - (i32.le_u - (local.get $0) - (i32.const 3) - ) - ) - (loop $while-in3 - (if - (i32.eqz - (i32.and - (i32.xor - (i32.and - (local.tee $4 - (i32.xor - (i32.load - (local.get $2) - ) - (local.get $3) - ) - ) - (i32.const -2139062144) - ) - (i32.const -2139062144) - ) - (i32.add - (local.get $4) - (i32.const -16843009) - ) - ) - ) - (block - (local.set $2 - (i32.add - (local.get $2) - (i32.const 4) - ) - ) - (br_if $while-in3 - (i32.gt_u - (local.tee $0 - (i32.add - (local.get $0) - (i32.const -4) - ) - ) - (i32.const 3) - ) - ) - (br $__rjti$0) - ) - ) - ) - (br $__rjto$0) - ) - (if - (i32.eqz - (local.get $0) - ) - (block - (local.set $0 - (i32.const 0) - ) - (br $label$break$L8) - ) - ) - ) - (loop $while-in5 - (br_if $label$break$L8 - (i32.eq - (i32.load8_u - (local.get $2) - ) - (i32.and - (local.get $1) - (i32.const 255) - ) - ) - ) - (local.set $2 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (br_if $while-in5 - (local.tee $0 - (i32.add - (local.get $0) - (i32.const -1) - ) - ) - ) - (local.set $0 - (i32.const 0) - ) - ) - ) - ) - ) - (select - (local.get $2) - (i32.const 0) - (local.get $0) - ) - ) - ;; CHECK: (func $___syscall_ret (param $0 i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -4096) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (call $___errno_location) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $___syscall_ret (param $0 i32) (result i32) - (if (result i32) - (i32.gt_u - (local.get $0) - (i32.const -4096) - ) - (block (result i32) - (i32.store - (call $___errno_location) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - (i32.const -1) - ) - (local.get $0) - ) - ) - ;; CHECK: (func $___fflush_unlocked (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (block $__rjto$0 (result i32) - ;; CHECK-NEXT: (block $__rjti$0 - ;; CHECK-NEXT: (br_if $__rjti$0 - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$iiii) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=36 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$0 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$iiii) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=40 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $___fflush_unlocked (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local.tee $0 - (block $__rjto$0 (result i32) - (block $__rjti$0 - (br_if $__rjti$0 - (i32.le_u - (i32.load - (local.tee $1 - (i32.add - (local.get $0) - (i32.const 20) - ) - ) - ) - (i32.load - (local.tee $2 - (i32.add - (local.get $0) - (i32.const 28) - ) - ) - ) - ) - ) - (drop - (call_indirect (type $FUNCSIG$iiii) - (local.get $0) - (i32.const 0) - (i32.const 0) - (i32.add - (i32.and - (i32.load offset=36 - (local.get $0) - ) - (i32.const 7) - ) - (i32.const 2) - ) - ) - ) - (br_if $__rjti$0 - (i32.load - (local.get $1) - ) - ) - (br $__rjto$0 - (i32.const -1) - ) - ) - (if - (i32.lt_u - (local.tee $4 - (i32.load - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - ) - ) - (local.tee $6 - (i32.load - (local.tee $5 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - ) - (drop - (call_indirect (type $FUNCSIG$iiii) - (local.get $0) - (i32.sub - (local.get $4) - (local.get $6) - ) - (i32.const 1) - (i32.add - (i32.and - (i32.load offset=40 - (local.get $0) - ) - (i32.const 7) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $0) - (i32.const 0) - ) - (i32.store - (local.get $2) - (i32.const 0) - ) - (i32.store - (local.get $1) - (i32.const 0) - ) - (i32.store - (local.get $5) - (i32.const 0) - ) - (i32.store - (local.get $3) - (i32.const 0) - ) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $_cleanup (param $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=68 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_cleanup (param $0 i32) - (if - (i32.eqz - (i32.load offset=68 - (local.get $0) - ) - ) - (call $___unlockfile - (local.get $0) - ) - ) - ) - (func $f64-to-int (param $0 f64) (result i32) - (if (result i32) - (f64.ne - (local.get $0) - (local.get $0) - ) - (i32.const -2147483648) - (if (result i32) - (f64.ge - (local.get $0) - (f64.const 2147483648) - ) - (i32.const -2147483648) - (if (result i32) - (f64.le - (local.get $0) - (f64.const -2147483649) - ) - (i32.const -2147483648) - (i32.trunc_f64_s - (local.get $0) - ) - ) - ) - ) - ) - (func $i32s-div (param $0 i32) (param $1 i32) (result i32) - (if (result i32) - (local.get $1) - (if (result i32) - (i32.and - (i32.eq - (local.get $0) - (i32.const -2147483648) - ) - (i32.eq - (local.get $1) - (i32.const -1) - ) - ) - (i32.const 0) - (i32.div_s - (local.get $0) - (local.get $1) - ) - ) - (i32.const 0) - ) - ) - (func $i32u-rem (param $0 i32) (param $1 i32) (result i32) - (if (result i32) - (local.get $1) - (i32.rem_u - (local.get $0) - (local.get $1) - ) - (i32.const 0) - ) - ) - (func $i32u-div (param $0 i32) (param $1 i32) (result i32) - (if (result i32) - (local.get $1) - (i32.div_u - (local.get $0) - (local.get $1) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $_printf_core (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 f64) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (local $19 i32) - ;; CHECK-NEXT: (local $20 i32) - ;; CHECK-NEXT: (local $21 i32) - ;; CHECK-NEXT: (local $22 i32) - ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (local $24 i32) - ;; CHECK-NEXT: (local $25 f64) - ;; CHECK-NEXT: (local $26 i32) - ;; CHECK-NEXT: (local $27 i32) - ;; CHECK-NEXT: (local $28 i32) - ;; CHECK-NEXT: (local $29 i32) - ;; CHECK-NEXT: (local $30 i32) - ;; CHECK-NEXT: (local $31 i32) - ;; CHECK-NEXT: (local $32 i32) - ;; CHECK-NEXT: (local $33 i32) - ;; CHECK-NEXT: (local $34 i32) - ;; CHECK-NEXT: (local $35 i32) - ;; CHECK-NEXT: (local $36 i32) - ;; CHECK-NEXT: (local $37 i32) - ;; CHECK-NEXT: (local $38 i32) - ;; CHECK-NEXT: (local $39 i32) - ;; CHECK-NEXT: (local $40 i32) - ;; CHECK-NEXT: (local $41 i32) - ;; CHECK-NEXT: (local $42 i32) - ;; CHECK-NEXT: (local $43 i32) - ;; CHECK-NEXT: (local $44 i32) - ;; CHECK-NEXT: (local $45 i32) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $21 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $33 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 528) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $29 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $23 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $36 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 39) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $39 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $37 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $24 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $38 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $40 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (local.tee $22 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 588) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $41 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $42 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $44 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $43 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 288) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $27 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $32 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L343 - ;; CHECK-NEXT: (block $__rjti$9 - ;; CHECK-NEXT: (loop $label$continue$L1 - ;; CHECK-NEXT: (block $label$break$L1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (call $___errno_location) - ;; CHECK-NEXT: (i32.const 75) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$9 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L12 - ;; CHECK-NEXT: (block $__rjti$1 - ;; CHECK-NEXT: (loop $label$continue$L9 - ;; CHECK-NEXT: (block $label$break$L9 - ;; CHECK-NEXT: (block $switch-default - ;; CHECK-NEXT: (block $switch-case0 - ;; CHECK-NEXT: (block $switch-case - ;; CHECK-NEXT: (br_table $switch-case0 $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case $switch-default - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (br_if $label$break$L12 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load8_s offset=1 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $29) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s offset=2 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L25 (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in4 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 75913) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L25 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in4 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once5 (result i32) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (block $__rjto$0 (result i32) - ;; CHECK-NEXT: (block $__rjti$0 - ;; CHECK-NEXT: (br_if $__rjti$0 - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$0 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load8_s offset=2 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $29) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once5 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in8 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 46) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L46 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L46 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in11 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $label$break$L46 - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s offset=3 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L46 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $29) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in13 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 57) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $15 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 58) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3611) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$2 - ;; CHECK-NEXT: (block $__rjti$2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $29) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pop_arg_336 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $29) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const -65537) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $15 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (block $__rjto$8 (result i32) - ;; CHECK-NEXT: (block $__rjti$8 - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (block $__rjti$7 (result i32) - ;; CHECK-NEXT: (block $__rjti$6 - ;; CHECK-NEXT: (block $__rjti$5 - ;; CHECK-NEXT: (block $__rjti$4 - ;; CHECK-NEXT: (block $__rjti$3 - ;; CHECK-NEXT: (block $switch-default120 - ;; CHECK-NEXT: (block $switch-case42 - ;; CHECK-NEXT: (block $switch-case41 - ;; CHECK-NEXT: (block $switch-case40 - ;; CHECK-NEXT: (block $switch-case39 - ;; CHECK-NEXT: (block $switch-case38 - ;; CHECK-NEXT: (block $switch-case37 - ;; CHECK-NEXT: (block $switch-case36 - ;; CHECK-NEXT: (block $switch-case34 - ;; CHECK-NEXT: (block $switch-case33 - ;; CHECK-NEXT: (block $switch-case29 - ;; CHECK-NEXT: (block $switch-case28 - ;; CHECK-NEXT: (block $switch-case27 - ;; CHECK-NEXT: (br_table $switch-case42 $switch-default120 $switch-case40 $switch-default120 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case41 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case29 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case42 $switch-default120 $switch-case37 $switch-case34 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-case34 $switch-default120 $switch-default120 $switch-default120 $switch-case38 $switch-case27 $switch-case33 $switch-case28 $switch-default120 $switch-default120 $switch-case39 $switch-default120 $switch-case36 $switch-default120 $switch-default120 $switch-case29 $switch-default120 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -33) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch-default26 - ;; CHECK-NEXT: (block $switch-case25 - ;; CHECK-NEXT: (block $switch-case24 - ;; CHECK-NEXT: (block $switch-case23 - ;; CHECK-NEXT: (block $switch-case22 - ;; CHECK-NEXT: (block $switch-case21 - ;; CHECK-NEXT: (block $switch-case20 - ;; CHECK-NEXT: (block $switch-case19 - ;; CHECK-NEXT: (br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.const 120) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in32 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in32 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_bitshift64Lshr - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 2048) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4092) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 4093) - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $36) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $36) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$8 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (call $___errno_location) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$1 - ;; CHECK-NEXT: (block $__rjti$10 - ;; CHECK-NEXT: (loop $while-in2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.load8_u offset=687 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $while-in2 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 87) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 87) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$10 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 775) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 775) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in1 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (loop $while-in3 (result i32) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in1 - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4101) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $37) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $39) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$7 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $30 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $28 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4108) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 2048) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $28 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $28 - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 4114) - ;; CHECK-NEXT: (i32.const 4109) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (global.get $tempDoublePtr) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2146435072) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2146435072) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once49 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.tee $25 - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (call $_frexp - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $26 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 97) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: (local.tee $17 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (if (result f64) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in54 - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in54 - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $28) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $38) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $38) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in56 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.ge - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const 2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.le - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const -2147483649) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: (i32.trunc_f64_s - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4075) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.convert_i32_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 46) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in56 - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $40) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $41) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 65536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once49 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (if (result f64) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: (f64.const 268435456) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $43) - ;; CHECK-NEXT: (local.get $44) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in60 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.ge - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const 2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (f64.le - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.const -2147483649) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: (i32.trunc_f64_s - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in60 - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.tee $14 - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.convert_i32_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 1e9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in62 - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once63 - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in66 - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $20 - ;; CHECK-NEXT: (call $_bitshift64Shl - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (call $___uremdi3 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.tee $20 - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1000000000) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (call $___udivdi3 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (i32.const 1000000000) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in66 - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once63 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in68 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in68) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in62 - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $31 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (loop $while-in70 (result i32) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once71 - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $34 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 1000000000) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in74 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $34) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in74 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once71 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in70) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once75 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once75 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in78 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in78 - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $31 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $34 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: (i32.const 103) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 9216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in80 - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in80 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4092) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $26 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once81 - ;; CHECK-NEXT: (local.set $35 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (if (result f64) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (local.tee $45 - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 0.5) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 1.5) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (local.get $45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $25 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (f64.const 9007199254740994) - ;; CHECK-NEXT: (f64.const 9007199254740992) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $35) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $28) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $25 - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once81 - ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 999999999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in86 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in86 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 999999999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once81 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in88 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in88 - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $35 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (loop $while-in90 (result i32) - ;; CHECK-NEXT: (block $while-out89 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $26 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out89 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $26 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in90) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $34) - ;; CHECK-NEXT: (block $do-once91 (result i32) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const -5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $19 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $do-once91 - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (local.tee $17 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: (block $do-once93 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $15 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once93) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once93) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in96 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in96 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $28) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $19 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $31 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $35) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in98 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in98 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $15 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: (local.get $28) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 65536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $31) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in102 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once103 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $do-once103 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $32) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $do-once103 - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in106 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in106 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in102) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (i32.const 4143) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in110 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in112 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in112 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in110) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once99 - ;; CHECK-NEXT: (local.set $20 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $26) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in114 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $32) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once115 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once115 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once115 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (i32.const 4143) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (br_if $do-once115 - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in118 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in118 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $27) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in114 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once99 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $24) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $28) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 4135) - ;; CHECK-NEXT: (i32.const 4139) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 4127) - ;; CHECK-NEXT: (i32.const 4131) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$8 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (loop $while-in123 (result i32) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4075) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in123 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_bitshift64Lshr - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L8 - ;; CHECK-NEXT: (block $__rjti$29 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in12 - ;; CHECK-NEXT: (br_if $__rjti$29 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in12 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$29 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__rjto$013 - ;; CHECK-NEXT: (block $__rjti$014 - ;; CHECK-NEXT: (br_if $__rjti$014 - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in315 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2139062144) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2139062144) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 16843009) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in315 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$014) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$013) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (loop $while-in5 (result i32) - ;; CHECK-NEXT: (br_if $label$break$L8 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in5 - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $15 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$8 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in125 - ;; CHECK-NEXT: (block $while-out124 - ;; CHECK-NEXT: (br_if $while-out124 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-out124 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (call $_wctomb - ;; CHECK-NEXT: (local.get $33) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in125 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in127 (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__rjti$7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $__rjti$7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (call $_wctomb - ;; CHECK-NEXT: (local.get $33) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $33) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in127 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const -65537) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 65536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_pad - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$continue$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L343) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in130 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $_pop_arg_336 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in130 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L343) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in132 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $18 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L343) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in132 - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: ) - (func $_printf_core (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local $10 i32) - (local $11 i32) - (local $12 i32) - (local $13 i32) - (local $14 i32) - (local $15 f64) - (local $16 i32) - (local $17 i32) - (local $18 i32) - (local $19 i32) - (local $20 i32) - (local $21 i32) - (local $22 i32) - (local $23 f64) - (local $24 i32) - (local $25 i32) - (local $26 i32) - (local $27 i32) - (local $28 i32) - (local $29 i32) - (local $30 i32) - (local $31 i32) - (local $32 i32) - (local $33 i32) - (local $34 i32) - (local $35 i32) - (local $36 i32) - (local $37 i32) - (local $38 i32) - (local $39 i32) - (local $40 i32) - (local $41 i32) - (local $42 i32) - (local $43 i32) - (local $44 i32) - (local $45 i32) - (local $46 i32) - (local $47 i32) - (local $48 i32) - (local $49 i32) - (local $50 i32) - (local $51 i32) - (local.set $25 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 624) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (local.set $20 - (i32.add - (local.get $25) - (i32.const 16) - ) - ) - (local.set $19 - (local.get $25) - ) - (local.set $36 - (i32.add - (local.get $25) - (i32.const 528) - ) - ) - (local.set $29 - (i32.ne - (local.get $0) - (i32.const 0) - ) - ) - (local.set $39 - (local.tee $26 - (i32.add - (local.tee $5 - (i32.add - (local.get $25) - (i32.const 536) - ) - ) - (i32.const 40) - ) - ) - ) - (local.set $40 - (i32.add - (local.get $5) - (i32.const 39) - ) - ) - (local.set $44 - (i32.add - (local.tee $41 - (i32.add - (local.get $25) - (i32.const 8) - ) - ) - (i32.const 4) - ) - ) - (local.set $34 - (i32.add - (local.tee $5 - (i32.add - (local.get $25) - (i32.const 576) - ) - ) - (i32.const 12) - ) - ) - (local.set $42 - (i32.add - (local.get $5) - (i32.const 11) - ) - ) - (local.set $45 - (i32.sub - (local.tee $28 - (local.get $34) - ) - (local.tee $37 - (local.tee $22 - (i32.add - (local.get $25) - (i32.const 588) - ) - ) - ) - ) - ) - (local.set $46 - (i32.sub - (i32.const -2) - (local.get $37) - ) - ) - (local.set $47 - (i32.add - (local.get $28) - (i32.const 2) - ) - ) - (local.set $49 - (i32.add - (local.tee $48 - (i32.add - (local.get $25) - (i32.const 24) - ) - ) - (i32.const 288) - ) - ) - (local.set $43 - (local.tee $30 - (i32.add - (local.get $22) - (i32.const 9) - ) - ) - ) - (local.set $35 - (i32.add - (local.get $22) - (i32.const 8) - ) - ) - (local.set $16 - (i32.const 0) - ) - (local.set $5 - (local.get $1) - ) - (local.set $10 - (i32.const 0) - ) - (local.set $1 - (i32.const 0) - ) - (block $label$break$L343 - (block $__rjti$9 - (loop $label$continue$L1 - (block $label$break$L1 - (if - (i32.gt_s - (local.get $16) - (i32.const -1) - ) - (local.set $16 - (if (result i32) - (i32.gt_s - (local.get $10) - (i32.sub - (i32.const 2147483647) - (local.get $16) - ) - ) - (block (result i32) - (i32.store - (call $___errno_location) - (i32.const 75) - ) - (i32.const -1) - ) - (i32.add - (local.get $10) - (local.get $16) - ) - ) - ) - ) - (br_if $__rjti$9 - (i32.eqz - (local.tee $7 - (i32.load8_s - (local.get $5) - ) - ) - ) - ) - (local.set $10 - (local.get $5) - ) - (block $label$break$L12 - (block $__rjti$1 - (loop $label$continue$L9 - (block $label$break$L9 - (block $switch-default - (block $switch-case0 - (block $switch-case - (br_table $switch-case0 $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case $switch-default - (i32.shr_s - (i32.shl - (local.get $7) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - (local.set $6 - (local.get $10) - ) - (br $__rjti$1) - ) - (local.set $6 - (local.get $10) - ) - (br $label$break$L9) - ) - (local.set $7 - (i32.load8_s - (local.tee $10 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - ) - ) - (br $label$continue$L9) - ) - ) - (br $label$break$L12) - ) - (loop $while-in - (br_if $label$break$L12 - (i32.ne - (i32.load8_s offset=1 - (local.get $6) - ) - (i32.const 37) - ) - ) - (local.set $10 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - (br_if $while-in - (i32.eq - (i32.load8_s - (local.tee $6 - (i32.add - (local.get $6) - (i32.const 2) - ) - ) - ) - (i32.const 37) - ) - ) - ) - ) - (local.set $7 - (i32.sub - (local.get $10) - (local.get $5) - ) - ) - (if - (local.get $29) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $5) - (local.get $7) - (local.get $0) - ) - ) - ) - ) - (if - (i32.ne - (local.get $10) - (local.get $5) - ) - (block - (local.set $5 - (local.get $6) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - ) - (local.set $8 - (if (result i32) - (i32.lt_u - (local.tee $8 - (i32.add - (local.tee $11 - (i32.load8_s - (local.tee $10 - (i32.add - (local.get $6) - (i32.const 1) - ) - ) - ) - ) - (i32.const -48) - ) - ) - (i32.const 10) - ) - (block (result i32) - (local.set $6 - (i32.load8_s - (local.tee $10 - (select - (i32.add - (local.get $6) - (i32.const 3) - ) - (local.get $10) - (local.tee $11 - (i32.eq - (i32.load8_s offset=2 - (local.get $6) - ) - (i32.const 36) - ) - ) - ) - ) - ) - ) - (local.set $17 - (select - (local.get $8) - (i32.const -1) - (local.get $11) - ) - ) - (select - (i32.const 1) - (local.get $1) - (local.get $11) - ) - ) - (block (result i32) - (local.set $6 - (local.get $11) - ) - (local.set $17 - (i32.const -1) - ) - (local.get $1) - ) - ) - ) - (block $label$break$L25 - (if - (i32.eq - (i32.and - (local.tee $11 - (i32.shr_s - (i32.shl - (local.get $6) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (i32.const -32) - ) - (i32.const 32) - ) - (block - (local.set $1 - (local.get $6) - ) - (local.set $6 - (local.get $11) - ) - (local.set $11 - (i32.const 0) - ) - (loop $while-in4 - (if - (i32.eqz - (i32.and - (i32.shl - (i32.const 1) - (i32.add - (local.get $6) - (i32.const -32) - ) - ) - (i32.const 75913) - ) - ) - (block - (local.set $6 - (local.get $1) - ) - (local.set $1 - (local.get $11) - ) - (br $label$break$L25) - ) - ) - (local.set $11 - (i32.or - (i32.shl - (i32.const 1) - (i32.add - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const -32) - ) - ) - (local.get $11) - ) - ) - (br_if $while-in4 - (i32.eq - (i32.and - (local.tee $6 - (local.tee $1 - (i32.load8_s - (local.tee $10 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - ) - ) - ) - (i32.const -32) - ) - (i32.const 32) - ) - ) - (local.set $6 - (local.get $1) - ) - (local.set $1 - (local.get $11) - ) - ) - ) - (local.set $1 - (i32.const 0) - ) - ) - ) - (block $do-once5 - (if - (i32.eq - (i32.and - (local.get $6) - (i32.const 255) - ) - (i32.const 42) - ) - (block - (local.set $10 - (block $__rjto$0 (result i32) - (block $__rjti$0 - (br_if $__rjti$0 - (i32.ge_u - (local.tee $11 - (i32.add - (i32.load8_s - (local.tee $6 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - ) - (i32.const -48) - ) - ) - (i32.const 10) - ) - ) - (br_if $__rjti$0 - (i32.ne - (i32.load8_s offset=2 - (local.get $10) - ) - (i32.const 36) - ) - ) - (i32.store - (i32.add - (local.get $4) - (i32.shl - (local.get $11) - (i32.const 2) - ) - ) - (i32.const 10) - ) - (drop - (i32.load offset=4 - (local.tee $6 - (i32.add - (local.get $3) - (i32.shl - (i32.add - (i32.load8_s - (local.get $6) - ) - (i32.const -48) - ) - (i32.const 3) - ) - ) - ) - ) - ) - (local.set $8 - (i32.const 1) - ) - (local.set $14 - (i32.load - (local.get $6) - ) - ) - (br $__rjto$0 - (i32.add - (local.get $10) - (i32.const 3) - ) - ) - ) - (if - (local.get $8) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - ) - (if - (i32.eqz - (local.get $29) - ) - (block - (local.set $11 - (local.get $1) - ) - (local.set $10 - (local.get $6) - ) - (local.set $1 - (i32.const 0) - ) - (local.set $14 - (i32.const 0) - ) - (br $do-once5) - ) - ) - (local.set $14 - (i32.load - (local.tee $10 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $10) - (i32.const 4) - ) - ) - (local.set $8 - (i32.const 0) - ) - (local.get $6) - ) - ) - (local.set $11 - (if (result i32) - (i32.lt_s - (local.get $14) - (i32.const 0) - ) - (block (result i32) - (local.set $14 - (i32.sub - (i32.const 0) - (local.get $14) - ) - ) - (i32.or - (local.get $1) - (i32.const 8192) - ) - ) - (local.get $1) - ) - ) - (local.set $1 - (local.get $8) - ) - ) - (if - (i32.lt_u - (local.tee $6 - (i32.add - (i32.shr_s - (i32.shl - (local.get $6) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const -48) - ) - ) - (i32.const 10) - ) - (block - (local.set $11 - (i32.const 0) - ) - (loop $while-in8 - (local.set $6 - (i32.add - (i32.mul - (local.get $11) - (i32.const 10) - ) - (local.get $6) - ) - ) - (if - (i32.lt_u - (local.tee $9 - (i32.add - (i32.load8_s - (local.tee $10 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - ) - (i32.const -48) - ) - ) - (i32.const 10) - ) - (block - (local.set $11 - (local.get $6) - ) - (local.set $6 - (local.get $9) - ) - (br $while-in8) - ) - ) - ) - (if - (i32.lt_s - (local.get $6) - (i32.const 0) - ) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - (block - (local.set $11 - (local.get $1) - ) - (local.set $1 - (local.get $8) - ) - (local.set $14 - (local.get $6) - ) - ) - ) - ) - (block - (local.set $11 - (local.get $1) - ) - (local.set $1 - (local.get $8) - ) - (local.set $14 - (i32.const 0) - ) - ) - ) - ) - ) - (local.set $6 - (block $label$break$L46 (result i32) - (if (result i32) - (i32.eq - (i32.load8_s - (local.get $10) - ) - (i32.const 46) - ) - (block (result i32) - (if - (i32.ne - (local.tee $8 - (i32.load8_s - (local.tee $6 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - ) - ) - (i32.const 42) - ) - (block - (if - (i32.lt_u - (local.tee $9 - (i32.add - (local.get $8) - (i32.const -48) - ) - ) - (i32.const 10) - ) - (block - (local.set $10 - (local.get $6) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $6 - (local.get $9) - ) - ) - (block - (local.set $10 - (local.get $6) - ) - (br $label$break$L46 - (i32.const 0) - ) - ) - ) - (loop $while-in11 - (drop - (br_if $label$break$L46 - (local.tee $6 - (i32.add - (i32.mul - (local.get $8) - (i32.const 10) - ) - (local.get $6) - ) - ) - (i32.ge_u - (local.tee $9 - (i32.add - (i32.load8_s - (local.tee $10 - (i32.add - (local.get $10) - (i32.const 1) - ) - ) - ) - (i32.const -48) - ) - ) - (i32.const 10) - ) - ) - ) - (local.set $8 - (local.get $6) - ) - (local.set $6 - (local.get $9) - ) - (br $while-in11) - ) - ) - ) - (if - (i32.lt_u - (local.tee $8 - (i32.add - (i32.load8_s - (local.tee $6 - (i32.add - (local.get $10) - (i32.const 2) - ) - ) - ) - (i32.const -48) - ) - ) - (i32.const 10) - ) - (if - (i32.eq - (i32.load8_s offset=3 - (local.get $10) - ) - (i32.const 36) - ) - (block - (i32.store - (i32.add - (local.get $4) - (i32.shl - (local.get $8) - (i32.const 2) - ) - ) - (i32.const 10) - ) - (drop - (i32.load offset=4 - (local.tee $6 - (i32.add - (local.get $3) - (i32.shl - (i32.add - (i32.load8_s - (local.get $6) - ) - (i32.const -48) - ) - (i32.const 3) - ) - ) - ) - ) - ) - (local.set $10 - (i32.add - (local.get $10) - (i32.const 4) - ) - ) - (br $label$break$L46 - (i32.load - (local.get $6) - ) - ) - ) - ) - ) - (if - (local.get $1) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - ) - (if (result i32) - (local.get $29) - (block (result i32) - (local.set $8 - (i32.load - (local.tee $10 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $10) - (i32.const 4) - ) - ) - (local.set $10 - (local.get $6) - ) - (local.get $8) - ) - (block (result i32) - (local.set $10 - (local.get $6) - ) - (i32.const 0) - ) - ) - ) - (i32.const -1) - ) - ) - ) - (local.set $8 - (local.get $10) - ) - (local.set $9 - (i32.const 0) - ) - (loop $while-in13 - (if - (i32.gt_u - (local.tee $12 - (i32.add - (i32.load8_s - (local.get $8) - ) - (i32.const -65) - ) - ) - (i32.const 57) - ) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - ) - (local.set $10 - (i32.add - (local.get $8) - (i32.const 1) - ) - ) - (if - (i32.lt_u - (i32.add - (local.tee $12 - (i32.and - (local.tee $13 - (i32.load8_s - (i32.add - (i32.add - (i32.mul - (local.get $9) - (i32.const 58) - ) - (i32.const 3611) - ) - (local.get $12) - ) - ) - ) - (i32.const 255) - ) - ) - (i32.const -1) - ) - (i32.const 8) - ) - (block - (local.set $8 - (local.get $10) - ) - (local.set $9 - (local.get $12) - ) - (br $while-in13) - ) - (local.set $18 - (local.get $8) - ) - ) - ) - (if - (i32.eqz - (i32.and - (local.get $13) - (i32.const 255) - ) - ) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - ) - (local.set $8 - (i32.gt_s - (local.get $17) - (i32.const -1) - ) - ) - (block $__rjto$2 - (block $__rjti$2 - (if - (i32.eq - (i32.and - (local.get $13) - (i32.const 255) - ) - (i32.const 19) - ) - (if - (local.get $8) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - (br $__rjti$2) - ) - (block - (if - (local.get $8) - (block - (i32.store - (i32.add - (local.get $4) - (i32.shl - (local.get $17) - (i32.const 2) - ) - ) - (local.get $12) - ) - (local.set $13 - (i32.load offset=4 - (local.tee $12 - (i32.add - (local.get $3) - (i32.shl - (local.get $17) - (i32.const 3) - ) - ) - ) - ) - ) - (i32.store - (local.tee $8 - (local.get $19) - ) - (i32.load - (local.get $12) - ) - ) - (i32.store offset=4 - (local.get $8) - (local.get $13) - ) - (br $__rjti$2) - ) - ) - (if - (i32.eqz - (local.get $29) - ) - (block - (local.set $16 - (i32.const 0) - ) - (br $label$break$L1) - ) - ) - (call $_pop_arg_336 - (local.get $19) - (local.get $12) - (local.get $2) - ) - ) - ) - (br $__rjto$2) - ) - (if - (i32.eqz - (local.get $29) - ) - (block - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - ) - ) - (local.set $11 - (select - (local.tee $8 - (i32.and - (local.get $11) - (i32.const -65537) - ) - ) - (local.get $11) - (i32.and - (local.get $11) - (i32.const 8192) - ) - ) - ) - (local.set $5 - (block $__rjto$8 (result i32) - (block $__rjti$8 - (block $__rjti$7 - (block $__rjti$6 - (block $__rjti$5 - (block $__rjti$4 - (block $__rjti$3 - (block $switch-default120 - (block $switch-case42 - (block $switch-case41 - (block $switch-case40 - (block $switch-case39 - (block $switch-case38 - (block $switch-case37 - (block $switch-case36 - (block $switch-case34 - (block $switch-case33 - (block $switch-case29 - (block $switch-case28 - (block $switch-case27 - (br_table $switch-case42 $switch-default120 $switch-case40 $switch-default120 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case41 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case29 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case42 $switch-default120 $switch-case37 $switch-case34 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-case34 $switch-default120 $switch-default120 $switch-default120 $switch-case38 $switch-case27 $switch-case33 $switch-case28 $switch-default120 $switch-default120 $switch-case39 $switch-default120 $switch-case36 $switch-default120 $switch-default120 $switch-case29 $switch-default120 - (i32.sub - (local.tee $18 - (select - (i32.and - (local.tee $12 - (i32.load8_s - (local.get $18) - ) - ) - (i32.const -33) - ) - (local.get $12) - (i32.and - (i32.ne - (local.get $9) - (i32.const 0) - ) - (i32.eq - (i32.and - (local.get $12) - (i32.const 15) - ) - (i32.const 3) - ) - ) - ) - ) - (i32.const 65) - ) - ) - ) - (block $switch-default26 - (block $switch-case25 - (block $switch-case24 - (block $switch-case23 - (block $switch-case22 - (block $switch-case21 - (block $switch-case20 - (block $switch-case19 - (br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26 - (local.get $9) - ) - ) - (i32.store - (i32.load - (local.get $19) - ) - (local.get $16) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (i32.store - (i32.load - (local.get $19) - ) - (local.get $16) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (i32.store - (local.tee $5 - (i32.load - (local.get $19) - ) - ) - (local.get $16) - ) - (i32.store offset=4 - (local.get $5) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $16) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (i32.store16 - (i32.load - (local.get $19) - ) - (local.get $16) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (i32.store8 - (i32.load - (local.get $19) - ) - (local.get $16) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (i32.store - (i32.load - (local.get $19) - ) - (local.get $16) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (i32.store - (local.tee $5 - (i32.load - (local.get $19) - ) - ) - (local.get $16) - ) - (i32.store offset=4 - (local.get $5) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $16) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (local.set $7 - (i32.or - (local.get $11) - (i32.const 8) - ) - ) - (local.set $6 - (select - (local.get $6) - (i32.const 8) - (i32.gt_u - (local.get $6) - (i32.const 8) - ) - ) - ) - (local.set $18 - (i32.const 120) - ) - (br $__rjti$3) - ) - (local.set $7 - (local.get $11) - ) - (br $__rjti$3) - ) - (if - (i32.and - (i32.eqz - (local.tee $7 - (i32.load - (local.tee $5 - (local.get $19) - ) - ) - ) - ) - (i32.eqz - (local.tee $8 - (i32.load offset=4 - (local.get $5) - ) - ) - ) - ) - (local.set $8 - (local.get $26) - ) - (block - (local.set $5 - (local.get $7) - ) - (local.set $7 - (local.get $8) - ) - (local.set $8 - (local.get $26) - ) - (loop $while-in32 - (i32.store8 - (local.tee $8 - (i32.add - (local.get $8) - (i32.const -1) - ) - ) - (i32.or - (i32.and - (local.get $5) - (i32.const 7) - ) - (i32.const 48) - ) - ) - (br_if $while-in32 - (i32.eqz - (i32.and - (i32.eqz - (local.tee $5 - (call $_bitshift64Lshr - (local.get $5) - (local.get $7) - (i32.const 3) - ) - ) - ) - (i32.eqz - (local.tee $7 - (global.get $tempRet0) - ) - ) - ) - ) - ) - ) - ) - ) - (local.set $5 - (if (result i32) - (i32.and - (local.get $11) - (i32.const 8) - ) - (block (result i32) - (local.set $7 - (local.get $11) - ) - (local.set $6 - (select - (local.tee $11 - (i32.add - (i32.sub - (local.get $39) - (local.get $8) - ) - (i32.const 1) - ) - ) - (local.get $6) - (i32.lt_s - (local.get $6) - (local.get $11) - ) - ) - ) - (local.get $8) - ) - (block (result i32) - (local.set $7 - (local.get $11) - ) - (local.get $8) - ) - ) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjti$8) - ) - (local.set $5 - (i32.load - (local.tee $7 - (local.get $19) - ) - ) - ) - (if - (i32.lt_s - (local.tee $7 - (i32.load offset=4 - (local.get $7) - ) - ) - (i32.const 0) - ) - (block - (i32.store - (local.tee $8 - (local.get $19) - ) - (local.tee $5 - (call $_i64Subtract - (i32.const 0) - (i32.const 0) - (local.get $5) - (local.get $7) - ) - ) - ) - (i32.store offset=4 - (local.get $8) - (local.tee $7 - (global.get $tempRet0) - ) - ) - (local.set $8 - (i32.const 1) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjti$4) - ) - ) - (local.set $9 - (if (result i32) - (i32.and - (local.get $11) - (i32.const 2048) - ) - (block (result i32) - (local.set $8 - (i32.const 1) - ) - (i32.const 4092) - ) - (block (result i32) - (local.set $8 - (local.tee $9 - (i32.and - (local.get $11) - (i32.const 1) - ) - ) - ) - (select - (i32.const 4093) - (i32.const 4091) - (local.get $9) - ) - ) - ) - ) - (br $__rjti$4) - ) - (local.set $5 - (i32.load - (local.tee $7 - (local.get $19) - ) - ) - ) - (local.set $7 - (i32.load offset=4 - (local.get $7) - ) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjti$4) - ) - (drop - (i32.load offset=4 - (local.tee $5 - (local.get $19) - ) - ) - ) - (i32.store8 - (local.get $40) - (i32.load - (local.get $5) - ) - ) - (local.set $7 - (local.get $40) - ) - (local.set $11 - (local.get $8) - ) - (local.set $12 - (i32.const 1) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjto$8 - (local.get $26) - ) - ) - (local.set $5 - (call $_strerror - (i32.load - (call $___errno_location) - ) - ) - ) - (br $__rjti$5) - ) - (local.set $5 - (select - (local.tee $5 - (i32.load - (local.get $19) - ) - ) - (i32.const 4101) - (local.get $5) - ) - ) - (br $__rjti$5) - ) - (drop - (i32.load offset=4 - (local.tee $5 - (local.get $19) - ) - ) - ) - (i32.store - (local.get $41) - (i32.load - (local.get $5) - ) - ) - (i32.store - (local.get $44) - (i32.const 0) - ) - (i32.store - (local.get $19) - (local.get $41) - ) - (local.set $8 - (i32.const -1) - ) - (br $__rjti$6) - ) - (if - (local.get $6) - (block - (local.set $8 - (local.get $6) - ) - (br $__rjti$6) - ) - (block - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (i32.const 0) - (local.get $11) - ) - (local.set $7 - (i32.const 0) - ) - (br $__rjti$7) - ) - ) - ) - (local.set $15 - (f64.load - (local.get $19) - ) - ) - (i32.store - (local.get $20) - (i32.const 0) - ) - (f64.store - (global.get $tempDoublePtr) - (local.get $15) - ) - (drop - (i32.load - (global.get $tempDoublePtr) - ) - ) - (local.set $31 - (if (result i32) - (i32.lt_s - (i32.load offset=4 - (global.get $tempDoublePtr) - ) - (i32.const 0) - ) - (block (result i32) - (local.set $27 - (i32.const 1) - ) - (local.set $15 - (f64.neg - (local.get $15) - ) - ) - (i32.const 4108) - ) - (if (result i32) - (i32.and - (local.get $11) - (i32.const 2048) - ) - (block (result i32) - (local.set $27 - (i32.const 1) - ) - (i32.const 4111) - ) - (block (result i32) - (local.set $27 - (local.tee $5 - (i32.and - (local.get $11) - (i32.const 1) - ) - ) - ) - (select - (i32.const 4114) - (i32.const 4109) - (local.get $5) - ) - ) - ) - ) - ) - (f64.store - (global.get $tempDoublePtr) - (local.get $15) - ) - (drop - (i32.load - (global.get $tempDoublePtr) - ) - ) - (local.set $7 - (block $do-once49 (result i32) - (if (result i32) - (i32.or - (i32.lt_u - (local.tee $5 - (i32.and - (i32.load offset=4 - (global.get $tempDoublePtr) - ) - (i32.const 2146435072) - ) - ) - (i32.const 2146435072) - ) - (i32.and - (i32.eq - (local.get $5) - (i32.const 2146435072) - ) - (i32.const 0) - ) - ) - (block (result i32) - (if - (local.tee $5 - (f64.ne - (local.tee $23 - (f64.mul - (call $_frexp - (local.get $15) - (local.tee $5 - (local.get $20) - ) - ) - (f64.const 2) - ) - ) - (f64.const 0) - ) - ) - (i32.store - (local.get $20) - (i32.add - (i32.load - (local.get $20) - ) - (i32.const -1) - ) - ) - ) - (if - (i32.eq - (local.tee $24 - (i32.or - (local.get $18) - (i32.const 32) - ) - ) - (i32.const 97) - ) - (block - (local.set $9 - (select - (i32.add - (local.get $31) - (i32.const 9) - ) - (local.get $31) - (local.tee $13 - (i32.and - (local.get $18) - (i32.const 32) - ) - ) - ) - ) - (local.set $15 - (if (result f64) - (i32.or - (i32.gt_u - (local.get $6) - (i32.const 11) - ) - (i32.eqz - (local.tee $5 - (i32.sub - (i32.const 12) - (local.get $6) - ) - ) - ) - ) - (local.get $23) - (block (result f64) - (local.set $15 - (f64.const 8) - ) - (loop $while-in54 - (local.set $15 - (f64.mul - (local.get $15) - (f64.const 16) - ) - ) - (br_if $while-in54 - (local.tee $5 - (i32.add - (local.get $5) - (i32.const -1) - ) - ) - ) - ) - (if (result f64) - (i32.eq - (i32.load8_s - (local.get $9) - ) - (i32.const 45) - ) - (f64.neg - (f64.add - (local.get $15) - (f64.sub - (f64.neg - (local.get $23) - ) - (local.get $15) - ) - ) - ) - (f64.sub - (f64.add - (local.get $23) - (local.get $15) - ) - (local.get $15) - ) - ) - ) - ) - ) - (if - (i32.eq - (local.tee $5 - (call $_fmt_u - (local.tee $5 - (select - (i32.sub - (i32.const 0) - (local.tee $7 - (i32.load - (local.get $20) - ) - ) - ) - (local.get $7) - (i32.lt_s - (local.get $7) - (i32.const 0) - ) - ) - ) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $5) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - (local.get $34) - ) - ) - (local.get $34) - ) - (block - (i32.store8 - (local.get $42) - (i32.const 48) - ) - (local.set $5 - (local.get $42) - ) - ) - ) - (local.set $12 - (i32.or - (local.get $27) - (i32.const 2) - ) - ) - (i32.store8 - (i32.add - (local.get $5) - (i32.const -1) - ) - (i32.add - (i32.and - (i32.shr_s - (local.get $7) - (i32.const 31) - ) - (i32.const 2) - ) - (i32.const 43) - ) - ) - (i32.store8 - (local.tee $8 - (i32.add - (local.get $5) - (i32.const -2) - ) - ) - (i32.add - (local.get $18) - (i32.const 15) - ) - ) - (local.set $18 - (i32.lt_s - (local.get $6) - (i32.const 1) - ) - ) - (local.set $17 - (i32.eqz - (i32.and - (local.get $11) - (i32.const 8) - ) - ) - ) - (local.set $5 - (local.get $22) - ) - (loop $while-in56 - (i32.store8 - (local.get $5) - (i32.or - (i32.load8_u - (i32.add - (local.tee $7 - (call $f64-to-int - (local.get $15) - ) - ) - (i32.const 4075) - ) - ) - (local.get $13) - ) - ) - (local.set $15 - (f64.mul - (f64.sub - (local.get $15) - (f64.convert_i32_s - (local.get $7) - ) - ) - (f64.const 16) - ) - ) - (local.set $5 - (block $do-once57 (result i32) - (if (result i32) - (i32.eq - (i32.sub - (local.tee $7 - (i32.add - (local.get $5) - (i32.const 1) - ) - ) - (local.get $37) - ) - (i32.const 1) - ) - (block (result i32) - (drop - (br_if $do-once57 - (local.get $7) - (i32.and - (local.get $17) - (i32.and - (local.get $18) - (f64.eq - (local.get $15) - (f64.const 0) - ) - ) - ) - ) - ) - (i32.store8 - (local.get $7) - (i32.const 46) - ) - (i32.add - (local.get $5) - (i32.const 2) - ) - ) - (local.get $7) - ) - ) - ) - (br_if $while-in56 - (f64.ne - (local.get $15) - (f64.const 0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.tee $7 - (i32.add - (local.tee $6 - (select - (i32.sub - (i32.add - (local.get $47) - (local.get $6) - ) - (local.get $8) - ) - (i32.add - (i32.sub - (local.get $45) - (local.get $8) - ) - (local.get $5) - ) - (i32.and - (i32.ne - (local.get $6) - (i32.const 0) - ) - (i32.lt_s - (i32.add - (local.get $46) - (local.get $5) - ) - (local.get $6) - ) - ) - ) - ) - (local.get $12) - ) - ) - (local.get $11) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $9) - (local.get $12) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (local.get $14) - (local.get $7) - (i32.xor - (local.get $11) - (i32.const 65536) - ) - ) - (local.set $5 - (i32.sub - (local.get $5) - (local.get $37) - ) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $22) - (local.get $5) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (i32.sub - (local.get $6) - (i32.add - (local.get $5) - (local.tee $5 - (i32.sub - (local.get $28) - (local.get $8) - ) - ) - ) - ) - (i32.const 0) - (i32.const 0) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $8) - (local.get $5) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.get $7) - (i32.xor - (local.get $11) - (i32.const 8192) - ) - ) - (br $do-once49 - (select - (local.get $14) - (local.get $7) - (i32.lt_s - (local.get $7) - (local.get $14) - ) - ) - ) - ) - ) - (local.set $15 - (if (result f64) - (local.get $5) - (block (result f64) - (i32.store - (local.get $20) - (local.tee $5 - (i32.add - (i32.load - (local.get $20) - ) - (i32.const -28) - ) - ) - ) - (f64.mul - (local.get $23) - (f64.const 268435456) - ) - ) - (block (result f64) - (local.set $5 - (i32.load - (local.get $20) - ) - ) - (local.get $23) - ) - ) - ) - (local.set $7 - (local.tee $8 - (select - (local.get $48) - (local.get $49) - (i32.lt_s - (local.get $5) - (i32.const 0) - ) - ) - ) - ) - (loop $while-in60 - (i32.store - (local.get $7) - (local.tee $5 - (call $f64-to-int - (local.get $15) - ) - ) - ) - (local.set $7 - (i32.add - (local.get $7) - (i32.const 4) - ) - ) - (br_if $while-in60 - (f64.ne - (local.tee $15 - (f64.mul - (f64.sub - (local.get $15) - (f64.convert_i32_u - (local.get $5) - ) - ) - (f64.const 1e9) - ) - ) - (f64.const 0) - ) - ) - ) - (if - (i32.gt_s - (local.tee $9 - (i32.load - (local.get $20) - ) - ) - (i32.const 0) - ) - (block - (local.set $5 - (local.get $8) - ) - (loop $while-in62 - (local.set $13 - (select - (i32.const 29) - (local.get $9) - (i32.gt_s - (local.get $9) - (i32.const 29) - ) - ) - ) - (block $do-once63 - (if - (i32.ge_u - (local.tee $9 - (i32.add - (local.get $7) - (i32.const -4) - ) - ) - (local.get $5) - ) - (block - (local.set $12 - (i32.const 0) - ) - (loop $while-in66 - (i32.store - (local.get $9) - (call $___uremdi3 - (local.tee $12 - (call $_i64Add - (call $_bitshift64Shl - (i32.load - (local.get $9) - ) - (i32.const 0) - (local.get $13) - ) - (global.get $tempRet0) - (local.get $12) - (i32.const 0) - ) - ) - (local.tee $17 - (global.get $tempRet0) - ) - (i32.const 1000000000) - (i32.const 0) - ) - ) - (local.set $12 - (call $___udivdi3 - (local.get $12) - (local.get $17) - (i32.const 1000000000) - (i32.const 0) - ) - ) - (br_if $while-in66 - (i32.ge_u - (local.tee $9 - (i32.add - (local.get $9) - (i32.const -4) - ) - ) - (local.get $5) - ) - ) - ) - (br_if $do-once63 - (i32.eqz - (local.get $12) - ) - ) - (i32.store - (local.tee $5 - (i32.add - (local.get $5) - (i32.const -4) - ) - ) - (local.get $12) - ) - ) - ) - ) - (loop $while-in68 - (if - (i32.gt_u - (local.get $7) - (local.get $5) - ) - (if - (i32.eqz - (i32.load - (local.tee $9 - (i32.add - (local.get $7) - (i32.const -4) - ) - ) - ) - ) - (block - (local.set $7 - (local.get $9) - ) - (br $while-in68) - ) - ) - ) - ) - (i32.store - (local.get $20) - (local.tee $9 - (i32.sub - (i32.load - (local.get $20) - ) - (local.get $13) - ) - ) - ) - (br_if $while-in62 - (i32.gt_s - (local.get $9) - (i32.const 0) - ) - ) - ) - ) - (local.set $5 - (local.get $8) - ) - ) - (local.set $17 - (select - (i32.const 6) - (local.get $6) - (i32.lt_s - (local.get $6) - (i32.const 0) - ) - ) - ) - (if - (i32.lt_s - (local.get $9) - (i32.const 0) - ) - (block - (local.set $21 - (i32.add - (call $i32s-div - (i32.add - (local.get $17) - (i32.const 25) - ) - (i32.const 9) - ) - (i32.const 1) - ) - ) - (local.set $32 - (i32.eq - (local.get $24) - (i32.const 102) - ) - ) - (local.set $6 - (local.get $5) - ) - (local.set $5 - (local.get $7) - ) - (loop $while-in70 - (local.set $13 - (select - (i32.const 9) - (local.tee $7 - (i32.sub - (i32.const 0) - (local.get $9) - ) - ) - (i32.gt_s - (local.get $7) - (i32.const 9) - ) - ) - ) - (block $do-once71 - (if - (i32.lt_u - (local.get $6) - (local.get $5) - ) - (block - (local.set $12 - (i32.add - (i32.shl - (i32.const 1) - (local.get $13) - ) - (i32.const -1) - ) - ) - (local.set $38 - (i32.shr_u - (i32.const 1000000000) - (local.get $13) - ) - ) - (local.set $9 - (i32.const 0) - ) - (local.set $7 - (local.get $6) - ) - (loop $while-in74 - (i32.store - (local.get $7) - (i32.add - (i32.shr_u - (local.tee $33 - (i32.load - (local.get $7) - ) - ) - (local.get $13) - ) - (local.get $9) - ) - ) - (local.set $9 - (i32.mul - (i32.and - (local.get $33) - (local.get $12) - ) - (local.get $38) - ) - ) - (br_if $while-in74 - (i32.lt_u - (local.tee $7 - (i32.add - (local.get $7) - (i32.const 4) - ) - ) - (local.get $5) - ) - ) - ) - (local.set $7 - (select - (local.get $6) - (i32.add - (local.get $6) - (i32.const 4) - ) - (i32.load - (local.get $6) - ) - ) - ) - (br_if $do-once71 - (i32.eqz - (local.get $9) - ) - ) - (i32.store - (local.get $5) - (local.get $9) - ) - (local.set $5 - (i32.add - (local.get $5) - (i32.const 4) - ) - ) - ) - (local.set $7 - (select - (local.get $6) - (i32.add - (local.get $6) - (i32.const 4) - ) - (i32.load - (local.get $6) - ) - ) - ) - ) - ) - (local.set $12 - (select - (i32.add - (local.tee $6 - (select - (local.get $8) - (local.get $7) - (local.get $32) - ) - ) - (i32.shl - (local.get $21) - (i32.const 2) - ) - ) - (local.get $5) - (i32.gt_s - (i32.shr_s - (i32.sub - (local.get $5) - (local.get $6) - ) - (i32.const 2) - ) - (local.get $21) - ) - ) - ) - (i32.store - (local.get $20) - (local.tee $9 - (i32.add - (i32.load - (local.get $20) - ) - (local.get $13) - ) - ) - ) - (if - (i32.lt_s - (local.get $9) - (i32.const 0) - ) - (block - (local.set $6 - (local.get $7) - ) - (local.set $5 - (local.get $12) - ) - (br $while-in70) - ) - (block - (local.set $5 - (local.get $7) - ) - (local.set $9 - (local.get $12) - ) - ) - ) - ) - ) - (local.set $9 - (local.get $7) - ) - ) - (local.set $21 - (local.get $8) - ) - (block $do-once75 - (if - (i32.lt_u - (local.get $5) - (local.get $9) - ) - (block - (local.set $7 - (i32.mul - (i32.shr_s - (i32.sub - (local.get $21) - (local.get $5) - ) - (i32.const 2) - ) - (i32.const 9) - ) - ) - (br_if $do-once75 - (i32.lt_u - (local.tee $12 - (i32.load - (local.get $5) - ) - ) - (i32.const 10) - ) - ) - (local.set $6 - (i32.const 10) - ) - (loop $while-in78 - (local.set $7 - (i32.add - (local.get $7) - (i32.const 1) - ) - ) - (br_if $while-in78 - (i32.ge_u - (local.get $12) - (local.tee $6 - (i32.mul - (local.get $6) - (i32.const 10) - ) - ) - ) - ) - ) - ) - (local.set $7 - (i32.const 0) - ) - ) - ) - (local.set $5 - (if (result i32) - (i32.lt_s - (local.tee $6 - (i32.add - (i32.sub - (local.get $17) - (select - (local.get $7) - (i32.const 0) - (i32.ne - (local.get $24) - (i32.const 102) - ) - ) - ) - (i32.shr_s - (i32.shl - (i32.and - (local.tee $32 - (i32.ne - (local.get $17) - (i32.const 0) - ) - ) - (local.tee $38 - (i32.eq - (local.get $24) - (i32.const 103) - ) - ) - ) - (i32.const 31) - ) - (i32.const 31) - ) - ) - ) - (i32.add - (i32.mul - (i32.shr_s - (i32.sub - (local.get $9) - (local.get $21) - ) - (i32.const 2) - ) - (i32.const 9) - ) - (i32.const -9) - ) - ) - (block (result i32) - (local.set $13 - (call $i32s-div - (local.tee $6 - (i32.add - (local.get $6) - (i32.const 9216) - ) - ) - (i32.const 9) - ) - ) - (if - (i32.lt_s - (local.tee $6 - (i32.add - (if (result i32) - (local.tee $12 - (i32.const 9) - ) - (i32.rem_s - (local.get $6) - (local.get $12) - ) - (i32.const 0) - ) - (i32.const 1) - ) - ) - (i32.const 9) - ) - (block - (local.set $12 - (i32.const 10) - ) - (loop $while-in80 - (local.set $12 - (i32.mul - (local.get $12) - (i32.const 10) - ) - ) - (br_if $while-in80 - (i32.ne - (local.tee $6 - (i32.add - (local.get $6) - (i32.const 1) - ) - ) - (i32.const 9) - ) - ) - ) - ) - (local.set $12 - (i32.const 10) - ) - ) - (local.set $13 - (call $i32u-rem - (local.tee $24 - (i32.load - (local.tee $6 - (i32.add - (i32.add - (local.get $8) - (i32.shl - (local.get $13) - (i32.const 2) - ) - ) - (i32.const -4092) - ) - ) - ) - ) - (local.get $12) - ) - ) - (block $do-once81 - (if - (i32.eqz - (i32.and - (local.tee $33 - (i32.eq - (i32.add - (local.get $6) - (i32.const 4) - ) - (local.get $9) - ) - ) - (i32.eqz - (local.get $13) - ) - ) - ) - (block - (local.set $50 - (call $i32u-div - (local.get $24) - (local.get $12) - ) - ) - (local.set $15 - (if (result f64) - (i32.lt_u - (local.get $13) - (local.tee $51 - (call $i32s-div - (local.get $12) - (i32.const 2) - ) - ) - ) - (f64.const 0.5) - (select - (f64.const 1) - (f64.const 1.5) - (i32.and - (local.get $33) - (i32.eq - (local.get $13) - (local.get $51) - ) - ) - ) - ) - ) - (local.set $23 - (select - (f64.const 9007199254740994) - (f64.const 9007199254740992) - (i32.and - (local.get $50) - (i32.const 1) - ) - ) - ) - (block $do-once83 - (if - (local.get $27) - (block - (br_if $do-once83 - (i32.ne - (i32.load8_s - (local.get $31) - ) - (i32.const 45) - ) - ) - (local.set $23 - (f64.neg - (local.get $23) - ) - ) - (local.set $15 - (f64.neg - (local.get $15) - ) - ) - ) - ) - ) - (i32.store - (local.get $6) - (local.tee $13 - (i32.sub - (local.get $24) - (local.get $13) - ) - ) - ) - (br_if $do-once81 - (f64.eq - (f64.add - (local.get $23) - (local.get $15) - ) - (local.get $23) - ) - ) - (i32.store - (local.get $6) - (local.tee $7 - (i32.add - (local.get $13) - (local.get $12) - ) - ) - ) - (if - (i32.gt_u - (local.get $7) - (i32.const 999999999) - ) - (loop $while-in86 - (i32.store - (local.get $6) - (i32.const 0) - ) - (if - (i32.lt_u - (local.tee $6 - (i32.add - (local.get $6) - (i32.const -4) - ) - ) - (local.get $5) - ) - (i32.store - (local.tee $5 - (i32.add - (local.get $5) - (i32.const -4) - ) - ) - (i32.const 0) - ) - ) - (i32.store - (local.get $6) - (local.tee $7 - (i32.add - (i32.load - (local.get $6) - ) - (i32.const 1) - ) - ) - ) - (br_if $while-in86 - (i32.gt_u - (local.get $7) - (i32.const 999999999) - ) - ) - ) - ) - (local.set $7 - (i32.mul - (i32.shr_s - (i32.sub - (local.get $21) - (local.get $5) - ) - (i32.const 2) - ) - (i32.const 9) - ) - ) - (br_if $do-once81 - (i32.lt_u - (local.tee $13 - (i32.load - (local.get $5) - ) - ) - (i32.const 10) - ) - ) - (local.set $12 - (i32.const 10) - ) - (loop $while-in88 - (local.set $7 - (i32.add - (local.get $7) - (i32.const 1) - ) - ) - (br_if $while-in88 - (i32.ge_u - (local.get $13) - (local.tee $12 - (i32.mul - (local.get $12) - (i32.const 10) - ) - ) - ) - ) - ) - ) - ) - ) - (local.set $12 - (local.get $5) - ) - (local.set $13 - (local.get $7) - ) - (select - (local.tee $5 - (i32.add - (local.get $6) - (i32.const 4) - ) - ) - (local.get $9) - (i32.gt_u - (local.get $9) - (local.get $5) - ) - ) - ) - (block (result i32) - (local.set $12 - (local.get $5) - ) - (local.set $13 - (local.get $7) - ) - (local.get $9) - ) - ) - ) - (local.set $33 - (i32.sub - (i32.const 0) - (local.get $13) - ) - ) - (loop $while-in90 - (block $while-out89 - (if - (i32.le_u - (local.get $5) - (local.get $12) - ) - (block - (local.set $24 - (i32.const 0) - ) - (local.set $9 - (local.get $5) - ) - (br $while-out89) - ) - ) - (if - (i32.load - (local.tee $7 - (i32.add - (local.get $5) - (i32.const -4) - ) - ) - ) - (block - (local.set $24 - (i32.const 1) - ) - (local.set $9 - (local.get $5) - ) - ) - (block - (local.set $5 - (local.get $7) - ) - (br $while-in90) - ) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.tee $13 - (i32.add - (i32.add - (i32.add - (i32.add - (local.get $27) - (i32.const 1) - ) - (local.tee $5 - (block $do-once91 (result i32) - (if (result i32) - (local.get $38) - (block (result i32) - (local.set $7 - (if (result i32) - (i32.and - (i32.gt_s - (local.tee $5 - (i32.add - (i32.xor - (local.get $32) - (i32.const 1) - ) - (local.get $17) - ) - ) - (local.get $13) - ) - (i32.gt_s - (local.get $13) - (i32.const -5) - ) - ) - (block (result i32) - (local.set $17 - (i32.sub - (i32.add - (local.get $5) - (i32.const -1) - ) - (local.get $13) - ) - ) - (i32.add - (local.get $18) - (i32.const -1) - ) - ) - (block (result i32) - (local.set $17 - (i32.add - (local.get $5) - (i32.const -1) - ) - ) - (i32.add - (local.get $18) - (i32.const -2) - ) - ) - ) - ) - (if - (local.tee $5 - (i32.and - (local.get $11) - (i32.const 8) - ) - ) - (block - (local.set $21 - (local.get $5) - ) - (br $do-once91 - (local.get $17) - ) - ) - ) - (block $do-once93 - (if - (local.get $24) - (block - (if - (i32.eqz - (local.tee $18 - (i32.load - (i32.add - (local.get $9) - (i32.const -4) - ) - ) - ) - ) - (block - (local.set $5 - (i32.const 9) - ) - (br $do-once93) - ) - ) - (if - (call $i32u-rem - (local.get $18) - (i32.const 10) - ) - (block - (local.set $5 - (i32.const 0) - ) - (br $do-once93) - ) - (block - (local.set $6 - (i32.const 10) - ) - (local.set $5 - (i32.const 0) - ) - ) - ) - (loop $while-in96 - (local.set $5 - (i32.add - (local.get $5) - (i32.const 1) - ) - ) - (br_if $while-in96 - (i32.eqz - (call $i32u-rem - (local.get $18) - (local.tee $6 - (i32.mul - (local.get $6) - (i32.const 10) - ) - ) - ) - ) - ) - ) - ) - (local.set $5 - (i32.const 9) - ) - ) - ) - (local.set $6 - (i32.add - (i32.mul - (i32.shr_s - (i32.sub - (local.get $9) - (local.get $21) - ) - (i32.const 2) - ) - (i32.const 9) - ) - (i32.const -9) - ) - ) - (if (result i32) - (i32.eq - (i32.or - (local.get $7) - (i32.const 32) - ) - (i32.const 102) - ) - (block (result i32) - (local.set $21 - (i32.const 0) - ) - (select - (local.get $17) - (local.tee $5 - (select - (i32.const 0) - (local.tee $5 - (i32.sub - (local.get $6) - (local.get $5) - ) - ) - (i32.lt_s - (local.get $5) - (i32.const 0) - ) - ) - ) - (i32.lt_s - (local.get $17) - (local.get $5) - ) - ) - ) - (block (result i32) - (local.set $21 - (i32.const 0) - ) - (select - (local.get $17) - (local.tee $5 - (select - (i32.const 0) - (local.tee $5 - (i32.sub - (i32.add - (local.get $6) - (local.get $13) - ) - (local.get $5) - ) - ) - (i32.lt_s - (local.get $5) - (i32.const 0) - ) - ) - ) - (i32.lt_s - (local.get $17) - (local.get $5) - ) - ) - ) - ) - ) - (block (result i32) - (local.set $21 - (i32.and - (local.get $11) - (i32.const 8) - ) - ) - (local.set $7 - (local.get $18) - ) - (local.get $17) - ) - ) - ) - ) - ) - (i32.ne - (local.tee $32 - (i32.or - (local.get $5) - (local.get $21) - ) - ) - (i32.const 0) - ) - ) - (if (result i32) - (local.tee $17 - (i32.eq - (i32.or - (local.get $7) - (i32.const 32) - ) - (i32.const 102) - ) - ) - (block (result i32) - (local.set $18 - (i32.const 0) - ) - (select - (local.get $13) - (i32.const 0) - (i32.gt_s - (local.get $13) - (i32.const 0) - ) - ) - ) - (block (result i32) - (if - (i32.lt_s - (i32.sub - (local.get $28) - (local.tee $6 - (call $_fmt_u - (local.tee $6 - (select - (local.get $33) - (local.get $13) - (i32.lt_s - (local.get $13) - (i32.const 0) - ) - ) - ) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $6) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - (local.get $34) - ) - ) - ) - (i32.const 2) - ) - (loop $while-in98 - (i32.store8 - (local.tee $6 - (i32.add - (local.get $6) - (i32.const -1) - ) - ) - (i32.const 48) - ) - (br_if $while-in98 - (i32.lt_s - (i32.sub - (local.get $28) - (local.get $6) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.store8 - (i32.add - (local.get $6) - (i32.const -1) - ) - (i32.add - (i32.and - (i32.shr_s - (local.get $13) - (i32.const 31) - ) - (i32.const 2) - ) - (i32.const 43) - ) - ) - (i32.store8 - (local.tee $6 - (i32.add - (local.get $6) - (i32.const -2) - ) - ) - (local.get $7) - ) - (local.set $18 - (local.get $6) - ) - (i32.sub - (local.get $28) - (local.get $6) - ) - ) - ) - ) - ) - (local.get $11) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $31) - (local.get $27) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (local.get $14) - (local.get $13) - (i32.xor - (local.get $11) - (i32.const 65536) - ) - ) - (block $do-once99 - (if - (local.get $17) - (block - (local.set $6 - (local.tee $12 - (select - (local.get $8) - (local.get $12) - (i32.gt_u - (local.get $12) - (local.get $8) - ) - ) - ) - ) - (loop $while-in102 - (local.set $7 - (call $_fmt_u - (i32.load - (local.get $6) - ) - (i32.const 0) - (local.get $30) - ) - ) - (block $do-once103 - (if - (i32.eq - (local.get $6) - (local.get $12) - ) - (block - (br_if $do-once103 - (i32.ne - (local.get $7) - (local.get $30) - ) - ) - (i32.store8 - (local.get $35) - (i32.const 48) - ) - (local.set $7 - (local.get $35) - ) - ) - (block - (br_if $do-once103 - (i32.le_u - (local.get $7) - (local.get $22) - ) - ) - (loop $while-in106 - (i32.store8 - (local.tee $7 - (i32.add - (local.get $7) - (i32.const -1) - ) - ) - (i32.const 48) - ) - (br_if $while-in106 - (i32.gt_u - (local.get $7) - (local.get $22) - ) - ) - ) - ) - ) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $7) - (i32.sub - (local.get $43) - (local.get $7) - ) - (local.get $0) - ) - ) - ) - (if - (i32.le_u - (local.tee $7 - (i32.add - (local.get $6) - (i32.const 4) - ) - ) - (local.get $8) - ) - (block - (local.set $6 - (local.get $7) - ) - (br $while-in102) - ) - ) - ) - (block $do-once107 - (if - (local.get $32) - (block - (br_if $do-once107 - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (i32.const 4143) - (i32.const 1) - (local.get $0) - ) - ) - ) - ) - ) - (if - (i32.and - (i32.gt_s - (local.get $5) - (i32.const 0) - ) - (i32.lt_u - (local.get $7) - (local.get $9) - ) - ) - (loop $while-in110 - (if - (i32.gt_u - (local.tee $6 - (call $_fmt_u - (i32.load - (local.get $7) - ) - (i32.const 0) - (local.get $30) - ) - ) - (local.get $22) - ) - (loop $while-in112 - (i32.store8 - (local.tee $6 - (i32.add - (local.get $6) - (i32.const -1) - ) - ) - (i32.const 48) - ) - (br_if $while-in112 - (i32.gt_u - (local.get $6) - (local.get $22) - ) - ) - ) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $6) - (select - (i32.const 9) - (local.get $5) - (i32.gt_s - (local.get $5) - (i32.const 9) - ) - ) - (local.get $0) - ) - ) - ) - (local.set $6 - (i32.add - (local.get $5) - (i32.const -9) - ) - ) - (if - (i32.and - (i32.gt_s - (local.get $5) - (i32.const 9) - ) - (i32.lt_u - (local.tee $7 - (i32.add - (local.get $7) - (i32.const 4) - ) - ) - (local.get $9) - ) - ) - (block - (local.set $5 - (local.get $6) - ) - (br $while-in110) - ) - (local.set $5 - (local.get $6) - ) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (i32.add - (local.get $5) - (i32.const 9) - ) - (i32.const 9) - (i32.const 0) - ) - ) - (block - (local.set $9 - (select - (local.get $9) - (i32.add - (local.get $12) - (i32.const 4) - ) - (local.get $24) - ) - ) - (if - (i32.gt_s - (local.get $5) - (i32.const -1) - ) - (block - (local.set $17 - (i32.eqz - (local.get $21) - ) - ) - (local.set $6 - (local.get $12) - ) - (local.set $7 - (local.get $5) - ) - (loop $while-in114 - (if - (i32.eq - (local.tee $5 - (call $_fmt_u - (i32.load - (local.get $6) - ) - (i32.const 0) - (local.get $30) - ) - ) - (local.get $30) - ) - (block - (i32.store8 - (local.get $35) - (i32.const 48) - ) - (local.set $5 - (local.get $35) - ) - ) - ) - (block $do-once115 - (if - (i32.eq - (local.get $6) - (local.get $12) - ) - (block - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $5) - (i32.const 1) - (local.get $0) - ) - ) - ) - (local.set $5 - (i32.add - (local.get $5) - (i32.const 1) - ) - ) - (br_if $do-once115 - (i32.and - (local.get $17) - (i32.lt_s - (local.get $7) - (i32.const 1) - ) - ) - ) - (br_if $do-once115 - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (i32.const 4143) - (i32.const 1) - (local.get $0) - ) - ) - ) - (block - (br_if $do-once115 - (i32.le_u - (local.get $5) - (local.get $22) - ) - ) - (loop $while-in118 - (i32.store8 - (local.tee $5 - (i32.add - (local.get $5) - (i32.const -1) - ) - ) - (i32.const 48) - ) - (br_if $while-in118 - (i32.gt_u - (local.get $5) - (local.get $22) - ) - ) - ) - ) - ) - ) - (local.set $8 - (i32.sub - (local.get $43) - (local.get $5) - ) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $5) - (select - (local.get $8) - (local.get $7) - (i32.gt_s - (local.get $7) - (local.get $8) - ) - ) - (local.get $0) - ) - ) - ) - (br_if $while-in114 - (i32.and - (i32.lt_u - (local.tee $6 - (i32.add - (local.get $6) - (i32.const 4) - ) - ) - (local.get $9) - ) - (i32.gt_s - (local.tee $7 - (i32.sub - (local.get $7) - (local.get $8) - ) - ) - (i32.const -1) - ) - ) - ) - (local.set $5 - (local.get $7) - ) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (i32.add - (local.get $5) - (i32.const 18) - ) - (i32.const 18) - (i32.const 0) - ) - (br_if $do-once99 - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $18) - (i32.sub - (local.get $28) - (local.get $18) - ) - (local.get $0) - ) - ) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.get $13) - (i32.xor - (local.get $11) - (i32.const 8192) - ) - ) - (select - (local.get $14) - (local.get $13) - (i32.lt_s - (local.get $13) - (local.get $14) - ) - ) - ) - (block (result i32) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.tee $7 - (i32.add - (local.tee $9 - (select - (i32.const 0) - (local.get $27) - (local.tee $6 - (i32.or - (f64.ne - (local.get $15) - (local.get $15) - ) - (i32.const 0) - ) - ) - ) - ) - (i32.const 3) - ) - ) - (local.get $8) - ) - (if - (i32.eqz - (i32.and - (local.tee $5 - (i32.load - (local.get $0) - ) - ) - (i32.const 32) - ) - ) - (block - (drop - (call $___fwritex - (local.get $31) - (local.get $9) - (local.get $0) - ) - ) - (local.set $5 - (i32.load - (local.get $0) - ) - ) - ) - ) - (local.set $6 - (select - (select - (i32.const 4135) - (i32.const 4139) - (local.tee $8 - (i32.ne - (i32.and - (local.get $18) - (i32.const 32) - ) - (i32.const 0) - ) - ) - ) - (select - (i32.const 4127) - (i32.const 4131) - (local.get $8) - ) - (local.get $6) - ) - ) - (if - (i32.eqz - (i32.and - (local.get $5) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $6) - (i32.const 3) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.get $7) - (i32.xor - (local.get $11) - (i32.const 8192) - ) - ) - (select - (local.get $14) - (local.get $7) - (i32.lt_s - (local.get $7) - (local.get $14) - ) - ) - ) - ) - ) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $7) - ) - (br $label$continue$L1) - ) - (local.set $7 - (local.get $5) - ) - (local.set $12 - (local.get $6) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjto$8 - (local.get $26) - ) - ) - (local.set $9 - (i32.and - (local.get $18) - (i32.const 32) - ) - ) - (if - (i32.and - (i32.eqz - (local.tee $8 - (i32.load - (local.tee $5 - (local.get $19) - ) - ) - ) - ) - (i32.eqz - (local.tee $11 - (i32.load offset=4 - (local.get $5) - ) - ) - ) - ) - (block - (local.set $5 - (local.get $26) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjti$8) - ) - (block - (local.set $5 - (local.get $8) - ) - (local.set $8 - (local.get $26) - ) - (loop $while-in123 - (i32.store8 - (local.tee $8 - (i32.add - (local.get $8) - (i32.const -1) - ) - ) - (i32.or - (i32.load8_u - (i32.add - (i32.and - (local.get $5) - (i32.const 15) - ) - (i32.const 4075) - ) - ) - (local.get $9) - ) - ) - (br_if $while-in123 - (i32.eqz - (i32.and - (i32.eqz - (local.tee $5 - (call $_bitshift64Lshr - (local.get $5) - (local.get $11) - (i32.const 4) - ) - ) - ) - (i32.eqz - (local.tee $11 - (global.get $tempRet0) - ) - ) - ) - ) - ) - (local.set $5 - (local.get $8) - ) - ) - (local.set $8 - (if (result i32) - (i32.or - (i32.eqz - (i32.and - (local.get $7) - (i32.const 8) - ) - ) - (i32.and - (i32.eqz - (i32.load - (local.tee $11 - (local.get $19) - ) - ) - ) - (i32.eqz - (i32.load offset=4 - (local.get $11) - ) - ) - ) - ) - (block (result i32) - (local.set $9 - (i32.const 4091) - ) - (i32.const 0) - ) - (block (result i32) - (local.set $9 - (i32.add - (i32.shr_s - (local.get $18) - (i32.const 4) - ) - (i32.const 4091) - ) - ) - (i32.const 2) - ) - ) - ) - (br $__rjti$8) - ) - ) - ) - (local.set $5 - (call $_fmt_u - (local.get $5) - (local.get $7) - (local.get $26) - ) - ) - (local.set $7 - (local.get $11) - ) - (br $__rjti$8) - ) - (local.set $18 - (i32.eqz - (local.tee $13 - (call $_memchr - (local.get $5) - (i32.const 0) - (local.get $6) - ) - ) - ) - ) - (local.set $7 - (local.get $5) - ) - (local.set $11 - (local.get $8) - ) - (local.set $12 - (select - (local.get $6) - (i32.sub - (local.get $13) - (local.get $5) - ) - (local.get $18) - ) - ) - (local.set $8 - (i32.const 0) - ) - (local.set $9 - (i32.const 4091) - ) - (br $__rjto$8 - (select - (i32.add - (local.get $5) - (local.get $6) - ) - (local.get $13) - (local.get $18) - ) - ) - ) - (local.set $5 - (i32.const 0) - ) - (local.set $7 - (i32.const 0) - ) - (local.set $6 - (i32.load - (local.get $19) - ) - ) - (loop $while-in125 - (block $while-out124 - (br_if $while-out124 - (i32.eqz - (local.tee $9 - (i32.load - (local.get $6) - ) - ) - ) - ) - (br_if $while-out124 - (i32.or - (i32.lt_s - (local.tee $7 - (call $_wctomb - (local.get $36) - (local.get $9) - ) - ) - (i32.const 0) - ) - (i32.gt_u - (local.get $7) - (i32.sub - (local.get $8) - (local.get $5) - ) - ) - ) - ) - (local.set $6 - (i32.add - (local.get $6) - (i32.const 4) - ) - ) - (br_if $while-in125 - (i32.gt_u - (local.get $8) - (local.tee $5 - (i32.add - (local.get $7) - (local.get $5) - ) - ) - ) - ) - ) - ) - (if - (i32.lt_s - (local.get $7) - (i32.const 0) - ) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L1) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.get $5) - (local.get $11) - ) - (if - (local.get $5) - (block - (local.set $6 - (i32.const 0) - ) - (local.set $7 - (i32.load - (local.get $19) - ) - ) - (loop $while-in127 - (if - (i32.eqz - (local.tee $8 - (i32.load - (local.get $7) - ) - ) - ) - (block - (local.set $7 - (local.get $5) - ) - (br $__rjti$7) - ) - ) - (if - (i32.gt_s - (local.tee $6 - (i32.add - (local.tee $8 - (call $_wctomb - (local.get $36) - (local.get $8) - ) - ) - (local.get $6) - ) - ) - (local.get $5) - ) - (block - (local.set $7 - (local.get $5) - ) - (br $__rjti$7) - ) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $36) - (local.get $8) - (local.get $0) - ) - ) - ) - (local.set $7 - (i32.add - (local.get $7) - (i32.const 4) - ) - ) - (br_if $while-in127 - (i32.lt_u - (local.get $6) - (local.get $5) - ) - ) - (local.set $7 - (local.get $5) - ) - ) - ) - (local.set $7 - (i32.const 0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $14) - (local.get $7) - (i32.xor - (local.get $11) - (i32.const 8192) - ) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (select - (local.get $14) - (local.get $7) - (i32.gt_s - (local.get $14) - (local.get $7) - ) - ) - ) - (br $label$continue$L1) - ) - (local.set $11 - (select - (i32.and - (local.get $7) - (i32.const -65537) - ) - (local.get $7) - (i32.gt_s - (local.get $6) - (i32.const -1) - ) - ) - ) - (local.set $12 - (if (result i32) - (i32.or - (local.get $6) - (local.tee $12 - (i32.or - (i32.ne - (i32.load - (local.tee $7 - (local.get $19) - ) - ) - (i32.const 0) - ) - (i32.ne - (i32.load offset=4 - (local.get $7) - ) - (i32.const 0) - ) - ) - ) - ) - (block (result i32) - (local.set $7 - (local.get $5) - ) - (select - (local.get $6) - (local.tee $5 - (i32.add - (i32.xor - (i32.and - (local.get $12) - (i32.const 1) - ) - (i32.const 1) - ) - (i32.sub - (local.get $39) - (local.get $5) - ) - ) - ) - (i32.gt_s - (local.get $6) - (local.get $5) - ) - ) - ) - (block (result i32) - (local.set $7 - (local.get $26) - ) - (i32.const 0) - ) - ) - ) - (local.get $26) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.tee $6 - (select - (local.tee $5 - (i32.add - (local.get $8) - (local.tee $12 - (select - (local.tee $13 - (i32.sub - (local.get $5) - (local.get $7) - ) - ) - (local.get $12) - (i32.lt_s - (local.get $12) - (local.get $13) - ) - ) - ) - ) - ) - (local.get $14) - (i32.lt_s - (local.get $14) - (local.get $5) - ) - ) - ) - (local.get $5) - (local.get $11) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $9) - (local.get $8) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (local.get $6) - (local.get $5) - (i32.xor - (local.get $11) - (i32.const 65536) - ) - ) - (call $_pad - (local.get $0) - (i32.const 48) - (local.get $12) - (local.get $13) - (i32.const 0) - ) - (if - (i32.eqz - (i32.and - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (drop - (call $___fwritex - (local.get $7) - (local.get $13) - (local.get $0) - ) - ) - ) - (call $_pad - (local.get $0) - (i32.const 32) - (local.get $6) - (local.get $5) - (i32.xor - (local.get $11) - (i32.const 8192) - ) - ) - (local.set $5 - (local.get $10) - ) - (local.set $10 - (local.get $6) - ) - (br $label$continue$L1) - ) - ) - (br $label$break$L343) - ) - (if - (i32.eqz - (local.get $0) - ) - (if - (local.get $1) - (block - (local.set $0 - (i32.const 1) - ) - (loop $while-in130 - (if - (local.tee $1 - (i32.load - (i32.add - (local.get $4) - (i32.shl - (local.get $0) - (i32.const 2) - ) - ) - ) - ) - (block - (call $_pop_arg_336 - (i32.add - (local.get $3) - (i32.shl - (local.get $0) - (i32.const 3) - ) - ) - (local.get $1) - (local.get $2) - ) - (br_if $while-in130 - (i32.lt_s - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (i32.const 10) - ) - ) - (local.set $16 - (i32.const 1) - ) - (br $label$break$L343) - ) - ) - ) - (if - (i32.lt_s - (local.get $0) - (i32.const 10) - ) - (loop $while-in132 - (if - (i32.load - (i32.add - (local.get $4) - (i32.shl - (local.get $0) - (i32.const 2) - ) - ) - ) - (block - (local.set $16 - (i32.const -1) - ) - (br $label$break$L343) - ) - ) - (br_if $while-in132 - (i32.lt_s - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (i32.const 10) - ) - ) - (local.set $16 - (i32.const 1) - ) - ) - (local.set $16 - (i32.const 1) - ) - ) - ) - (local.set $16 - (i32.const 0) - ) - ) - ) - ) - (global.set $STACKTOP - (local.get $25) - ) - (local.get $16) - ) - ;; CHECK: (func $_pop_arg_336 (param $0 i32) (param $1 i32) (param $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 f64) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (block $label$break$L1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch-default - ;; CHECK-NEXT: (block $switch-case9 - ;; CHECK-NEXT: (block $switch-case8 - ;; CHECK-NEXT: (block $switch-case7 - ;; CHECK-NEXT: (block $switch-case6 - ;; CHECK-NEXT: (block $switch-case5 - ;; CHECK-NEXT: (block $switch-case4 - ;; CHECK-NEXT: (block $switch-case3 - ;; CHECK-NEXT: (block $switch-case2 - ;; CHECK-NEXT: (block $switch-case1 - ;; CHECK-NEXT: (block $switch-case - ;; CHECK-NEXT: (br_table $switch-case $switch-case1 $switch-case2 $switch-case3 $switch-case4 $switch-case5 $switch-case6 $switch-case7 $switch-case8 $switch-case9 $switch-default - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_pop_arg_336 (param $0 i32) (param $1 i32) (param $2 i32) - (local $3 i32) - (local $4 f64) - (local $5 i32) - (block $label$break$L1 - (if - (i32.le_u - (local.get $1) - (i32.const 20) - ) - (block $switch-default - (block $switch-case9 - (block $switch-case8 - (block $switch-case7 - (block $switch-case6 - (block $switch-case5 - (block $switch-case4 - (block $switch-case3 - (block $switch-case2 - (block $switch-case1 - (block $switch-case - (br_table $switch-case $switch-case1 $switch-case2 $switch-case3 $switch-case4 $switch-case5 $switch-case6 $switch-case7 $switch-case8 $switch-case9 $switch-default - (i32.sub - (local.get $1) - (i32.const 9) - ) - ) - ) - (local.set $3 - (i32.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (local.get $3) - ) - (br $label$break$L1) - ) - (local.set $1 - (i32.load - (local.tee $3 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $3) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (local.get $1) - ) - (i32.store offset=4 - (local.get $0) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $1) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (br $label$break$L1) - ) - (local.set $3 - (i32.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (local.get $3) - ) - (i32.store offset=4 - (local.get $0) - (i32.const 0) - ) - (br $label$break$L1) - ) - (local.set $5 - (i32.load - (local.tee $3 - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 7) - ) - (i32.const -8) - ) - ) - ) - ) - ) - (local.set $3 - (i32.load offset=4 - (local.get $3) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - (i32.store - (local.get $0) - (local.get $5) - ) - (i32.store offset=4 - (local.get $0) - (local.get $3) - ) - (br $label$break$L1) - ) - (local.set $3 - (i32.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (local.tee $1 - (i32.shr_s - (i32.shl - (i32.and - (local.get $3) - (i32.const 65535) - ) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $1) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (br $label$break$L1) - ) - (local.set $3 - (i32.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (i32.and - (local.get $3) - (i32.const 65535) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.const 0) - ) - (br $label$break$L1) - ) - (local.set $3 - (i32.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (local.tee $1 - (i32.shr_s - (i32.shl - (i32.and - (local.get $3) - (i32.const 255) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.shr_s - (i32.shl - (i32.lt_s - (local.get $1) - (i32.const 0) - ) - (i32.const 31) - ) - (i32.const 31) - ) - ) - (br $label$break$L1) - ) - (local.set $3 - (i32.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 3) - ) - (i32.const -4) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.store - (local.get $0) - (i32.and - (local.get $3) - (i32.const 255) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.const 0) - ) - (br $label$break$L1) - ) - (local.set $4 - (f64.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 7) - ) - (i32.const -8) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - (f64.store - (local.get $0) - (local.get $4) - ) - (br $label$break$L1) - ) - (local.set $4 - (f64.load - (local.tee $1 - (i32.and - (i32.add - (i32.load - (local.get $2) - ) - (i32.const 7) - ) - (i32.const -8) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - (f64.store - (local.get $0) - (local.get $4) - ) - ) - ) - ) - ) - ;; CHECK: (func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $___uremdi3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $___udivdi3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (loop $while-in1 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - (func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (if - (i32.or - (i32.gt_u - (local.get $1) - (i32.const 0) - ) - (i32.and - (i32.eqz - (local.get $1) - ) - (i32.gt_u - (local.get $0) - (i32.const -1) - ) - ) - ) - (loop $while-in - (i32.store8 - (local.tee $2 - (i32.add - (local.get $2) - (i32.const -1) - ) - ) - (i32.or - (local.tee $3 - (call $___uremdi3 - (local.get $0) - (local.get $1) - (i32.const 10) - (i32.const 0) - ) - ) - (i32.const 48) - ) - ) - (local.set $3 - (call $___udivdi3 - (local.get $0) - (local.get $1) - (i32.const 10) - (i32.const 0) - ) - ) - (local.set $4 - (global.get $tempRet0) - ) - (if - (i32.or - (i32.gt_u - (local.get $1) - (i32.const 9) - ) - (i32.and - (i32.eq - (local.get $1) - (i32.const 9) - ) - (i32.gt_u - (local.get $0) - (i32.const -1) - ) - ) - ) - (block - (local.set $0 - (local.get $3) - ) - (local.set $1 - (local.get $4) - ) - (br $while-in) - ) - (local.set $0 - (local.get $3) - ) - ) - ) - ) - (if - (local.get $0) - (loop $while-in1 - (i32.store8 - (local.tee $2 - (i32.add - (local.get $2) - (i32.const -1) - ) - ) - (i32.or - (call $i32u-rem - (local.get $0) - (i32.const 10) - ) - (i32.const 48) - ) - ) - (local.set $1 - (call $i32u-div - (local.get $0) - (i32.const 10) - ) - ) - (if - (i32.ge_u - (local.get $0) - (i32.const 10) - ) - (block - (local.set $0 - (local.get $1) - ) - (br $while-in1) - ) - ) - ) - ) - (local.get $2) - ) - ;; CHECK: (func $_pad (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (global.get $STACK_MAX) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 73728) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $_memset - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block271 - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (block $block273 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const -256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_pad (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local.set $7 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 256) - ) - ) - (if - (i32.ge_s - (global.get $STACKTOP) - (global.get $STACK_MAX) - ) - (call $abort) - ) - (local.set $6 - (local.get $7) - ) - (block $do-once - (if - (i32.and - (i32.gt_s - (local.get $2) - (local.get $3) - ) - (i32.eqz - (i32.and - (local.get $4) - (i32.const 73728) - ) - ) - ) - (block - (drop - (call $_memset - (local.get $6) - (local.get $1) - (select - (i32.const 256) - (local.tee $5 - (i32.sub - (local.get $2) - (local.get $3) - ) - ) - (i32.gt_u - (local.get $5) - (i32.const 256) - ) - ) - ) - ) - (local.set $4 - (i32.eqz - (i32.and - (local.tee $1 - (i32.load - (local.get $0) - ) - ) - (i32.const 32) - ) - ) - ) - (if - (i32.gt_u - (local.get $5) - (i32.const 255) - ) - (block - (loop $while-in - (if - (local.get $4) - (block - (drop - (call $___fwritex - (local.get $6) - (i32.const 256) - (local.get $0) - ) - ) - (local.set $1 - (i32.load - (local.get $0) - ) - ) - ) - ) - (local.set $4 - (i32.eqz - (i32.and - (local.get $1) - (i32.const 32) - ) - ) - ) - (br_if $while-in - (i32.gt_u - (local.tee $5 - (i32.add - (local.get $5) - (i32.const -256) - ) - ) - (i32.const 255) - ) - ) - ) - (br_if $do-once - (i32.eqz - (local.get $4) - ) - ) - (local.set $5 - (i32.and - (i32.sub - (local.get $2) - (local.get $3) - ) - (i32.const 255) - ) - ) - ) - (br_if $do-once - (i32.eqz - (local.get $4) - ) - ) - ) - (drop - (call $___fwritex - (local.get $6) - (local.get $5) - (local.get $0) - ) - ) - ) - ) - ) - (global.set $STACKTOP - (local.get $7) - ) - ) - ;; CHECK: (func $_malloc (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (local $16 i32) - ;; CHECK-NEXT: (local $17 i32) - ;; CHECK-NEXT: (local $18 i32) - ;; CHECK-NEXT: (block $folding-inner0 - ;; CHECK-NEXT: (block $do-once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 245) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $13 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block275 - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block277 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block280 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block282 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (block $block284 - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block286 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block287 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block290 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block $block292 - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block295 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block296 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block298 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=480 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (block $while-out - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=16 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=20 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block301 - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.load offset=24 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block305 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block308 - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in7 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block310 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block312 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block314 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block315 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block319 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once8 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (block $block321 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=28 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block323 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block325 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block326 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once8 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=16 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block332 - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=20 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block335 - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block337 - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block338 - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block340 - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block343 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block344 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -65) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block346 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $18 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block348 - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 16777215) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1048320) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 520192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 245760) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$3 - ;; CHECK-NEXT: (block $__rjti$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=480 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block352 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in14 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block355 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block356 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load offset=20 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (block $block358 - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block359 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block360 - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block362 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $18) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block364 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load offset=480 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (block $block366 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in16 - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load offset=16 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block368 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in16 - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load offset=20 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block371 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.load offset=24 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once17 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block375 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block378 - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in20 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block380 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block382 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block384 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block385 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block389 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once21 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (block $block391 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=28 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block393 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block395 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block396 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once21 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=16 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block402 - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=20 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block405 - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once25 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block407 - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block408 - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block410 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block413 - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block414 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16777215) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1048320) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 520192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 245760) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=28 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block418 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$1 - ;; CHECK-NEXT: (block $__rjti$1 - ;; CHECK-NEXT: (loop $while-in28 - ;; CHECK-NEXT: (br_if $__rjti$1 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block420 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block422 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block424 - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block426 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block428 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block429 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $folding-inner0 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (call $_sysconf - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block432 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 656) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 652) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 660) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 664) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 668) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 620) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 648) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (call $_time - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1431655768) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 656) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 47) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 616) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 608) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$13 - ;; CHECK-NEXT: (block $__rjti$13 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 620) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block437 - ;; CHECK-NEXT: (block $label$break$L279 - ;; CHECK-NEXT: (block $__rjti$5 - ;; CHECK-NEXT: (block $__rjti$4 - ;; CHECK-NEXT: (br_if $__rjti$4 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in34 - ;; CHECK-NEXT: (block $while-out33 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block440 - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-out33) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in34 - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$13 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block443 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L279) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block445 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 652) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 608) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block448 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 616) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$break$L279 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$13 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L279) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 656) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block453 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L279) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block455 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 620) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 620) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (call $_sbrk - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__rjti$13 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 608) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 608) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 612) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 612) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once40 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block460 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$10 - ;; CHECK-NEXT: (block $__rjti$10 - ;; CHECK-NEXT: (loop $while-in45 - ;; CHECK-NEXT: (br_if $__rjti$10 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in45 - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block463 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 204) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 664) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block465 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$11 - ;; CHECK-NEXT: (block $__rjti$11 - ;; CHECK-NEXT: (loop $while-in47 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block467 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjti$11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in47 - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block469 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once48 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block471 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block472 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block474 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block476 (result i32) - ;; CHECK-NEXT: (local.set $11 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$L331 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block478 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once51 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block480 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once51 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block483 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L331) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once53 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block485 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block488 - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once53) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block489 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load offset=24 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once55 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block491 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block494 - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once55) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in58 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block496 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in58) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block498 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in58) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block500 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block501 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block505 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$break$L331 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once59 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=28 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block507 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once59 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$L331) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block508 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$break$L331 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block514 - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label$break$L331 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block516 - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block518 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once63 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block520 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block522 - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block523 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (block $do-once65 (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block525 (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $do-once65 - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 16777215) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1048320) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 520192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 245760) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=28 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block527 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$7 - ;; CHECK-NEXT: (block $__rjti$7 - ;; CHECK-NEXT: (loop $while-in68 - ;; CHECK-NEXT: (br_if $__rjti$7 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block529 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in68) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block531 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block533 - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in70 - ;; CHECK-NEXT: (block $while-out69 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-out69 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in70) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const -47) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const -40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 204) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 664) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 628) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 632) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 636) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 628) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 636) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 632) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in72 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in72 - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block536 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block538 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block541 - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block542 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16777215) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1048320) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 520192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 245760) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=28 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block546 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$9 - ;; CHECK-NEXT: (block $__rjti$9 - ;; CHECK-NEXT: (loop $while-in74 - ;; CHECK-NEXT: (br_if $__rjti$9 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block548 - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in74) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block550 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block552 - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block553 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 624) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 628) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 636) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 212) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 208) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in43 - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in43 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const -40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 204) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 664) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $folding-inner0 - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (call $___errno_location) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_malloc (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local $10 i32) - (local $11 i32) - (local $12 i32) - (local $13 i32) - (local $14 i32) - (local $15 i32) - (local $16 i32) - (local $17 i32) - (local $18 i32) - (block $folding-inner0 - (block $do-once - (if - (i32.lt_u - (local.get $0) - (i32.const 245) - ) - (block - (if - (i32.and - (local.tee $5 - (i32.shr_u - (local.tee $11 - (i32.load - (i32.const 176) - ) - ) - (local.tee $13 - (i32.shr_u - (local.tee $4 - (select - (i32.const 16) - (i32.and - (i32.add - (local.get $0) - (i32.const 11) - ) - (i32.const -8) - ) - (i32.lt_u - (local.get $0) - (i32.const 11) - ) - ) - ) - (i32.const 3) - ) - ) - ) - ) - (i32.const 3) - ) - (block - (local.set $10 - (i32.load - (local.tee $1 - (i32.add - (local.tee $7 - (i32.load - (local.tee $3 - (i32.add - (local.tee $2 - (i32.add - (i32.shl - (local.tee $4 - (i32.add - (i32.xor - (i32.and - (local.get $5) - (i32.const 1) - ) - (i32.const 1) - ) - (local.get $13) - ) - ) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 8) - ) - ) - ) - ) - (if - (i32.eq - (local.get $2) - (local.get $10) - ) - (i32.store - (i32.const 176) - (i32.and - (local.get $11) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $4) - ) - (i32.const -1) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $10) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $10) - (i32.const 12) - ) - ) - ) - (local.get $7) - ) - (block - (i32.store - (local.get $0) - (local.get $2) - ) - (i32.store - (local.get $3) - (local.get $10) - ) - ) - (call $_abort) - ) - ) - ) - (i32.store offset=4 - (local.get $7) - (i32.or - (local.tee $0 - (i32.shl - (local.get $4) - (i32.const 3) - ) - ) - (i32.const 3) - ) - ) - (i32.store - (local.tee $0 - (i32.add - (i32.add - (local.get $7) - (local.get $0) - ) - (i32.const 4) - ) - ) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 1) - ) - ) - (return - (local.get $1) - ) - ) - ) - (if - (i32.gt_u - (local.get $4) - (local.tee $0 - (i32.load - (i32.const 184) - ) - ) - ) - (block - (if - (local.get $5) - (block - (local.set $10 - (i32.and - (i32.shr_u - (local.tee $3 - (i32.add - (i32.and - (local.tee $3 - (i32.and - (i32.shl - (local.get $5) - (local.get $13) - ) - (i32.or - (local.tee $3 - (i32.shl - (i32.const 2) - (local.get $13) - ) - ) - (i32.sub - (i32.const 0) - (local.get $3) - ) - ) - ) - ) - (i32.sub - (i32.const 0) - (local.get $3) - ) - ) - (i32.const -1) - ) - ) - (i32.const 12) - ) - (i32.const 16) - ) - ) - (local.set $9 - (i32.load - (local.tee $7 - (i32.add - (local.tee $12 - (i32.load - (local.tee $3 - (i32.add - (local.tee $10 - (i32.add - (i32.shl - (local.tee $5 - (i32.add - (i32.or - (i32.or - (i32.or - (i32.or - (local.tee $3 - (i32.and - (i32.shr_u - (local.tee $7 - (i32.shr_u - (local.get $3) - (local.get $10) - ) - ) - (i32.const 5) - ) - (i32.const 8) - ) - ) - (local.get $10) - ) - (local.tee $3 - (i32.and - (i32.shr_u - (local.tee $7 - (i32.shr_u - (local.get $7) - (local.get $3) - ) - ) - (i32.const 2) - ) - (i32.const 4) - ) - ) - ) - (local.tee $3 - (i32.and - (i32.shr_u - (local.tee $7 - (i32.shr_u - (local.get $7) - (local.get $3) - ) - ) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ) - (local.tee $3 - (i32.and - (i32.shr_u - (local.tee $7 - (i32.shr_u - (local.get $7) - (local.get $3) - ) - ) - (i32.const 1) - ) - (i32.const 1) - ) - ) - ) - (i32.shr_u - (local.get $7) - (local.get $3) - ) - ) - ) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 8) - ) - ) - ) - ) - (if - (i32.eq - (local.get $10) - (local.get $9) - ) - (block - (i32.store - (i32.const 176) - (i32.and - (local.get $11) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $5) - ) - (i32.const -1) - ) - ) - ) - (local.set $8 - (local.get $0) - ) - ) - (block - (if - (i32.lt_u - (local.get $9) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $9) - (i32.const 12) - ) - ) - ) - (local.get $12) - ) - (block - (i32.store - (local.get $0) - (local.get $10) - ) - (i32.store - (local.get $3) - (local.get $9) - ) - (local.set $8 - (i32.load - (i32.const 184) - ) - ) - ) - (call $_abort) - ) - ) - ) - (i32.store offset=4 - (local.get $12) - (i32.or - (local.get $4) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $10 - (i32.add - (local.get $12) - (local.get $4) - ) - ) - (i32.or - (local.tee $5 - (i32.sub - (i32.shl - (local.get $5) - (i32.const 3) - ) - (local.get $4) - ) - ) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $10) - (local.get $5) - ) - (local.get $5) - ) - (if - (local.get $8) - (block - (local.set $12 - (i32.load - (i32.const 196) - ) - ) - (local.set $4 - (i32.add - (i32.shl - (local.tee $0 - (i32.shr_u - (local.get $8) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (if - (i32.and - (local.tee $3 - (i32.load - (i32.const 176) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - (if - (i32.lt_u - (local.tee $0 - (i32.load - (local.tee $3 - (i32.add - (local.get $4) - (i32.const 8) - ) - ) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (local.set $2 - (local.get $3) - ) - (local.set $1 - (local.get $0) - ) - ) - ) - (block - (i32.store - (i32.const 176) - (i32.or - (local.get $3) - (local.get $0) - ) - ) - (local.set $2 - (i32.add - (local.get $4) - (i32.const 8) - ) - ) - (local.set $1 - (local.get $4) - ) - ) - ) - (i32.store - (local.get $2) - (local.get $12) - ) - (i32.store offset=12 - (local.get $1) - (local.get $12) - ) - (i32.store offset=8 - (local.get $12) - (local.get $1) - ) - (i32.store offset=12 - (local.get $12) - (local.get $4) - ) - ) - ) - (i32.store - (i32.const 184) - (local.get $5) - ) - (i32.store - (i32.const 196) - (local.get $10) - ) - (return - (local.get $7) - ) - ) - ) - (if - (local.tee $0 - (i32.load - (i32.const 180) - ) - ) - (block - (local.set $2 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.add - (i32.and - (local.get $0) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - (i32.const -1) - ) - ) - (i32.const 12) - ) - (i32.const 16) - ) - ) - (local.set $7 - (i32.sub - (i32.and - (i32.load offset=4 - (local.tee $0 - (i32.load offset=480 - (i32.shl - (i32.add - (i32.or - (i32.or - (i32.or - (i32.or - (local.tee $0 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.shr_u - (local.get $0) - (local.get $2) - ) - ) - (i32.const 5) - ) - (i32.const 8) - ) - ) - (local.get $2) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.shr_u - (local.get $1) - (local.get $0) - ) - ) - (i32.const 2) - ) - (i32.const 4) - ) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.shr_u - (local.get $1) - (local.get $0) - ) - ) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.shr_u - (local.get $1) - (local.get $0) - ) - ) - (i32.const 1) - ) - (i32.const 1) - ) - ) - ) - (i32.shr_u - (local.get $1) - (local.get $0) - ) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.const -8) - ) - (local.get $4) - ) - ) - (local.set $1 - (local.get $0) - ) - (local.set $2 - (local.get $0) - ) - (loop $while-in - (block $while-out - (if - (i32.eqz - (local.tee $0 - (i32.load offset=16 - (local.get $1) - ) - ) - ) - (if - (i32.eqz - (local.tee $0 - (i32.load offset=20 - (local.get $1) - ) - ) - ) - (block - (local.set $10 - (local.get $7) - ) - (local.set $5 - (local.get $2) - ) - (br $while-out) - ) - ) - ) - (local.set $10 - (i32.lt_u - (local.tee $1 - (i32.sub - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - (local.get $4) - ) - ) - (local.get $7) - ) - ) - (local.set $7 - (select - (local.get $1) - (local.get $7) - (local.get $10) - ) - ) - (local.set $1 - (local.get $0) - ) - (local.set $2 - (select - (local.get $0) - (local.get $2) - (local.get $10) - ) - ) - (br $while-in) - ) - ) - (if - (i32.lt_u - (local.get $5) - (local.tee $12 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (if - (i32.ge_u - (local.get $5) - (local.tee $11 - (i32.add - (local.get $5) - (local.get $4) - ) - ) - ) - (call $_abort) - ) - (local.set $8 - (i32.load offset=24 - (local.get $5) - ) - ) - (block $do-once4 - (if - (i32.eq - (local.tee $0 - (i32.load offset=12 - (local.get $5) - ) - ) - (local.get $5) - ) - (block - (if - (i32.eqz - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $5) - (i32.const 20) - ) - ) - ) - ) - ) - (if - (i32.eqz - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - ) - ) - ) - (block - (local.set $9 - (i32.const 0) - ) - (br $do-once4) - ) - ) - ) - (loop $while-in7 - (if - (local.tee $2 - (i32.load - (local.tee $7 - (i32.add - (local.get $1) - (i32.const 20) - ) - ) - ) - ) - (block - (local.set $1 - (local.get $2) - ) - (local.set $0 - (local.get $7) - ) - (br $while-in7) - ) - ) - (if - (local.tee $2 - (i32.load - (local.tee $7 - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - ) - (block - (local.set $1 - (local.get $2) - ) - (local.set $0 - (local.get $7) - ) - (br $while-in7) - ) - ) - ) - (if - (i32.lt_u - (local.get $0) - (local.get $12) - ) - (call $_abort) - (block - (i32.store - (local.get $0) - (i32.const 0) - ) - (local.set $9 - (local.get $1) - ) - ) - ) - ) - (block - (if - (i32.lt_u - (local.tee $7 - (i32.load offset=8 - (local.get $5) - ) - ) - (local.get $12) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load - (local.tee $2 - (i32.add - (local.get $7) - (i32.const 12) - ) - ) - ) - (local.get $5) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - (local.get $5) - ) - (block - (i32.store - (local.get $2) - (local.get $0) - ) - (i32.store - (local.get $1) - (local.get $7) - ) - (local.set $9 - (local.get $0) - ) - ) - (call $_abort) - ) - ) - ) - ) - (block $do-once8 - (if - (local.get $8) - (block - (if - (i32.eq - (local.get $5) - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $1 - (i32.load offset=28 - (local.get $5) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - ) - ) - (block - (i32.store - (local.get $0) - (local.get $9) - ) - (if - (i32.eqz - (local.get $9) - ) - (block - (i32.store - (i32.const 180) - (i32.and - (i32.load - (i32.const 180) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $1) - ) - (i32.const -1) - ) - ) - ) - (br $do-once8) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $8) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $8) - (i32.const 16) - ) - ) - ) - (local.get $5) - ) - (i32.store - (local.get $0) - (local.get $9) - ) - (i32.store offset=20 - (local.get $8) - (local.get $9) - ) - ) - (br_if $do-once8 - (i32.eqz - (local.get $9) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $9) - (local.tee $0 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (i32.store offset=24 - (local.get $9) - (local.get $8) - ) - (if - (local.tee $1 - (i32.load offset=16 - (local.get $5) - ) - ) - (if - (i32.lt_u - (local.get $1) - (local.get $0) - ) - (call $_abort) - (block - (i32.store offset=16 - (local.get $9) - (local.get $1) - ) - (i32.store offset=24 - (local.get $1) - (local.get $9) - ) - ) - ) - ) - (if - (local.tee $0 - (i32.load offset=20 - (local.get $5) - ) - ) - (if - (i32.lt_u - (local.get $0) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store offset=20 - (local.get $9) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $9) - ) - ) - ) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $10) - (i32.const 16) - ) - (block - (i32.store offset=4 - (local.get $5) - (i32.or - (local.tee $0 - (i32.add - (local.get $10) - (local.get $4) - ) - ) - (i32.const 3) - ) - ) - (i32.store - (local.tee $0 - (i32.add - (i32.add - (local.get $5) - (local.get $0) - ) - (i32.const 4) - ) - ) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 1) - ) - ) - ) - (block - (i32.store offset=4 - (local.get $5) - (i32.or - (local.get $4) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.get $11) - (i32.or - (local.get $10) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $11) - (local.get $10) - ) - (local.get $10) - ) - (if - (local.tee $0 - (i32.load - (i32.const 184) - ) - ) - (block - (local.set $4 - (i32.load - (i32.const 196) - ) - ) - (local.set $2 - (i32.add - (i32.shl - (local.tee $0 - (i32.shr_u - (local.get $0) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (if - (i32.and - (local.tee $1 - (i32.load - (i32.const 176) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - (if - (i32.lt_u - (local.tee $0 - (i32.load - (local.tee $1 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (local.set $6 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - ) - ) - (block - (i32.store - (i32.const 176) - (i32.or - (local.get $1) - (local.get $0) - ) - ) - (local.set $6 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - (local.set $3 - (local.get $2) - ) - ) - ) - (i32.store - (local.get $6) - (local.get $4) - ) - (i32.store offset=12 - (local.get $3) - (local.get $4) - ) - (i32.store offset=8 - (local.get $4) - (local.get $3) - ) - (i32.store offset=12 - (local.get $4) - (local.get $2) - ) - ) - ) - (i32.store - (i32.const 184) - (local.get $10) - ) - (i32.store - (i32.const 196) - (local.get $11) - ) - ) - ) - (return - (i32.add - (local.get $5) - (i32.const 8) - ) - ) - ) - (local.set $0 - (local.get $4) - ) - ) - ) - (local.set $0 - (local.get $4) - ) - ) - ) - (if - (i32.gt_u - (local.get $0) - (i32.const -65) - ) - (local.set $0 - (i32.const -1) - ) - (block - (local.set $2 - (i32.and - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 11) - ) - ) - (i32.const -8) - ) - ) - (if - (local.tee $18 - (i32.load - (i32.const 180) - ) - ) - (block - (local.set $14 - (if (result i32) - (local.tee $0 - (i32.shr_u - (local.get $0) - (i32.const 8) - ) - ) - (if (result i32) - (i32.gt_u - (local.get $2) - (i32.const 16777215) - ) - (i32.const 31) - (i32.or - (i32.and - (i32.shr_u - (local.get $2) - (i32.add - (local.tee $0 - (i32.add - (i32.sub - (i32.const 14) - (i32.or - (i32.or - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $0) - (local.tee $3 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - (local.get $3) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $1) - (local.get $0) - ) - ) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.shr_u - (i32.shl - (local.get $1) - (local.get $0) - ) - (i32.const 15) - ) - ) - ) - (i32.const 7) - ) - ) - (i32.const 1) - ) - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - ) - (local.set $3 - (i32.sub - (i32.const 0) - (local.get $2) - ) - ) - (block $__rjto$3 - (block $__rjti$3 - (if - (local.tee $0 - (i32.load offset=480 - (i32.shl - (local.get $14) - (i32.const 2) - ) - ) - ) - (block - (local.set $6 - (i32.const 0) - ) - (local.set $8 - (i32.shl - (local.get $2) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $14) - (i32.const 1) - ) - ) - (i32.eq - (local.get $14) - (i32.const 31) - ) - ) - ) - ) - (local.set $1 - (i32.const 0) - ) - (loop $while-in14 - (if - (i32.lt_u - (local.tee $4 - (i32.sub - (local.tee $9 - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - ) - (local.get $2) - ) - ) - (local.get $3) - ) - (if - (i32.eq - (local.get $9) - (local.get $2) - ) - (block - (local.set $1 - (local.get $4) - ) - (local.set $3 - (local.get $0) - ) - (br $__rjti$3) - ) - (block - (local.set $3 - (local.get $4) - ) - (local.set $1 - (local.get $0) - ) - ) - ) - ) - (local.set $0 - (select - (local.get $6) - (local.tee $4 - (i32.load offset=20 - (local.get $0) - ) - ) - (i32.or - (i32.eqz - (local.get $4) - ) - (i32.eq - (local.get $4) - (local.tee $9 - (i32.load - (i32.add - (i32.add - (local.get $0) - (i32.const 16) - ) - (i32.shl - (i32.shr_u - (local.get $8) - (i32.const 31) - ) - (i32.const 2) - ) - ) - ) - ) - ) - ) - ) - ) - (local.set $4 - (i32.shl - (local.get $8) - (i32.xor - (local.tee $6 - (i32.eqz - (local.get $9) - ) - ) - (i32.const 1) - ) - ) - ) - (if - (local.get $6) - (block - (local.set $4 - (local.get $0) - ) - (local.set $0 - (local.get $1) - ) - ) - (block - (local.set $6 - (local.get $0) - ) - (local.set $8 - (local.get $4) - ) - (local.set $0 - (local.get $9) - ) - (br $while-in14) - ) - ) - ) - ) - (block - (local.set $4 - (i32.const 0) - ) - (local.set $0 - (i32.const 0) - ) - ) - ) - (if - (i32.and - (i32.eqz - (local.get $4) - ) - (i32.eqz - (local.get $0) - ) - ) - (block - (if - (i32.eqz - (local.tee $1 - (i32.and - (local.get $18) - (i32.or - (local.tee $1 - (i32.shl - (i32.const 2) - (local.get $14) - ) - ) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - ) - ) - (block - (local.set $0 - (local.get $2) - ) - (br $do-once) - ) - ) - (local.set $9 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.add - (i32.and - (local.get $1) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - (i32.const -1) - ) - ) - (i32.const 12) - ) - (i32.const 16) - ) - ) - (local.set $4 - (i32.load offset=480 - (i32.shl - (i32.add - (i32.or - (i32.or - (i32.or - (i32.or - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $4 - (i32.shr_u - (local.get $1) - (local.get $9) - ) - ) - (i32.const 5) - ) - (i32.const 8) - ) - ) - (local.get $9) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $4 - (i32.shr_u - (local.get $4) - (local.get $1) - ) - ) - (i32.const 2) - ) - (i32.const 4) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $4 - (i32.shr_u - (local.get $4) - (local.get $1) - ) - ) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $4 - (i32.shr_u - (local.get $4) - (local.get $1) - ) - ) - (i32.const 1) - ) - (i32.const 1) - ) - ) - ) - (i32.shr_u - (local.get $4) - (local.get $1) - ) - ) - (i32.const 2) - ) - ) - ) - ) - ) - (if - (local.get $4) - (block - (local.set $1 - (local.get $3) - ) - (local.set $3 - (local.get $4) - ) - (br $__rjti$3) - ) - (local.set $4 - (local.get $0) - ) - ) - (br $__rjto$3) - ) - (loop $while-in16 - (local.set $9 - (i32.lt_u - (local.tee $4 - (i32.sub - (i32.and - (i32.load offset=4 - (local.get $3) - ) - (i32.const -8) - ) - (local.get $2) - ) - ) - (local.get $1) - ) - ) - (local.set $1 - (select - (local.get $4) - (local.get $1) - (local.get $9) - ) - ) - (local.set $0 - (select - (local.get $3) - (local.get $0) - (local.get $9) - ) - ) - (if - (local.tee $4 - (i32.load offset=16 - (local.get $3) - ) - ) - (block - (local.set $3 - (local.get $4) - ) - (br $while-in16) - ) - ) - (br_if $while-in16 - (local.tee $3 - (i32.load offset=20 - (local.get $3) - ) - ) - ) - (local.set $3 - (local.get $1) - ) - (local.set $4 - (local.get $0) - ) - ) - ) - (if - (local.get $4) - (if - (i32.lt_u - (local.get $3) - (i32.sub - (i32.load - (i32.const 184) - ) - (local.get $2) - ) - ) - (block - (if - (i32.lt_u - (local.get $4) - (local.tee $12 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (if - (i32.ge_u - (local.get $4) - (local.tee $6 - (i32.add - (local.get $4) - (local.get $2) - ) - ) - ) - (call $_abort) - ) - (local.set $9 - (i32.load offset=24 - (local.get $4) - ) - ) - (block $do-once17 - (if - (i32.eq - (local.tee $0 - (i32.load offset=12 - (local.get $4) - ) - ) - (local.get $4) - ) - (block - (if - (i32.eqz - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $4) - (i32.const 20) - ) - ) - ) - ) - ) - (if - (i32.eqz - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $4) - (i32.const 16) - ) - ) - ) - ) - ) - (block - (local.set $11 - (i32.const 0) - ) - (br $do-once17) - ) - ) - ) - (loop $while-in20 - (if - (local.tee $7 - (i32.load - (local.tee $10 - (i32.add - (local.get $1) - (i32.const 20) - ) - ) - ) - ) - (block - (local.set $1 - (local.get $7) - ) - (local.set $0 - (local.get $10) - ) - (br $while-in20) - ) - ) - (if - (local.tee $7 - (i32.load - (local.tee $10 - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - ) - (block - (local.set $1 - (local.get $7) - ) - (local.set $0 - (local.get $10) - ) - (br $while-in20) - ) - ) - ) - (if - (i32.lt_u - (local.get $0) - (local.get $12) - ) - (call $_abort) - (block - (i32.store - (local.get $0) - (i32.const 0) - ) - (local.set $11 - (local.get $1) - ) - ) - ) - ) - (block - (if - (i32.lt_u - (local.tee $10 - (i32.load offset=8 - (local.get $4) - ) - ) - (local.get $12) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load - (local.tee $7 - (i32.add - (local.get $10) - (i32.const 12) - ) - ) - ) - (local.get $4) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - (local.get $4) - ) - (block - (i32.store - (local.get $7) - (local.get $0) - ) - (i32.store - (local.get $1) - (local.get $10) - ) - (local.set $11 - (local.get $0) - ) - ) - (call $_abort) - ) - ) - ) - ) - (block $do-once21 - (if - (local.get $9) - (block - (if - (i32.eq - (local.get $4) - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $1 - (i32.load offset=28 - (local.get $4) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - ) - ) - (block - (i32.store - (local.get $0) - (local.get $11) - ) - (if - (i32.eqz - (local.get $11) - ) - (block - (i32.store - (i32.const 180) - (i32.and - (i32.load - (i32.const 180) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $1) - ) - (i32.const -1) - ) - ) - ) - (br $do-once21) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $9) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $9) - (i32.const 16) - ) - ) - ) - (local.get $4) - ) - (i32.store - (local.get $0) - (local.get $11) - ) - (i32.store offset=20 - (local.get $9) - (local.get $11) - ) - ) - (br_if $do-once21 - (i32.eqz - (local.get $11) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $11) - (local.tee $0 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (i32.store offset=24 - (local.get $11) - (local.get $9) - ) - (if - (local.tee $1 - (i32.load offset=16 - (local.get $4) - ) - ) - (if - (i32.lt_u - (local.get $1) - (local.get $0) - ) - (call $_abort) - (block - (i32.store offset=16 - (local.get $11) - (local.get $1) - ) - (i32.store offset=24 - (local.get $1) - (local.get $11) - ) - ) - ) - ) - (if - (local.tee $0 - (i32.load offset=20 - (local.get $4) - ) - ) - (if - (i32.lt_u - (local.get $0) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store offset=20 - (local.get $11) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $11) - ) - ) - ) - ) - ) - ) - ) - (block $do-once25 - (if - (i32.lt_u - (local.get $3) - (i32.const 16) - ) - (block - (i32.store offset=4 - (local.get $4) - (i32.or - (local.tee $0 - (i32.add - (local.get $3) - (local.get $2) - ) - ) - (i32.const 3) - ) - ) - (i32.store - (local.tee $0 - (i32.add - (i32.add - (local.get $4) - (local.get $0) - ) - (i32.const 4) - ) - ) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 1) - ) - ) - ) - (block - (i32.store offset=4 - (local.get $4) - (i32.or - (local.get $2) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.get $6) - (i32.or - (local.get $3) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $6) - (local.get $3) - ) - (local.get $3) - ) - (local.set $0 - (i32.shr_u - (local.get $3) - (i32.const 3) - ) - ) - (if - (i32.lt_u - (local.get $3) - (i32.const 256) - ) - (block - (local.set $3 - (i32.add - (i32.shl - (local.get $0) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (if - (i32.and - (local.tee $1 - (i32.load - (i32.const 176) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - (if - (i32.lt_u - (local.tee $0 - (i32.load - (local.tee $1 - (i32.add - (local.get $3) - (i32.const 8) - ) - ) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (local.set $13 - (local.get $1) - ) - (local.set $5 - (local.get $0) - ) - ) - ) - (block - (i32.store - (i32.const 176) - (i32.or - (local.get $1) - (local.get $0) - ) - ) - (local.set $13 - (i32.add - (local.get $3) - (i32.const 8) - ) - ) - (local.set $5 - (local.get $3) - ) - ) - ) - (i32.store - (local.get $13) - (local.get $6) - ) - (i32.store offset=12 - (local.get $5) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $5) - ) - (i32.store offset=12 - (local.get $6) - (local.get $3) - ) - (br $do-once25) - ) - ) - (local.set $2 - (i32.add - (i32.shl - (local.tee $7 - (if (result i32) - (local.tee $0 - (i32.shr_u - (local.get $3) - (i32.const 8) - ) - ) - (if (result i32) - (i32.gt_u - (local.get $3) - (i32.const 16777215) - ) - (i32.const 31) - (i32.or - (i32.and - (i32.shr_u - (local.get $3) - (i32.add - (local.tee $0 - (i32.add - (i32.sub - (i32.const 14) - (i32.or - (i32.or - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $0) - (local.tee $2 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - (local.get $2) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $1) - (local.get $0) - ) - ) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.shr_u - (i32.shl - (local.get $1) - (local.get $0) - ) - (i32.const 15) - ) - ) - ) - (i32.const 7) - ) - ) - (i32.const 1) - ) - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - (i32.store offset=28 - (local.get $6) - (local.get $7) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - (i32.const 0) - ) - (i32.store - (local.get $0) - (i32.const 0) - ) - (if - (i32.eqz - (i32.and - (local.tee $1 - (i32.load - (i32.const 180) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $7) - ) - ) - ) - ) - (block - (i32.store - (i32.const 180) - (i32.or - (local.get $1) - (local.get $0) - ) - ) - (i32.store - (local.get $2) - (local.get $6) - ) - (i32.store offset=24 - (local.get $6) - (local.get $2) - ) - (i32.store offset=12 - (local.get $6) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $6) - ) - (br $do-once25) - ) - ) - (local.set $7 - (i32.shl - (local.get $3) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $7) - (i32.const 1) - ) - ) - (i32.eq - (local.get $7) - (i32.const 31) - ) - ) - ) - ) - (local.set $0 - (i32.load - (local.get $2) - ) - ) - (block $__rjto$1 - (block $__rjti$1 - (loop $while-in28 - (br_if $__rjti$1 - (i32.eq - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.set $2 - (i32.shl - (local.get $7) - (i32.const 1) - ) - ) - (if - (local.tee $1 - (i32.load - (local.tee $7 - (i32.add - (i32.add - (local.get $0) - (i32.const 16) - ) - (i32.shl - (i32.shr_u - (local.get $7) - (i32.const 31) - ) - (i32.const 2) - ) - ) - ) - ) - ) - (block - (local.set $7 - (local.get $2) - ) - (local.set $0 - (local.get $1) - ) - (br $while-in28) - ) - ) - ) - (if - (i32.lt_u - (local.get $7) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store - (local.get $7) - (local.get $6) - ) - (i32.store offset=24 - (local.get $6) - (local.get $0) - ) - (i32.store offset=12 - (local.get $6) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $6) - ) - (br $do-once25) - ) - ) - (br $__rjto$1) - ) - (if - (i32.and - (i32.ge_u - (local.tee $2 - (i32.load - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - (local.tee $1 - (i32.load - (i32.const 192) - ) - ) - ) - (i32.ge_u - (local.get $0) - (local.get $1) - ) - ) - (block - (i32.store offset=12 - (local.get $2) - (local.get $6) - ) - (i32.store - (local.get $3) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $2) - ) - (i32.store offset=12 - (local.get $6) - (local.get $0) - ) - (i32.store offset=24 - (local.get $6) - (i32.const 0) - ) - ) - (call $_abort) - ) - ) - ) - ) - ) - (return - (i32.add - (local.get $4) - (i32.const 8) - ) - ) - ) - (local.set $0 - (local.get $2) - ) - ) - (local.set $0 - (local.get $2) - ) - ) - ) - (local.set $0 - (local.get $2) - ) - ) - ) - ) - ) - ) - (if - (i32.ge_u - (local.tee $1 - (i32.load - (i32.const 184) - ) - ) - (local.get $0) - ) - (block - (local.set $2 - (i32.load - (i32.const 196) - ) - ) - (if - (i32.gt_u - (local.tee $3 - (i32.sub - (local.get $1) - (local.get $0) - ) - ) - (i32.const 15) - ) - (block - (i32.store - (i32.const 196) - (local.tee $1 - (i32.add - (local.get $2) - (local.get $0) - ) - ) - ) - (i32.store - (i32.const 184) - (local.get $3) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $3) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $3) - ) - (local.get $3) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $0) - (i32.const 3) - ) - ) - ) - (block - (i32.store - (i32.const 184) - (i32.const 0) - ) - (i32.store - (i32.const 196) - (i32.const 0) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $1) - (i32.const 3) - ) - ) - (i32.store - (local.tee $0 - (i32.add - (i32.add - (local.get $2) - (local.get $1) - ) - (i32.const 4) - ) - ) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 1) - ) - ) - ) - ) - (return - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - ) - ) - (br_if $folding-inner0 - (i32.gt_u - (local.tee $1 - (i32.load - (i32.const 188) - ) - ) - (local.get $0) - ) - ) - (if - (i32.eqz - (i32.load - (i32.const 648) - ) - ) - (if - (i32.and - (i32.add - (local.tee $1 - (call $_sysconf - (i32.const 30) - ) - ) - (i32.const -1) - ) - (local.get $1) - ) - (call $_abort) - (block - (i32.store - (i32.const 656) - (local.get $1) - ) - (i32.store - (i32.const 652) - (local.get $1) - ) - (i32.store - (i32.const 660) - (i32.const -1) - ) - (i32.store - (i32.const 664) - (i32.const -1) - ) - (i32.store - (i32.const 668) - (i32.const 0) - ) - (i32.store - (i32.const 620) - (i32.const 0) - ) - (i32.store - (i32.const 648) - (i32.xor - (i32.and - (call $_time - (i32.const 0) - ) - (i32.const -16) - ) - (i32.const 1431655768) - ) - ) - ) - ) - ) - (if - (i32.le_u - (local.tee $5 - (i32.and - (local.tee $6 - (i32.add - (local.tee $1 - (i32.load - (i32.const 656) - ) - ) - (local.tee $8 - (i32.add - (local.get $0) - (i32.const 47) - ) - ) - ) - ) - (local.tee $9 - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - ) - (local.get $0) - ) - (return - (i32.const 0) - ) - ) - (if - (local.tee $2 - (i32.load - (i32.const 616) - ) - ) - (if - (i32.or - (i32.le_u - (local.tee $1 - (i32.add - (local.tee $3 - (i32.load - (i32.const 608) - ) - ) - (local.get $5) - ) - ) - (local.get $3) - ) - (i32.gt_u - (local.get $1) - (local.get $2) - ) - ) - (return - (i32.const 0) - ) - ) - ) - (local.set $11 - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (block $__rjto$13 - (block $__rjti$13 - (if - (i32.eqz - (i32.and - (i32.load - (i32.const 620) - ) - (i32.const 4) - ) - ) - (block - (block $label$break$L279 - (block $__rjti$5 - (block $__rjti$4 - (br_if $__rjti$4 - (i32.eqz - (local.tee $4 - (i32.load - (i32.const 200) - ) - ) - ) - ) - (local.set $1 - (i32.const 624) - ) - (loop $while-in34 - (block $while-out33 - (if - (i32.le_u - (local.tee $3 - (i32.load - (local.get $1) - ) - ) - (local.get $4) - ) - (if - (i32.gt_u - (i32.add - (local.get $3) - (i32.load - (local.tee $2 - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - ) - ) - (local.get $4) - ) - (block - (local.set $4 - (local.get $1) - ) - (br $while-out33) - ) - ) - ) - (br_if $while-in34 - (local.tee $1 - (i32.load offset=8 - (local.get $1) - ) - ) - ) - (br $__rjti$4) - ) - ) - (if - (i32.lt_u - (local.tee $3 - (i32.and - (i32.sub - (local.get $6) - (i32.load - (i32.const 188) - ) - ) - (local.get $9) - ) - ) - (i32.const 2147483647) - ) - (if - (i32.eq - (local.tee $1 - (call $_sbrk - (local.get $3) - ) - ) - (i32.add - (i32.load - (local.get $4) - ) - (i32.load - (local.get $2) - ) - ) - ) - (br_if $__rjti$13 - (i32.ne - (local.get $1) - (i32.const -1) - ) - ) - (block - (local.set $2 - (local.get $1) - ) - (br $__rjti$5) - ) - ) - ) - (br $label$break$L279) - ) - (if - (i32.ne - (local.tee $1 - (call $_sbrk - (i32.const 0) - ) - ) - (i32.const -1) - ) - (block - (local.set $3 - (if (result i32) - (i32.and - (local.tee $2 - (i32.add - (local.tee $4 - (i32.load - (i32.const 652) - ) - ) - (i32.const -1) - ) - ) - (local.tee $3 - (local.get $1) - ) - ) - (i32.add - (i32.sub - (local.get $5) - (local.get $3) - ) - (i32.and - (i32.add - (local.get $2) - (local.get $3) - ) - (i32.sub - (i32.const 0) - (local.get $4) - ) - ) - ) - (local.get $5) - ) - ) - (local.set $9 - (i32.add - (local.tee $4 - (i32.load - (i32.const 608) - ) - ) - (local.get $3) - ) - ) - (if - (i32.and - (i32.gt_u - (local.get $3) - (local.get $0) - ) - (i32.lt_u - (local.get $3) - (i32.const 2147483647) - ) - ) - (block - (if - (local.tee $2 - (i32.load - (i32.const 616) - ) - ) - (br_if $label$break$L279 - (i32.or - (i32.le_u - (local.get $9) - (local.get $4) - ) - (i32.gt_u - (local.get $9) - (local.get $2) - ) - ) - ) - ) - (br_if $__rjti$13 - (i32.eq - (local.tee $2 - (call $_sbrk - (local.get $3) - ) - ) - (local.get $1) - ) - ) - (br $__rjti$5) - ) - ) - ) - ) - (br $label$break$L279) - ) - (local.set $1 - (local.get $3) - ) - (local.set $4 - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - (if - (i32.and - (i32.gt_u - (local.get $11) - (local.get $1) - ) - (i32.and - (i32.lt_u - (local.get $1) - (i32.const 2147483647) - ) - (i32.ne - (local.get $2) - (i32.const -1) - ) - ) - ) - (if - (i32.lt_u - (local.tee $3 - (i32.and - (i32.add - (i32.sub - (local.get $8) - (local.get $1) - ) - (local.tee $3 - (i32.load - (i32.const 656) - ) - ) - ) - (i32.sub - (i32.const 0) - (local.get $3) - ) - ) - ) - (i32.const 2147483647) - ) - (if - (i32.eq - (call $_sbrk - (local.get $3) - ) - (i32.const -1) - ) - (block - (drop - (call $_sbrk - (local.get $4) - ) - ) - (br $label$break$L279) - ) - (local.set $3 - (i32.add - (local.get $3) - (local.get $1) - ) - ) - ) - (local.set $3 - (local.get $1) - ) - ) - (local.set $3 - (local.get $1) - ) - ) - (if - (i32.ne - (local.get $2) - (i32.const -1) - ) - (block - (local.set $1 - (local.get $2) - ) - (br $__rjti$13) - ) - ) - ) - (i32.store - (i32.const 620) - (i32.or - (i32.load - (i32.const 620) - ) - (i32.const 4) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $5) - (i32.const 2147483647) - ) - (if - (i32.and - (i32.lt_u - (local.tee $1 - (call $_sbrk - (local.get $5) - ) - ) - (local.tee $3 - (call $_sbrk - (i32.const 0) - ) - ) - ) - (i32.and - (i32.ne - (local.get $1) - (i32.const -1) - ) - (i32.ne - (local.get $3) - (i32.const -1) - ) - ) - ) - (br_if $__rjti$13 - (i32.gt_u - (local.tee $3 - (i32.sub - (local.get $3) - (local.get $1) - ) - ) - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - ) - ) - ) - (br $__rjto$13) - ) - (i32.store - (i32.const 608) - (local.tee $2 - (i32.add - (i32.load - (i32.const 608) - ) - (local.get $3) - ) - ) - ) - (if - (i32.gt_u - (local.get $2) - (i32.load - (i32.const 612) - ) - ) - (i32.store - (i32.const 612) - (local.get $2) - ) - ) - (block $do-once40 - (if - (local.tee $6 - (i32.load - (i32.const 200) - ) - ) - (block - (local.set $2 - (i32.const 624) - ) - (block $__rjto$10 - (block $__rjti$10 - (loop $while-in45 - (br_if $__rjti$10 - (i32.eq - (local.get $1) - (i32.add - (local.tee $11 - (i32.load - (local.get $2) - ) - ) - (local.tee $5 - (i32.load - (local.tee $4 - (i32.add - (local.get $2) - (i32.const 4) - ) - ) - ) - ) - ) - ) - ) - (br_if $while-in45 - (local.tee $2 - (i32.load offset=8 - (local.get $2) - ) - ) - ) - ) - (br $__rjto$10) - ) - (if - (i32.eqz - (i32.and - (i32.load offset=12 - (local.get $2) - ) - (i32.const 8) - ) - ) - (if - (i32.and - (i32.lt_u - (local.get $6) - (local.get $1) - ) - (i32.ge_u - (local.get $6) - (local.get $11) - ) - ) - (block - (i32.store - (local.get $4) - (i32.add - (local.get $5) - (local.get $3) - ) - ) - (local.set $2 - (i32.add - (local.get $6) - (local.tee $1 - (select - (i32.and - (i32.sub - (i32.const 0) - (local.tee $1 - (i32.add - (local.get $6) - (i32.const 8) - ) - ) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (local.get $1) - (i32.const 7) - ) - ) - ) - ) - ) - (local.set $1 - (i32.add - (i32.sub - (local.get $3) - (local.get $1) - ) - (i32.load - (i32.const 188) - ) - ) - ) - (i32.store - (i32.const 200) - (local.get $2) - ) - (i32.store - (i32.const 188) - (local.get $1) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store offset=4 - (i32.add - (local.get $2) - (local.get $1) - ) - (i32.const 40) - ) - (i32.store - (i32.const 204) - (i32.load - (i32.const 664) - ) - ) - (br $do-once40) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $1) - (local.tee $4 - (i32.load - (i32.const 192) - ) - ) - ) - (block - (i32.store - (i32.const 192) - (local.get $1) - ) - (local.set $4 - (local.get $1) - ) - ) - ) - (local.set $11 - (i32.add - (local.get $1) - (local.get $3) - ) - ) - (local.set $2 - (i32.const 624) - ) - (block $__rjto$11 - (block $__rjti$11 - (loop $while-in47 - (if - (i32.eq - (i32.load - (local.get $2) - ) - (local.get $11) - ) - (block - (local.set $5 - (local.get $2) - ) - (br $__rjti$11) - ) - ) - (br_if $while-in47 - (local.tee $2 - (i32.load offset=8 - (local.get $2) - ) - ) - ) - (local.set $4 - (i32.const 624) - ) - ) - (br $__rjto$11) - ) - (if - (i32.and - (i32.load offset=12 - (local.get $2) - ) - (i32.const 8) - ) - (local.set $4 - (i32.const 624) - ) - (block - (i32.store - (local.get $5) - (local.get $1) - ) - (i32.store - (local.tee $2 - (i32.add - (local.get $2) - (i32.const 4) - ) - ) - (i32.add - (i32.load - (local.get $2) - ) - (local.get $3) - ) - ) - (local.set $8 - (i32.add - (local.tee $9 - (i32.add - (local.get $1) - (select - (i32.and - (i32.sub - (i32.const 0) - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (local.get $1) - (i32.const 7) - ) - ) - ) - ) - (local.get $0) - ) - ) - (local.set $7 - (i32.sub - (i32.sub - (local.tee $5 - (i32.add - (local.get $11) - (select - (i32.and - (i32.sub - (i32.const 0) - (local.tee $1 - (i32.add - (local.get $11) - (i32.const 8) - ) - ) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (local.get $1) - (i32.const 7) - ) - ) - ) - ) - (local.get $9) - ) - (local.get $0) - ) - ) - (i32.store offset=4 - (local.get $9) - (i32.or - (local.get $0) - (i32.const 3) - ) - ) - (block $do-once48 - (if - (i32.eq - (local.get $5) - (local.get $6) - ) - (block - (i32.store - (i32.const 188) - (local.tee $0 - (i32.add - (i32.load - (i32.const 188) - ) - (local.get $7) - ) - ) - ) - (i32.store - (i32.const 200) - (local.get $8) - ) - (i32.store offset=4 - (local.get $8) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - ) - (block - (if - (i32.eq - (local.get $5) - (i32.load - (i32.const 196) - ) - ) - (block - (i32.store - (i32.const 184) - (local.tee $0 - (i32.add - (i32.load - (i32.const 184) - ) - (local.get $7) - ) - ) - ) - (i32.store - (i32.const 196) - (local.get $8) - ) - (i32.store offset=4 - (local.get $8) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $8) - (local.get $0) - ) - (local.get $0) - ) - (br $do-once48) - ) - ) - (i32.store - (local.tee $0 - (i32.add - (local.tee $0 - (if (result i32) - (i32.eq - (i32.and - (local.tee $0 - (i32.load offset=4 - (local.get $5) - ) - ) - (i32.const 3) - ) - (i32.const 1) - ) - (block (result i32) - (local.set $11 - (i32.and - (local.get $0) - (i32.const -8) - ) - ) - (local.set $1 - (i32.shr_u - (local.get $0) - (i32.const 3) - ) - ) - (block $label$break$L331 - (if - (i32.lt_u - (local.get $0) - (i32.const 256) - ) - (block - (local.set $2 - (i32.load offset=12 - (local.get $5) - ) - ) - (block $do-once51 - (if - (i32.ne - (local.tee $3 - (i32.load offset=8 - (local.get $5) - ) - ) - (local.tee $0 - (i32.add - (i32.shl - (local.get $1) - (i32.const 3) - ) - (i32.const 216) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $3) - (local.get $4) - ) - (call $_abort) - ) - (br_if $do-once51 - (i32.eq - (i32.load offset=12 - (local.get $3) - ) - (local.get $5) - ) - ) - (call $_abort) - ) - ) - ) - (if - (i32.eq - (local.get $2) - (local.get $3) - ) - (block - (i32.store - (i32.const 176) - (i32.and - (i32.load - (i32.const 176) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $1) - ) - (i32.const -1) - ) - ) - ) - (br $label$break$L331) - ) - ) - (block $do-once53 - (if - (i32.eq - (local.get $2) - (local.get $0) - ) - (local.set $15 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - (block - (if - (i32.lt_u - (local.get $2) - (local.get $4) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - ) - (local.get $5) - ) - (block - (local.set $15 - (local.get $0) - ) - (br $do-once53) - ) - ) - (call $_abort) - ) - ) - ) - (i32.store offset=12 - (local.get $3) - (local.get $2) - ) - (i32.store - (local.get $15) - (local.get $3) - ) - ) - (block - (local.set $6 - (i32.load offset=24 - (local.get $5) - ) - ) - (block $do-once55 - (if - (i32.eq - (local.tee $0 - (i32.load offset=12 - (local.get $5) - ) - ) - (local.get $5) - ) - (block - (if - (i32.eqz - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.tee $3 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - (i32.const 4) - ) - ) - ) - ) - ) - (if - (local.tee $1 - (i32.load - (local.get $3) - ) - ) - (local.set $0 - (local.get $3) - ) - (block - (local.set $12 - (i32.const 0) - ) - (br $do-once55) - ) - ) - ) - (loop $while-in58 - (if - (local.tee $3 - (i32.load - (local.tee $2 - (i32.add - (local.get $1) - (i32.const 20) - ) - ) - ) - ) - (block - (local.set $1 - (local.get $3) - ) - (local.set $0 - (local.get $2) - ) - (br $while-in58) - ) - ) - (if - (local.tee $3 - (i32.load - (local.tee $2 - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - ) - (block - (local.set $1 - (local.get $3) - ) - (local.set $0 - (local.get $2) - ) - (br $while-in58) - ) - ) - ) - (if - (i32.lt_u - (local.get $0) - (local.get $4) - ) - (call $_abort) - (block - (i32.store - (local.get $0) - (i32.const 0) - ) - (local.set $12 - (local.get $1) - ) - ) - ) - ) - (block - (if - (i32.lt_u - (local.tee $2 - (i32.load offset=8 - (local.get $5) - ) - ) - (local.get $4) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load - (local.tee $3 - (i32.add - (local.get $2) - (i32.const 12) - ) - ) - ) - (local.get $5) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - (local.get $5) - ) - (block - (i32.store - (local.get $3) - (local.get $0) - ) - (i32.store - (local.get $1) - (local.get $2) - ) - (local.set $12 - (local.get $0) - ) - ) - (call $_abort) - ) - ) - ) - ) - (br_if $label$break$L331 - (i32.eqz - (local.get $6) - ) - ) - (block $do-once59 - (if - (i32.eq - (local.get $5) - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $1 - (i32.load offset=28 - (local.get $5) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - ) - ) - (block - (i32.store - (local.get $0) - (local.get $12) - ) - (br_if $do-once59 - (local.get $12) - ) - (i32.store - (i32.const 180) - (i32.and - (i32.load - (i32.const 180) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $1) - ) - (i32.const -1) - ) - ) - ) - (br $label$break$L331) - ) - (block - (if - (i32.lt_u - (local.get $6) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - ) - (local.get $5) - ) - (i32.store - (local.get $0) - (local.get $12) - ) - (i32.store offset=20 - (local.get $6) - (local.get $12) - ) - ) - (br_if $label$break$L331 - (i32.eqz - (local.get $12) - ) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $12) - (local.tee $1 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (i32.store offset=24 - (local.get $12) - (local.get $6) - ) - (if - (local.tee $3 - (i32.load - (local.tee $0 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $3) - (local.get $1) - ) - (call $_abort) - (block - (i32.store offset=16 - (local.get $12) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $12) - ) - ) - ) - ) - (br_if $label$break$L331 - (i32.eqz - (local.tee $0 - (i32.load offset=4 - (local.get $0) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $0) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store offset=20 - (local.get $12) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $12) - ) - ) - ) - ) - ) - ) - (local.set $7 - (i32.add - (local.get $11) - (local.get $7) - ) - ) - (i32.add - (local.get $5) - (local.get $11) - ) - ) - (local.get $5) - ) - ) - (i32.const 4) - ) - ) - (i32.and - (i32.load - (local.get $0) - ) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $8) - (i32.or - (local.get $7) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $8) - (local.get $7) - ) - (local.get $7) - ) - (local.set $0 - (i32.shr_u - (local.get $7) - (i32.const 3) - ) - ) - (if - (i32.lt_u - (local.get $7) - (i32.const 256) - ) - (block - (local.set $3 - (i32.add - (i32.shl - (local.get $0) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (block $do-once63 - (if - (i32.and - (local.tee $1 - (i32.load - (i32.const 176) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - (block - (if - (i32.ge_u - (local.tee $0 - (i32.load - (local.tee $1 - (i32.add - (local.get $3) - (i32.const 8) - ) - ) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (block - (local.set $16 - (local.get $1) - ) - (local.set $10 - (local.get $0) - ) - (br $do-once63) - ) - ) - (call $_abort) - ) - (block - (i32.store - (i32.const 176) - (i32.or - (local.get $1) - (local.get $0) - ) - ) - (local.set $16 - (i32.add - (local.get $3) - (i32.const 8) - ) - ) - (local.set $10 - (local.get $3) - ) - ) - ) - ) - (i32.store - (local.get $16) - (local.get $8) - ) - (i32.store offset=12 - (local.get $10) - (local.get $8) - ) - (i32.store offset=8 - (local.get $8) - (local.get $10) - ) - (i32.store offset=12 - (local.get $8) - (local.get $3) - ) - (br $do-once48) - ) - ) - (local.set $3 - (i32.add - (i32.shl - (local.tee $2 - (block $do-once65 (result i32) - (if (result i32) - (local.tee $0 - (i32.shr_u - (local.get $7) - (i32.const 8) - ) - ) - (block (result i32) - (drop - (br_if $do-once65 - (i32.const 31) - (i32.gt_u - (local.get $7) - (i32.const 16777215) - ) - ) - ) - (i32.or - (i32.and - (i32.shr_u - (local.get $7) - (i32.add - (local.tee $0 - (i32.add - (i32.sub - (i32.const 14) - (i32.or - (i32.or - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $0) - (local.tee $3 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - (local.get $3) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $1) - (local.get $0) - ) - ) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.shr_u - (i32.shl - (local.get $1) - (local.get $0) - ) - (i32.const 15) - ) - ) - ) - (i32.const 7) - ) - ) - (i32.const 1) - ) - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - (i32.store offset=28 - (local.get $8) - (local.get $2) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $8) - (i32.const 16) - ) - ) - (i32.const 0) - ) - (i32.store - (local.get $0) - (i32.const 0) - ) - (if - (i32.eqz - (i32.and - (local.tee $1 - (i32.load - (i32.const 180) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $2) - ) - ) - ) - ) - (block - (i32.store - (i32.const 180) - (i32.or - (local.get $1) - (local.get $0) - ) - ) - (i32.store - (local.get $3) - (local.get $8) - ) - (i32.store offset=24 - (local.get $8) - (local.get $3) - ) - (i32.store offset=12 - (local.get $8) - (local.get $8) - ) - (i32.store offset=8 - (local.get $8) - (local.get $8) - ) - (br $do-once48) - ) - ) - (local.set $2 - (i32.shl - (local.get $7) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $2) - (i32.const 1) - ) - ) - (i32.eq - (local.get $2) - (i32.const 31) - ) - ) - ) - ) - (local.set $0 - (i32.load - (local.get $3) - ) - ) - (block $__rjto$7 - (block $__rjti$7 - (loop $while-in68 - (br_if $__rjti$7 - (i32.eq - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - (local.get $7) - ) - ) - (local.set $3 - (i32.shl - (local.get $2) - (i32.const 1) - ) - ) - (if - (local.tee $1 - (i32.load - (local.tee $2 - (i32.add - (i32.add - (local.get $0) - (i32.const 16) - ) - (i32.shl - (i32.shr_u - (local.get $2) - (i32.const 31) - ) - (i32.const 2) - ) - ) - ) - ) - ) - (block - (local.set $2 - (local.get $3) - ) - (local.set $0 - (local.get $1) - ) - (br $while-in68) - ) - ) - ) - (if - (i32.lt_u - (local.get $2) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store - (local.get $2) - (local.get $8) - ) - (i32.store offset=24 - (local.get $8) - (local.get $0) - ) - (i32.store offset=12 - (local.get $8) - (local.get $8) - ) - (i32.store offset=8 - (local.get $8) - (local.get $8) - ) - (br $do-once48) - ) - ) - (br $__rjto$7) - ) - (if - (i32.and - (i32.ge_u - (local.tee $2 - (i32.load - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - (local.tee $1 - (i32.load - (i32.const 192) - ) - ) - ) - (i32.ge_u - (local.get $0) - (local.get $1) - ) - ) - (block - (i32.store offset=12 - (local.get $2) - (local.get $8) - ) - (i32.store - (local.get $3) - (local.get $8) - ) - (i32.store offset=8 - (local.get $8) - (local.get $2) - ) - (i32.store offset=12 - (local.get $8) - (local.get $0) - ) - (i32.store offset=24 - (local.get $8) - (i32.const 0) - ) - ) - (call $_abort) - ) - ) - ) - ) - ) - (return - (i32.add - (local.get $9) - (i32.const 8) - ) - ) - ) - ) - ) - (loop $while-in70 - (block $while-out69 - (if - (i32.le_u - (local.tee $2 - (i32.load - (local.get $4) - ) - ) - (local.get $6) - ) - (br_if $while-out69 - (i32.gt_u - (local.tee $2 - (i32.add - (local.get $2) - (i32.load offset=4 - (local.get $4) - ) - ) - ) - (local.get $6) - ) - ) - ) - (local.set $4 - (i32.load offset=8 - (local.get $4) - ) - ) - (br $while-in70) - ) - ) - (local.set $10 - (i32.add - (local.tee $4 - (i32.add - (local.get $2) - (i32.const -47) - ) - ) - (i32.const 8) - ) - ) - (local.set $12 - (i32.add - (local.tee $11 - (select - (local.get $6) - (local.tee $4 - (i32.add - (local.get $4) - (select - (i32.and - (i32.sub - (i32.const 0) - (local.get $10) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (local.get $10) - (i32.const 7) - ) - ) - ) - ) - (i32.lt_u - (local.get $4) - (local.tee $10 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - ) - ) - ) - (i32.const 8) - ) - ) - (i32.store - (i32.const 200) - (local.tee $5 - (i32.add - (local.get $1) - (local.tee $4 - (select - (i32.and - (i32.sub - (i32.const 0) - (local.tee $4 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (local.get $4) - (i32.const 7) - ) - ) - ) - ) - ) - ) - (i32.store - (i32.const 188) - (local.tee $4 - (i32.sub - (i32.add - (local.get $3) - (i32.const -40) - ) - (local.get $4) - ) - ) - ) - (i32.store offset=4 - (local.get $5) - (i32.or - (local.get $4) - (i32.const 1) - ) - ) - (i32.store offset=4 - (i32.add - (local.get $5) - (local.get $4) - ) - (i32.const 40) - ) - (i32.store - (i32.const 204) - (i32.load - (i32.const 664) - ) - ) - (i32.store - (local.tee $4 - (i32.add - (local.get $11) - (i32.const 4) - ) - ) - (i32.const 27) - ) - (i32.store - (local.get $12) - (i32.load - (i32.const 624) - ) - ) - (i32.store offset=4 - (local.get $12) - (i32.load - (i32.const 628) - ) - ) - (i32.store offset=8 - (local.get $12) - (i32.load - (i32.const 632) - ) - ) - (i32.store offset=12 - (local.get $12) - (i32.load - (i32.const 636) - ) - ) - (i32.store - (i32.const 624) - (local.get $1) - ) - (i32.store - (i32.const 628) - (local.get $3) - ) - (i32.store - (i32.const 636) - (i32.const 0) - ) - (i32.store - (i32.const 632) - (local.get $12) - ) - (local.set $1 - (i32.add - (local.get $11) - (i32.const 24) - ) - ) - (loop $while-in72 - (i32.store - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (i32.const 7) - ) - (br_if $while-in72 - (i32.lt_u - (i32.add - (local.get $1) - (i32.const 4) - ) - (local.get $2) - ) - ) - ) - (if - (i32.ne - (local.get $11) - (local.get $6) - ) - (block - (i32.store - (local.get $4) - (i32.and - (i32.load - (local.get $4) - ) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $6) - (i32.or - (local.tee $5 - (i32.sub - (local.get $11) - (local.get $6) - ) - ) - (i32.const 1) - ) - ) - (i32.store - (local.get $11) - (local.get $5) - ) - (local.set $1 - (i32.shr_u - (local.get $5) - (i32.const 3) - ) - ) - (if - (i32.lt_u - (local.get $5) - (i32.const 256) - ) - (block - (local.set $2 - (i32.add - (i32.shl - (local.get $1) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (if - (i32.and - (local.tee $3 - (i32.load - (i32.const 176) - ) - ) - (local.tee $1 - (i32.shl - (i32.const 1) - (local.get $1) - ) - ) - ) - (if - (i32.lt_u - (local.tee $1 - (i32.load - (local.tee $3 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (local.set $17 - (local.get $3) - ) - (local.set $7 - (local.get $1) - ) - ) - ) - (block - (i32.store - (i32.const 176) - (i32.or - (local.get $3) - (local.get $1) - ) - ) - (local.set $17 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - (local.set $7 - (local.get $2) - ) - ) - ) - (i32.store - (local.get $17) - (local.get $6) - ) - (i32.store offset=12 - (local.get $7) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $7) - ) - (i32.store offset=12 - (local.get $6) - (local.get $2) - ) - (br $do-once40) - ) - ) - (local.set $2 - (i32.add - (i32.shl - (local.tee $4 - (if (result i32) - (local.tee $1 - (i32.shr_u - (local.get $5) - (i32.const 8) - ) - ) - (if (result i32) - (i32.gt_u - (local.get $5) - (i32.const 16777215) - ) - (i32.const 31) - (i32.or - (i32.and - (i32.shr_u - (local.get $5) - (i32.add - (local.tee $1 - (i32.add - (i32.sub - (i32.const 14) - (i32.or - (i32.or - (local.tee $1 - (i32.and - (i32.shr_u - (i32.add - (local.tee $3 - (i32.shl - (local.get $1) - (local.tee $2 - (i32.and - (i32.shr_u - (i32.add - (local.get $1) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - (local.get $2) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (i32.add - (local.tee $3 - (i32.shl - (local.get $3) - (local.get $1) - ) - ) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.shr_u - (i32.shl - (local.get $3) - (local.get $1) - ) - (i32.const 15) - ) - ) - ) - (i32.const 7) - ) - ) - (i32.const 1) - ) - (i32.shl - (local.get $1) - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - (i32.store offset=28 - (local.get $6) - (local.get $4) - ) - (i32.store offset=20 - (local.get $6) - (i32.const 0) - ) - (i32.store - (local.get $10) - (i32.const 0) - ) - (if - (i32.eqz - (i32.and - (local.tee $3 - (i32.load - (i32.const 180) - ) - ) - (local.tee $1 - (i32.shl - (i32.const 1) - (local.get $4) - ) - ) - ) - ) - (block - (i32.store - (i32.const 180) - (i32.or - (local.get $3) - (local.get $1) - ) - ) - (i32.store - (local.get $2) - (local.get $6) - ) - (i32.store offset=24 - (local.get $6) - (local.get $2) - ) - (i32.store offset=12 - (local.get $6) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $6) - ) - (br $do-once40) - ) - ) - (local.set $4 - (i32.shl - (local.get $5) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $4) - (i32.const 1) - ) - ) - (i32.eq - (local.get $4) - (i32.const 31) - ) - ) - ) - ) - (local.set $1 - (i32.load - (local.get $2) - ) - ) - (block $__rjto$9 - (block $__rjti$9 - (loop $while-in74 - (br_if $__rjti$9 - (i32.eq - (i32.and - (i32.load offset=4 - (local.get $1) - ) - (i32.const -8) - ) - (local.get $5) - ) - ) - (local.set $2 - (i32.shl - (local.get $4) - (i32.const 1) - ) - ) - (if - (local.tee $3 - (i32.load - (local.tee $4 - (i32.add - (i32.add - (local.get $1) - (i32.const 16) - ) - (i32.shl - (i32.shr_u - (local.get $4) - (i32.const 31) - ) - (i32.const 2) - ) - ) - ) - ) - ) - (block - (local.set $4 - (local.get $2) - ) - (local.set $1 - (local.get $3) - ) - (br $while-in74) - ) - ) - ) - (if - (i32.lt_u - (local.get $4) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store - (local.get $4) - (local.get $6) - ) - (i32.store offset=24 - (local.get $6) - (local.get $1) - ) - (i32.store offset=12 - (local.get $6) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $6) - ) - (br $do-once40) - ) - ) - (br $__rjto$9) - ) - (if - (i32.and - (i32.ge_u - (local.tee $4 - (i32.load - (local.tee $2 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - ) - ) - (local.tee $3 - (i32.load - (i32.const 192) - ) - ) - ) - (i32.ge_u - (local.get $1) - (local.get $3) - ) - ) - (block - (i32.store offset=12 - (local.get $4) - (local.get $6) - ) - (i32.store - (local.get $2) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $4) - ) - (i32.store offset=12 - (local.get $6) - (local.get $1) - ) - (i32.store offset=24 - (local.get $6) - (i32.const 0) - ) - ) - (call $_abort) - ) - ) - ) - ) - ) - (block - (if - (i32.or - (i32.eqz - (local.tee $2 - (i32.load - (i32.const 192) - ) - ) - ) - (i32.lt_u - (local.get $1) - (local.get $2) - ) - ) - (i32.store - (i32.const 192) - (local.get $1) - ) - ) - (i32.store - (i32.const 624) - (local.get $1) - ) - (i32.store - (i32.const 628) - (local.get $3) - ) - (i32.store - (i32.const 636) - (i32.const 0) - ) - (i32.store - (i32.const 212) - (i32.load - (i32.const 648) - ) - ) - (i32.store - (i32.const 208) - (i32.const -1) - ) - (local.set $2 - (i32.const 0) - ) - (loop $while-in43 - (i32.store offset=12 - (local.tee $4 - (i32.add - (i32.shl - (local.get $2) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (local.get $4) - ) - (i32.store offset=8 - (local.get $4) - (local.get $4) - ) - (br_if $while-in43 - (i32.ne - (local.tee $2 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (i32.const 32) - ) - ) - ) - (i32.store - (i32.const 200) - (local.tee $2 - (i32.add - (local.get $1) - (local.tee $1 - (select - (i32.and - (i32.sub - (i32.const 0) - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (local.get $1) - (i32.const 7) - ) - ) - ) - ) - ) - ) - (i32.store - (i32.const 188) - (local.tee $1 - (i32.sub - (i32.add - (local.get $3) - (i32.const -40) - ) - (local.get $1) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store offset=4 - (i32.add - (local.get $2) - (local.get $1) - ) - (i32.const 40) - ) - (i32.store - (i32.const 204) - (i32.load - (i32.const 664) - ) - ) - ) - ) - ) - (br_if $folding-inner0 - (i32.gt_u - (local.tee $1 - (i32.load - (i32.const 188) - ) - ) - (local.get $0) - ) - ) - ) - (i32.store - (call $___errno_location) - (i32.const 12) - ) - (return - (i32.const 0) - ) - ) - (i32.store - (i32.const 188) - (local.tee $3 - (i32.sub - (local.get $1) - (local.get $0) - ) - ) - ) - (i32.store - (i32.const 200) - (local.tee $1 - (i32.add - (local.tee $2 - (i32.load - (i32.const 200) - ) - ) - (local.get $0) - ) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $3) - (i32.const 1) - ) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $0) - (i32.const 3) - ) - ) - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - ;; CHECK: (func $_free (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 i32) - ;; CHECK-NEXT: (local $9 i32) - ;; CHECK-NEXT: (local $10 i32) - ;; CHECK-NEXT: (local $11 i32) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 i32) - ;; CHECK-NEXT: (local $15 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block558 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block562 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block564 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block566 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block568 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block572 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block574 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 - ;; CHECK-NEXT: (i32.load offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block578 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block581 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block583 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block585 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block587 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block588 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block592 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (block $block594 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load offset=28 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block596 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block598 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block599 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block603 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block607 - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block610 - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block611 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block612 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block616 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block617 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block619 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 188) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block622 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block624 - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block626 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block630 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block632 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block635 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.load offset=24 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once6 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=12 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block637 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block640 - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in9 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block642 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block644 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block646 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block647 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block651 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (block $block653 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load offset=28 - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block655 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block657 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block658 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $do-once4 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block664 - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block667 - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 196) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block669 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 184) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block671 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 216) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block674 - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block675 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 176) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16777215) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1048320) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 520192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 245760) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 480) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=28 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=20 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=16 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $do-once12 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block679 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__rjto$1 - ;; CHECK-NEXT: (block $__rjti$1 - ;; CHECK-NEXT: (loop $while-in15 - ;; CHECK-NEXT: (br_if $__rjti$1 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block681 - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: (block $block683 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $do-once12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__rjto$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block685 - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $_abort) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block686 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 180) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=24 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=12 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 208) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 208) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 632) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in17 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in17 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 208) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_free (param $0 i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local $10 i32) - (local $11 i32) - (local $12 i32) - (local $13 i32) - (local $14 i32) - (local $15 i32) - (if - (i32.eqz - (local.get $0) - ) - (return) - ) - (if - (i32.lt_u - (local.tee $1 - (i32.add - (local.get $0) - (i32.const -8) - ) - ) - (local.tee $11 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (local.tee $5 - (i32.and - (local.tee $7 - (i32.load - (i32.add - (local.get $0) - (i32.const -4) - ) - ) - ) - (i32.const 3) - ) - ) - (i32.const 1) - ) - (call $_abort) - ) - (local.set $8 - (i32.add - (local.get $1) - (local.tee $0 - (i32.and - (local.get $7) - (i32.const -8) - ) - ) - ) - ) - (block $do-once - (if - (i32.and - (local.get $7) - (i32.const 1) - ) - (block - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - ) - (block - (local.set $7 - (i32.load - (local.get $1) - ) - ) - (if - (i32.eqz - (local.get $5) - ) - (return) - ) - (if - (i32.lt_u - (local.tee $1 - (i32.add - (local.get $1) - (i32.sub - (i32.const 0) - (local.get $7) - ) - ) - ) - (local.get $11) - ) - (call $_abort) - ) - (local.set $0 - (i32.add - (local.get $7) - (local.get $0) - ) - ) - (if - (i32.eq - (local.get $1) - (i32.load - (i32.const 196) - ) - ) - (block - (if - (i32.ne - (i32.and - (local.tee $3 - (i32.load - (local.tee $2 - (i32.add - (local.get $8) - (i32.const 4) - ) - ) - ) - ) - (i32.const 3) - ) - (i32.const 3) - ) - (block - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - (br $do-once) - ) - ) - (i32.store - (i32.const 184) - (local.get $0) - ) - (i32.store - (local.get $2) - (i32.and - (local.get $3) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $0) - ) - (local.get $0) - ) - (return) - ) - ) - (local.set $5 - (i32.shr_u - (local.get $7) - (i32.const 3) - ) - ) - (if - (i32.lt_u - (local.get $7) - (i32.const 256) - ) - (block - (local.set $6 - (i32.load offset=12 - (local.get $1) - ) - ) - (if - (i32.ne - (local.tee $2 - (i32.load offset=8 - (local.get $1) - ) - ) - (local.tee $3 - (i32.add - (i32.shl - (local.get $5) - (i32.const 3) - ) - (i32.const 216) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $2) - (local.get $11) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load offset=12 - (local.get $2) - ) - (local.get $1) - ) - (call $_abort) - ) - ) - ) - (if - (i32.eq - (local.get $6) - (local.get $2) - ) - (block - (i32.store - (i32.const 176) - (i32.and - (i32.load - (i32.const 176) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $5) - ) - (i32.const -1) - ) - ) - ) - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - (br $do-once) - ) - ) - (if - (i32.eq - (local.get $6) - (local.get $3) - ) - (local.set $4 - (i32.add - (local.get $6) - (i32.const 8) - ) - ) - (block - (if - (i32.lt_u - (local.get $6) - (local.get $11) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $3 - (i32.add - (local.get $6) - (i32.const 8) - ) - ) - ) - (local.get $1) - ) - (local.set $4 - (local.get $3) - ) - (call $_abort) - ) - ) - ) - (i32.store offset=12 - (local.get $2) - (local.get $6) - ) - (i32.store - (local.get $4) - (local.get $2) - ) - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - (br $do-once) - ) - ) - (local.set $12 - (i32.load offset=24 - (local.get $1) - ) - ) - (block $do-once0 - (if - (i32.eq - (local.tee $4 - (i32.load offset=12 - (local.get $1) - ) - ) - (local.get $1) - ) - (block - (if - (i32.eqz - (local.tee $5 - (i32.load - (local.tee $4 - (i32.add - (local.tee $7 - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (i32.const 4) - ) - ) - ) - ) - ) - (if - (local.tee $5 - (i32.load - (local.get $7) - ) - ) - (local.set $4 - (local.get $7) - ) - (block - (local.set $6 - (i32.const 0) - ) - (br $do-once0) - ) - ) - ) - (loop $while-in - (if - (local.tee $7 - (i32.load - (local.tee $10 - (i32.add - (local.get $5) - (i32.const 20) - ) - ) - ) - ) - (block - (local.set $5 - (local.get $7) - ) - (local.set $4 - (local.get $10) - ) - (br $while-in) - ) - ) - (if - (local.tee $7 - (i32.load - (local.tee $10 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - ) - ) - (block - (local.set $5 - (local.get $7) - ) - (local.set $4 - (local.get $10) - ) - (br $while-in) - ) - ) - ) - (if - (i32.lt_u - (local.get $4) - (local.get $11) - ) - (call $_abort) - (block - (i32.store - (local.get $4) - (i32.const 0) - ) - (local.set $6 - (local.get $5) - ) - ) - ) - ) - (block - (if - (i32.lt_u - (local.tee $10 - (i32.load offset=8 - (local.get $1) - ) - ) - (local.get $11) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load - (local.tee $7 - (i32.add - (local.get $10) - (i32.const 12) - ) - ) - ) - (local.get $1) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $5 - (i32.add - (local.get $4) - (i32.const 8) - ) - ) - ) - (local.get $1) - ) - (block - (i32.store - (local.get $7) - (local.get $4) - ) - (i32.store - (local.get $5) - (local.get $10) - ) - (local.set $6 - (local.get $4) - ) - ) - (call $_abort) - ) - ) - ) - ) - (if - (local.get $12) - (block - (if - (i32.eq - (local.get $1) - (i32.load - (local.tee $4 - (i32.add - (i32.shl - (local.tee $5 - (i32.load offset=28 - (local.get $1) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - ) - ) - (block - (i32.store - (local.get $4) - (local.get $6) - ) - (if - (i32.eqz - (local.get $6) - ) - (block - (i32.store - (i32.const 180) - (i32.and - (i32.load - (i32.const 180) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $5) - ) - (i32.const -1) - ) - ) - ) - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - (br $do-once) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $12) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $4 - (i32.add - (local.get $12) - (i32.const 16) - ) - ) - ) - (local.get $1) - ) - (i32.store - (local.get $4) - (local.get $6) - ) - (i32.store offset=20 - (local.get $12) - (local.get $6) - ) - ) - (if - (i32.eqz - (local.get $6) - ) - (block - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - (br $do-once) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $6) - (local.tee $5 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (i32.store offset=24 - (local.get $6) - (local.get $12) - ) - (if - (local.tee $7 - (i32.load - (local.tee $4 - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $7) - (local.get $5) - ) - (call $_abort) - (block - (i32.store offset=16 - (local.get $6) - (local.get $7) - ) - (i32.store offset=24 - (local.get $7) - (local.get $6) - ) - ) - ) - ) - (if - (local.tee $4 - (i32.load offset=4 - (local.get $4) - ) - ) - (if - (i32.lt_u - (local.get $4) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store offset=20 - (local.get $6) - (local.get $4) - ) - (i32.store offset=24 - (local.get $4) - (local.get $6) - ) - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - ) - ) - (block - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - ) - ) - ) - (block - (local.set $2 - (local.get $1) - ) - (local.set $3 - (local.get $0) - ) - ) - ) - ) - ) - ) - (if - (i32.ge_u - (local.get $2) - (local.get $8) - ) - (call $_abort) - ) - (if - (i32.eqz - (i32.and - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $8) - (i32.const 4) - ) - ) - ) - ) - (i32.const 1) - ) - ) - (call $_abort) - ) - (if - (i32.and - (local.get $1) - (i32.const 2) - ) - (block - (i32.store - (local.get $0) - (i32.and - (local.get $1) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $3) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $2) - (local.get $3) - ) - (local.get $3) - ) - ) - (block - (if - (i32.eq - (local.get $8) - (i32.load - (i32.const 200) - ) - ) - (block - (i32.store - (i32.const 188) - (local.tee $0 - (i32.add - (i32.load - (i32.const 188) - ) - (local.get $3) - ) - ) - ) - (i32.store - (i32.const 200) - (local.get $2) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (if - (i32.ne - (local.get $2) - (i32.load - (i32.const 196) - ) - ) - (return) - ) - (i32.store - (i32.const 196) - (i32.const 0) - ) - (i32.store - (i32.const 184) - (i32.const 0) - ) - (return) - ) - ) - (if - (i32.eq - (local.get $8) - (i32.load - (i32.const 196) - ) - ) - (block - (i32.store - (i32.const 184) - (local.tee $0 - (i32.add - (i32.load - (i32.const 184) - ) - (local.get $3) - ) - ) - ) - (i32.store - (i32.const 196) - (local.get $2) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $2) - (local.get $0) - ) - (local.get $0) - ) - (return) - ) - ) - (local.set $5 - (i32.add - (i32.and - (local.get $1) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.set $3 - (i32.shr_u - (local.get $1) - (i32.const 3) - ) - ) - (block $do-once4 - (if - (i32.lt_u - (local.get $1) - (i32.const 256) - ) - (block - (local.set $4 - (i32.load offset=12 - (local.get $8) - ) - ) - (if - (i32.ne - (local.tee $1 - (i32.load offset=8 - (local.get $8) - ) - ) - (local.tee $0 - (i32.add - (i32.shl - (local.get $3) - (i32.const 3) - ) - (i32.const 216) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $1) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load offset=12 - (local.get $1) - ) - (local.get $8) - ) - (call $_abort) - ) - ) - ) - (if - (i32.eq - (local.get $4) - (local.get $1) - ) - (block - (i32.store - (i32.const 176) - (i32.and - (i32.load - (i32.const 176) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $3) - ) - (i32.const -1) - ) - ) - ) - (br $do-once4) - ) - ) - (if - (i32.eq - (local.get $4) - (local.get $0) - ) - (local.set $14 - (i32.add - (local.get $4) - (i32.const 8) - ) - ) - (block - (if - (i32.lt_u - (local.get $4) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $4) - (i32.const 8) - ) - ) - ) - (local.get $8) - ) - (local.set $14 - (local.get $0) - ) - (call $_abort) - ) - ) - ) - (i32.store offset=12 - (local.get $1) - (local.get $4) - ) - (i32.store - (local.get $14) - (local.get $1) - ) - ) - (block - (local.set $6 - (i32.load offset=24 - (local.get $8) - ) - ) - (block $do-once6 - (if - (i32.eq - (local.tee $0 - (i32.load offset=12 - (local.get $8) - ) - ) - (local.get $8) - ) - (block - (if - (i32.eqz - (local.tee $3 - (i32.load - (local.tee $0 - (i32.add - (local.tee $1 - (i32.add - (local.get $8) - (i32.const 16) - ) - ) - (i32.const 4) - ) - ) - ) - ) - ) - (if - (local.tee $3 - (i32.load - (local.get $1) - ) - ) - (local.set $0 - (local.get $1) - ) - (block - (local.set $9 - (i32.const 0) - ) - (br $do-once6) - ) - ) - ) - (loop $while-in9 - (if - (local.tee $1 - (i32.load - (local.tee $4 - (i32.add - (local.get $3) - (i32.const 20) - ) - ) - ) - ) - (block - (local.set $3 - (local.get $1) - ) - (local.set $0 - (local.get $4) - ) - (br $while-in9) - ) - ) - (if - (local.tee $1 - (i32.load - (local.tee $4 - (i32.add - (local.get $3) - (i32.const 16) - ) - ) - ) - ) - (block - (local.set $3 - (local.get $1) - ) - (local.set $0 - (local.get $4) - ) - (br $while-in9) - ) - ) - ) - (if - (i32.lt_u - (local.get $0) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store - (local.get $0) - (i32.const 0) - ) - (local.set $9 - (local.get $3) - ) - ) - ) - ) - (block - (if - (i32.lt_u - (local.tee $4 - (i32.load offset=8 - (local.get $8) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.ne - (i32.load - (local.tee $1 - (i32.add - (local.get $4) - (i32.const 12) - ) - ) - ) - (local.get $8) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - (local.get $8) - ) - (block - (i32.store - (local.get $1) - (local.get $0) - ) - (i32.store - (local.get $3) - (local.get $4) - ) - (local.set $9 - (local.get $0) - ) - ) - (call $_abort) - ) - ) - ) - ) - (if - (local.get $6) - (block - (if - (i32.eq - (local.get $8) - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $3 - (i32.load offset=28 - (local.get $8) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - ) - ) - (block - (i32.store - (local.get $0) - (local.get $9) - ) - (if - (i32.eqz - (local.get $9) - ) - (block - (i32.store - (i32.const 180) - (i32.and - (i32.load - (i32.const 180) - ) - (i32.xor - (i32.shl - (i32.const 1) - (local.get $3) - ) - (i32.const -1) - ) - ) - ) - (br $do-once4) - ) - ) - ) - (block - (if - (i32.lt_u - (local.get $6) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - ) - (if - (i32.eq - (i32.load - (local.tee $0 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - ) - (local.get $8) - ) - (i32.store - (local.get $0) - (local.get $9) - ) - (i32.store offset=20 - (local.get $6) - (local.get $9) - ) - ) - (br_if $do-once4 - (i32.eqz - (local.get $9) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $9) - (local.tee $3 - (i32.load - (i32.const 192) - ) - ) - ) - (call $_abort) - ) - (i32.store offset=24 - (local.get $9) - (local.get $6) - ) - (if - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $8) - (i32.const 16) - ) - ) - ) - ) - (if - (i32.lt_u - (local.get $1) - (local.get $3) - ) - (call $_abort) - (block - (i32.store offset=16 - (local.get $9) - (local.get $1) - ) - (i32.store offset=24 - (local.get $1) - (local.get $9) - ) - ) - ) - ) - (if - (local.tee $0 - (i32.load offset=4 - (local.get $0) - ) - ) - (if - (i32.lt_u - (local.get $0) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store offset=20 - (local.get $9) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $9) - ) - ) - ) - ) - ) - ) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (local.get $5) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $2) - (local.get $5) - ) - (local.get $5) - ) - (if - (i32.eq - (local.get $2) - (i32.load - (i32.const 196) - ) - ) - (block - (i32.store - (i32.const 184) - (local.get $5) - ) - (return) - ) - (local.set $3 - (local.get $5) - ) - ) - ) - ) - (local.set $0 - (i32.shr_u - (local.get $3) - (i32.const 3) - ) - ) - (if - (i32.lt_u - (local.get $3) - (i32.const 256) - ) - (block - (local.set $1 - (i32.add - (i32.shl - (local.get $0) - (i32.const 3) - ) - (i32.const 216) - ) - ) - (if - (i32.and - (local.tee $3 - (i32.load - (i32.const 176) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - (if - (i32.lt_u - (local.tee $0 - (i32.load - (local.tee $3 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - ) - ) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (local.set $15 - (local.get $3) - ) - (local.set $13 - (local.get $0) - ) - ) - ) - (block - (i32.store - (i32.const 176) - (i32.or - (local.get $3) - (local.get $0) - ) - ) - (local.set $15 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - (local.set $13 - (local.get $1) - ) - ) - ) - (i32.store - (local.get $15) - (local.get $2) - ) - (i32.store offset=12 - (local.get $13) - (local.get $2) - ) - (i32.store offset=8 - (local.get $2) - (local.get $13) - ) - (i32.store offset=12 - (local.get $2) - (local.get $1) - ) - (return) - ) - ) - (local.set $4 - (i32.add - (i32.shl - (local.tee $5 - (if (result i32) - (local.tee $0 - (i32.shr_u - (local.get $3) - (i32.const 8) - ) - ) - (if (result i32) - (i32.gt_u - (local.get $3) - (i32.const 16777215) - ) - (i32.const 31) - (i32.or - (i32.and - (i32.shr_u - (local.get $3) - (i32.add - (local.tee $0 - (i32.add - (i32.sub - (i32.const 14) - (i32.or - (i32.or - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $0) - (local.tee $4 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - (local.get $4) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.tee $1 - (i32.shl - (local.get $1) - (local.get $0) - ) - ) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - ) - (i32.shr_u - (i32.shl - (local.get $1) - (local.get $0) - ) - (i32.const 15) - ) - ) - ) - (i32.const 7) - ) - ) - (i32.const 1) - ) - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - ) - (i32.const 2) - ) - (i32.const 480) - ) - ) - (i32.store offset=28 - (local.get $2) - (local.get $5) - ) - (i32.store offset=20 - (local.get $2) - (i32.const 0) - ) - (i32.store offset=16 - (local.get $2) - (i32.const 0) - ) - (block $do-once12 - (if - (i32.and - (local.tee $1 - (i32.load - (i32.const 180) - ) - ) - (local.tee $0 - (i32.shl - (i32.const 1) - (local.get $5) - ) - ) - ) - (block - (local.set $5 - (i32.shl - (local.get $3) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $5) - (i32.const 1) - ) - ) - (i32.eq - (local.get $5) - (i32.const 31) - ) - ) - ) - ) - (local.set $0 - (i32.load - (local.get $4) - ) - ) - (block $__rjto$1 - (block $__rjti$1 - (loop $while-in15 - (br_if $__rjti$1 - (i32.eq - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.set $4 - (i32.shl - (local.get $5) - (i32.const 1) - ) - ) - (if - (local.tee $1 - (i32.load - (local.tee $5 - (i32.add - (i32.add - (local.get $0) - (i32.const 16) - ) - (i32.shl - (i32.shr_u - (local.get $5) - (i32.const 31) - ) - (i32.const 2) - ) - ) - ) - ) - ) - (block - (local.set $5 - (local.get $4) - ) - (local.set $0 - (local.get $1) - ) - (br $while-in15) - ) - ) - ) - (if - (i32.lt_u - (local.get $5) - (i32.load - (i32.const 192) - ) - ) - (call $_abort) - (block - (i32.store - (local.get $5) - (local.get $2) - ) - (i32.store offset=24 - (local.get $2) - (local.get $0) - ) - (i32.store offset=12 - (local.get $2) - (local.get $2) - ) - (i32.store offset=8 - (local.get $2) - (local.get $2) - ) - (br $do-once12) - ) - ) - (br $__rjto$1) - ) - (if - (i32.and - (i32.ge_u - (local.tee $4 - (i32.load - (local.tee $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - (local.tee $3 - (i32.load - (i32.const 192) - ) - ) - ) - (i32.ge_u - (local.get $0) - (local.get $3) - ) - ) - (block - (i32.store offset=12 - (local.get $4) - (local.get $2) - ) - (i32.store - (local.get $1) - (local.get $2) - ) - (i32.store offset=8 - (local.get $2) - (local.get $4) - ) - (i32.store offset=12 - (local.get $2) - (local.get $0) - ) - (i32.store offset=24 - (local.get $2) - (i32.const 0) - ) - ) - (call $_abort) - ) - ) - ) - (block - (i32.store - (i32.const 180) - (i32.or - (local.get $1) - (local.get $0) - ) - ) - (i32.store - (local.get $4) - (local.get $2) - ) - (i32.store offset=24 - (local.get $2) - (local.get $4) - ) - (i32.store offset=12 - (local.get $2) - (local.get $2) - ) - (i32.store offset=8 - (local.get $2) - (local.get $2) - ) - ) - ) - ) - (i32.store - (i32.const 208) - (local.tee $0 - (i32.add - (i32.load - (i32.const 208) - ) - (i32.const -1) - ) - ) - ) - (if - (local.get $0) - (return) - (local.set $0 - (i32.const 632) - ) - ) - (loop $while-in17 - (local.set $0 - (i32.add - (local.tee $3 - (i32.load - (local.get $0) - ) - ) - (i32.const 8) - ) - ) - (br_if $while-in17 - (local.get $3) - ) - ) - (i32.store - (i32.const 208) - (i32.const -1) - ) - ) - ;; CHECK: (func $runPostSets - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $runPostSets - (nop) - ) - ;; CHECK: (func $_i64Subtract (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_i64Subtract (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (global.set $tempRet0 - (i32.sub - (i32.sub - (local.get $1) - (local.get $3) - ) - (i32.gt_u - (local.get $2) - (local.get $0) - ) - ) - ) - (i32.sub - (local.get $0) - (local.get $2) - ) - ) - ;; CHECK: (func $_i64Add (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - (func $_i64Add (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (local $4 i32) - (global.set $tempRet0 - (i32.add - (i32.add - (local.get $1) - (local.get $3) - ) - (i32.lt_u - (local.tee $4 - (i32.add - (local.get $0) - (local.get $2) - ) - ) - (local.get $0) - ) - ) - ) - (local.get $4) - ) - ;; CHECK: (func $_memset (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block689 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block691 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block693 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block695 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_memset (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $4 - (i32.add - (local.get $0) - (local.get $2) - ) - ) - (if - (i32.ge_s - (local.get $2) - (i32.const 20) - ) - (block - (local.set $1 - (i32.and - (local.get $1) - (i32.const 255) - ) - ) - (if - (local.tee $3 - (i32.and - (local.get $0) - (i32.const 3) - ) - ) - (block - (local.set $3 - (i32.sub - (i32.add - (local.get $0) - (i32.const 4) - ) - (local.get $3) - ) - ) - (loop $while-in - (if - (i32.lt_s - (local.get $0) - (local.get $3) - ) - (block - (i32.store8 - (local.get $0) - (local.get $1) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (br $while-in) - ) - ) - ) - ) - ) - (local.set $3 - (i32.or - (i32.or - (i32.or - (local.get $1) - (i32.shl - (local.get $1) - (i32.const 8) - ) - ) - (i32.shl - (local.get $1) - (i32.const 16) - ) - ) - (i32.shl - (local.get $1) - (i32.const 24) - ) - ) - ) - (local.set $5 - (i32.and - (local.get $4) - (i32.const -4) - ) - ) - (loop $while-in1 - (if - (i32.lt_s - (local.get $0) - (local.get $5) - ) - (block - (i32.store - (local.get $0) - (local.get $3) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - (br $while-in1) - ) - ) - ) - ) - ) - (loop $while-in3 - (if - (i32.lt_s - (local.get $0) - (local.get $4) - ) - (block - (i32.store8 - (local.get $0) - (local.get $1) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (br $while-in3) - ) - ) - ) - (i32.sub - (local.get $0) - (local.get $2) - ) - ) - ;; CHECK: (func $_bitshift64Lshr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $_bitshift64Lshr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (if - (i32.lt_s - (local.get $2) - (i32.const 32) - ) - (block - (global.set $tempRet0 - (i32.shr_u - (local.get $1) - (local.get $2) - ) - ) - (return - (i32.or - (i32.shr_u - (local.get $0) - (local.get $2) - ) - (i32.shl - (i32.and - (local.get $1) - (i32.sub - (i32.shl - (i32.const 1) - (local.get $2) - ) - (i32.const 1) - ) - ) - (i32.sub - (i32.const 32) - (local.get $2) - ) - ) - ) - ) - ) - ) - (global.set $tempRet0 - (i32.const 0) - ) - (i32.shr_u - (local.get $1) - (i32.sub - (local.get $2) - (i32.const 32) - ) - ) - ) - ;; CHECK: (func $_bitshift64Shl (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $_bitshift64Shl (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (if - (i32.lt_s - (local.get $2) - (i32.const 32) - ) - (block - (global.set $tempRet0 - (i32.or - (i32.shl - (local.get $1) - (local.get $2) - ) - (i32.shr_u - (i32.and - (local.get $0) - (i32.shl - (i32.sub - (i32.shl - (i32.const 1) - (local.get $2) - ) - (i32.const 1) - ) - (i32.sub - (i32.const 32) - (local.get $2) - ) - ) - ) - (i32.sub - (i32.const 32) - (local.get $2) - ) - ) - ) - ) - (return - (i32.shl - (local.get $0) - (local.get $2) - ) - ) - ) - ) - (global.set $tempRet0 - (i32.shl - (local.get $0) - (i32.sub - (local.get $2) - (i32.const 32) - ) - ) - ) - (i32.const 0) - ) - ;; CHECK: (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4096) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (call $_emscripten_memcpy_big - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block698 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block701 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block703 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (if - (i32.ge_s - (local.get $2) - (i32.const 4096) - ) - (return - (call $_emscripten_memcpy_big - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ) - (local.set $3 - (local.get $0) - ) - (if - (i32.eq - (i32.and - (local.get $0) - (i32.const 3) - ) - (i32.and - (local.get $1) - (i32.const 3) - ) - ) - (block - (loop $while-in - (if - (i32.and - (local.get $0) - (i32.const 3) - ) - (block - (if - (i32.eqz - (local.get $2) - ) - (return - (local.get $3) - ) - ) - (i32.store8 - (local.get $0) - (i32.load8_s - (local.get $1) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (local.set $2 - (i32.sub - (local.get $2) - (i32.const 1) - ) - ) - (br $while-in) - ) - ) - ) - (loop $while-in1 - (if - (i32.ge_s - (local.get $2) - (i32.const 4) - ) - (block - (i32.store - (local.get $0) - (i32.load - (local.get $1) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 4) - ) - ) - (local.set $2 - (i32.sub - (local.get $2) - (i32.const 4) - ) - ) - (br $while-in1) - ) - ) - ) - ) - ) - (loop $while-in3 - (if - (i32.gt_s - (local.get $2) - (i32.const 0) - ) - (block - (i32.store8 - (local.get $0) - (i32.load8_s - (local.get $1) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (local.set $2 - (i32.sub - (local.get $2) - (i32.const 1) - ) - ) - (br $while-in3) - ) - ) - ) - (local.get $3) - ) - ;; CHECK: (func $___udivdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - ;; CHECK-NEXT: (call $___udivmoddi4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $___udivdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call $___udivmoddi4 - (local.get $0) - (local.get $1) - (local.get $2) - (local.get $3) - (i32.const 0) - ) - ) - ;; CHECK: (func $___uremdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (global.get $STACKTOP) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $___udivmoddi4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $STACKTOP - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $___uremdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (local $4 i32) - (local.set $4 - (global.get $STACKTOP) - ) - (global.set $STACKTOP - (i32.add - (global.get $STACKTOP) - (i32.const 16) - ) - ) - (drop - (call $___udivmoddi4 - (local.get $0) - (local.get $1) - (local.get $2) - (local.get $3) - (local.tee $0 - (local.get $4) - ) - ) - ) - (global.set $STACKTOP - (local.get $4) - ) - (global.set $tempRet0 - (i32.load offset=4 - (local.get $0) - ) - ) - (i32.load - (local.get $0) - ) - ) - ;; CHECK: (func $___udivmoddi4 (param $xl i32) (param $xh i32) (param $yl i32) (param $yh i32) (param $r i32) (result i32) - ;; CHECK-NEXT: (local $x64 i64) - ;; CHECK-NEXT: (local $y64 i64) - ;; CHECK-NEXT: (local.set $x64 - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (local.get $xl) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (local.get $xh) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y64 - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (local.get $yl) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (local.get $yh) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $r) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (local.get $r) - ;; CHECK-NEXT: (i64.rem_u - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: (local.get $y64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x64 - ;; CHECK-NEXT: (i64.div_u - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: (local.get $y64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $tempRet0 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $___udivmoddi4 (param $xl i32) (param $xh i32) (param $yl i32) (param $yh i32) (param $r i32) (result i32) - (local $x64 i64) - (local $y64 i64) - (local.set $x64 - (i64.or - (i64.extend_i32_u - (local.get $xl) - ) - (i64.shl - (i64.extend_i32_u - (local.get $xh) - ) - (i64.const 32) - ) - ) - ) - (local.set $y64 - (i64.or - (i64.extend_i32_u - (local.get $yl) - ) - (i64.shl - (i64.extend_i32_u - (local.get $yh) - ) - (i64.const 32) - ) - ) - ) - (if - (local.get $r) - (i64.store - (local.get $r) - (i64.rem_u - (local.get $x64) - (local.get $y64) - ) - ) - ) - (local.set $x64 - (i64.div_u - (local.get $x64) - (local.get $y64) - ) - ) - (global.set $tempRet0 - (i32.wrap_i64 - (i64.shr_u - (local.get $x64) - (i64.const 32) - ) - ) - ) - (i32.wrap_i64 - (local.get $x64) - ) - ) - ;; CHECK: (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$ii) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - (call_indirect (type $FUNCSIG$ii) - (local.get $1) - (i32.and - (local.get $0) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$iiii) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect (type $FUNCSIG$iiii) - (local.get $1) - (local.get $2) - (local.get $3) - (i32.add - (i32.and - (local.get $0) - (i32.const 7) - ) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $dynCall_vi (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (call_indirect (type $FUNCSIG$vi) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $dynCall_vi (param $0 i32) (param $1 i32) - (call_indirect (type $FUNCSIG$vi) - (local.get $1) - (i32.add - (i32.and - (local.get $0) - (i32.const 7) - ) - (i32.const 10) - ) - ) - ) - ;; CHECK: (func $b0 (param $0 i32) (result i32) - ;; CHECK-NEXT: (call $nullFunc_ii - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $b0 (param $0 i32) (result i32) - (call $nullFunc_ii - (i32.const 0) - ) - (i32.const 0) - ) - ;; CHECK: (func $b1 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (call $nullFunc_iiii - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $b1 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (call $nullFunc_iiii - (i32.const 1) - ) - (i32.const 0) - ) - ;; CHECK: (func $b2 (param $0 i32) - ;; CHECK-NEXT: (call $nullFunc_vi - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $b2 (param $0 i32) - (call $nullFunc_vi - (i32.const 2) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/inlining-optimizing.wast binaryen-99/test/lit/passes/inlining-optimizing.wast --- binaryen-108/test/lit/passes/inlining-optimizing.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining-optimizing.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --inlining-optimizing -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - (type $none_=>_none (func)) - (type $none_=>_i32 (func (result i32))) - ;; CHECK: (func $0 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $0 - (nop) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $1 - ;; $0 will be inlined into here. We will then optimize this function - but - ;; we do so *without* optimizing $0 (as inlining-optimizing only optimizes - ;; where it inlines, for efficiency). As part of the optimiziations, we will - ;; try to precompute the cast here, which will try to look up $0. We should - ;; not hit an assertion, rather we should skip precomputing it, the same as if - ;; we were optimizing $1 before $0 were added to the module. (In fact, we will - ;; be able to see that the cast cannot succeed, and will optimize it into an - ;; unreachable.) - (call $0) - (drop - (call_ref - (ref.cast - (ref.func $0) - (rtt.canon $none_=>_i32) - ) - ) - ) - ) -) - diff -Nru binaryen-108/test/lit/passes/inlining_splitting.wast binaryen-99/test/lit/passes/inlining_splitting.wast --- binaryen-108/test/lit/passes/inlining_splitting.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/inlining_splitting.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1702 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: foreach %s %t wasm-opt --inlining --optimize-level=3 --partial-inlining-ifs=4 --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $anyref_=>_anyref (func (param anyref) (result anyref))) - - ;; CHECK: (type $anyref_=>_none (func (param anyref))) - - ;; CHECK: (type $struct (struct )) - (type $struct (struct)) - - ;; CHECK: (type $i32_rtt_$struct_=>_none (func (param i32 (rtt $struct)))) - - ;; CHECK: (type $i64_i32_f64_=>_none (func (param i64 i32 f64))) - - ;; CHECK: (import "out" "func" (func $import)) - (import "out" "func" (func $import)) - - ;; CHECK: (global $glob i32 (i32.const 1)) - (global $glob i32 (i32.const 1)) - - ;; CHECK: (start $start-used-globally) - (start $start-used-globally) - - ;; Pattern A: functions beginning with - ;; - ;; if (simple) return; - - (func $maybe-work-hard (param $x i32) - ;; A function that does a quick check before any heavy work. We can outline - ;; the heavy work, so that the condition can be inlined. - ;; - ;; This function (and others lower down that we also optimize) will vanish - ;; in the output. Part of it will be inlined into its caller, below, and - ;; the rest will be outlined into a new function with suffix "outlined". - (if - (local.get $x) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-maybe-work-hard - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard1 - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-maybe-work-hard - ;; Call the above function to verify that we can in fact inline it after - ;; splitting. We should see each of these three calls replaced by inlined - ;; code performing the if from $maybe-work-hard, and depending on that - ;; result they each call the outlined code that must *not* be inlined. - ;; - ;; Note that we must call more than once, otherwise given a single use we - ;; will always inline the entire thing. - (call $maybe-work-hard (i32.const 1)) - (call $maybe-work-hard (i32.const 2)) - (call $maybe-work-hard (i32.const 3)) - ) - - (func $just-if (param $x i32) - ;; As above, but all we have is an if. - (if - (local.get $x) - (loop $l - (call $import) - (br_if $l - (local.get $x) - ) - ) - ) - ) - - ;; CHECK: (func $call-just-if - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$just-if - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (call $byn-split-outlined-B$just-if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$just-if0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (call $byn-split-outlined-B$just-if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-just-if - (call $just-if (i32.const 1)) - (call $just-if (i32.const 2)) - ) - - ;; CHECK: (func $br-to-toplevel (param $x i32) - ;; CHECK-NEXT: (block $toplevel - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (br $toplevel) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br-to-toplevel (param $x i32) - (block $toplevel - (if - (local.get $x) - (block - (if - (local.get $x) - ;; A br to the toplevel block prevents us from outlining this code, - ;; as we can't outline a br without its target. - (br $toplevel) - (call $import) - ) - ) - ) - ) - ) - - ;; CHECK: (func $call-br-to-toplevel - ;; CHECK-NEXT: (call $br-to-toplevel - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $br-to-toplevel - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-br-to-toplevel - (call $br-to-toplevel (i32.const 1)) - (call $br-to-toplevel (i32.const 2)) - ) - - ;; CHECK: (func $nondefaultable-param (param $x i32) (param $y (rtt $struct)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nondefaultable-param (param $x i32) (param $y (rtt $struct)) - ;; The RTT param here prevents us from even being inlined, even with - ;; splitting. - (if - (local.get $x) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-nondefaultable-param - ;; CHECK-NEXT: (call $nondefaultable-param - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-nondefaultable-param - (call $nondefaultable-param (i32.const 0) (rtt.canon $struct)) - ) - - (func $many-params (param $x i64) (param $y i32) (param $z f64) - ;; Test that we can optimize this function even though it has multiple - ;; parameters, and it is not the very first one that we use in the - ;; condition. - (if - (local.get $y) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-many-params - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 f64) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$many-params - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$many-params - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$many-params0 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$many-params - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-many-params - ;; Call the above function to verify that we can in fact inline it after - ;; splitting. We should see each of these three calls replaced by inlined - ;; code performing the if from $maybe-work-hard, and depending on that - ;; result they each call the outlined code that must *not* be inlined. - (call $many-params (i64.const 0) (i32.const 1) (f64.const 3.14159)) - (call $many-params (i64.const 0) (i32.const 1) (f64.const 3.14159)) - ) - - (func $condition-eqz (param $x i32) - (if - ;; More work in the condition, but work that we still consider worth - ;; optimizing: a unary op. - (i32.eqz - (local.get $x) - ) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-condition-eqz - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-eqz - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-eqz0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-condition-eqz - (call $condition-eqz (i32.const 0)) - (call $condition-eqz (i32.const 1)) - ) - - (func $condition-global - (if - ;; A global read, also worth splitting. - (global.get $glob) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-condition-global - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-global - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-global0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-condition-global - (call $condition-global) - (call $condition-global) - ) - - (func $condition-ref.is (param $x anyref) - (if - ;; A ref.is operation. - (ref.is_null - (local.get $x) - ) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-condition-ref.is - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-ref.is - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-ref.is - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-ref.is0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-ref.is - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-condition-ref.is - (call $condition-ref.is (ref.null any)) - (call $condition-ref.is (ref.null any)) - ) - - ;; CHECK: (func $condition-disallow-binary (param $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $condition-disallow-binary (param $x i32) - (if - ;; Work we do *not* allow (at least for now), a binary. - (i32.add - (local.get $x) - (local.get $x) - ) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-condition-disallow-binary - ;; CHECK-NEXT: (call $condition-disallow-binary - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $condition-disallow-binary - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-condition-disallow-binary - (call $condition-disallow-binary (i32.const 0)) - (call $condition-disallow-binary (i32.const 1)) - ) - - ;; CHECK: (func $condition-disallow-unreachable (param $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $condition-disallow-unreachable (param $x i32) - (if - ;; Work we do *not* allow (at least for now), an unreachable. - (i32.eqz - (unreachable) - ) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-condition-disallow-unreachable - ;; CHECK-NEXT: (call $condition-disallow-unreachable - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $condition-disallow-unreachable - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-condition-disallow-unreachable - (call $condition-disallow-unreachable (i32.const 0)) - (call $condition-disallow-unreachable (i32.const 1)) - ) - - ;; CHECK: (func $start-used-globally - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $start-used-globally - ;; This is optimizable even though it is the start function, that is is, - ;; having global uses of a function are not a problem for partial inlining - ;; (since we do not modify this function - we create new split pieces of - ;; it). - (if - (global.get $glob) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-start-used-globally - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$start-used-globally - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$start-used-globally0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-start-used-globally - (call $start-used-globally) - (call $start-used-globally) - ) - - (func $inlineable - ;; This looks optimizable, but it is also inlineable - so we do not need to - ;; split it. It will just be inlined directly, without any $outlined part - ;; that is split out. - (if - (global.get $glob) - (return) - ) - ) - - ;; CHECK: (func $call-inlineable - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$inlineable - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: (br $__inlined_func$inlineable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$inlineable0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: (br $__inlined_func$inlineable0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-inlineable - (call $inlineable) - (call $inlineable) - ) - - ;; CHECK: (func $if-not-first (param $x i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-not-first (param $x i32) - ;; Except for the initial nop, we should outline this. As the if is not - ;; first any more, we ignore it. - (nop) - (if - (local.get $x) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-if-not-first - ;; CHECK-NEXT: (call $if-not-first - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-not-first - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-if-not-first - (call $if-not-first (i32.const 0)) - (call $if-not-first (i32.const 1)) - ) - - ;; CHECK: (func $if-else (param $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else (param $x i32) - ;; An else in the if prevents us from recognizing the pattern we want. - (if - (local.get $x) - (return) - (nop) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-if-else - ;; CHECK-NEXT: (call $if-else - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-else - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-if-else - (call $if-else (i32.const 0)) - (call $if-else (i32.const 1)) - ) - - ;; CHECK: (func $if-non-return (param $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-non-return (param $x i32) - ;; Something other than a return in the if body prevents us from outlining. - (if - (local.get $x) - (unreachable) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-if-non-return - ;; CHECK-NEXT: (call $if-non-return - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-non-return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-if-non-return - (call $if-non-return (i32.const 0)) - (call $if-non-return (i32.const 1)) - ) - - (func $colliding-name (param $x i32) - ;; When we outline this, the name should not collide with that of the - ;; function after us. - (if - (local.get $x) - (return) - ) - (loop $l - (call $import) - (br $l) - ) - ) - - ;; CHECK: (func $call-colliding-name - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$colliding-name - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_0 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$colliding-name0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-colliding-name - (call $colliding-name (i32.const 0)) - (call $colliding-name (i32.const 1)) - ) - - ;; CHECK: (func $byn-split-outlined-A$colliding-name - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $byn-split-outlined-A$colliding-name - ;; This function's name might collide with the split function we create for - ;; the above function; the split function's name must be fixed up. - ) - - ;; Pattern B: functions containing - ;; - ;; if (simple1) heavy-work-that-is-unreachable; - ;; if (simple..) heavy-work-that-is-unreachable; - ;; simplek - - (func $error-if-null (param $x anyref) (result anyref) - ;; A "as non null" function: If the input is null, issue an error somehow - ;; (here, by calling an import, but could also be a throwing of an - ;; exception). If not null, return the value. - (if - (ref.is_null - (local.get $x) - ) - (block - (call $import) - (unreachable) - ) - ) - (local.get $x) - ) - - ;; CHECK: (func $call-error-if-null - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$error-if-null (result anyref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$error-if-null - ;; CHECK-NEXT: (call $byn-split-outlined-B$error-if-null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$error-if-null0 (result anyref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$error-if-null0 - ;; CHECK-NEXT: (call $byn-split-outlined-B$error-if-null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-error-if-null - (drop (call $error-if-null (ref.null any))) - (drop (call $error-if-null (ref.null any))) - ) - - ;; CHECK: (func $too-many (param $x anyref) (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - (func $too-many (param $x anyref) (result anyref) - (if - (ref.is_null - (local.get $x) - ) - (block - (call $import) - (unreachable) - ) - ) - (nop) ;; An extra operation here prevents us from identifying the pattern. - (local.get $x) - ) - - ;; CHECK: (func $call-too-many - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $too-many - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $too-many - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-too-many - (drop (call $too-many (ref.null any))) - (drop (call $too-many (ref.null any))) - ) - - ;; CHECK: (func $tail-not-simple (param $x anyref) (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $tail-not-simple (param $x anyref) (result anyref) - (if - (ref.is_null - (local.get $x) - ) - (block - (call $import) - (unreachable) - ) - ) - (unreachable) ;; This prevents us from optimizing - ) - - ;; CHECK: (func $call-tail-not-simple - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-not-simple - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $tail-not-simple - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-tail-not-simple - (drop (call $tail-not-simple (ref.null any))) - (drop (call $tail-not-simple (ref.null any))) - ) - - (func $reachable-if-body (param $x anyref) (result anyref) - (if - (ref.is_null - (local.get $x) - ) - ;; It is ok if the body is not unreachable (so long as it contains no - ;; returns). We will optimize this, and just do a call to the outlined - ;; code, without a return of a value here. - (call $import) - ) - (local.get $x) - ) - - ;; CHECK: (func $call-reachable-if-body - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (local $2 anyref) - ;; CHECK-NEXT: (local $3 anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$reachable-if-body (result anyref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$reachable-if-body - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$reachable-if-body0 (result anyref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$reachable-if-body0 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-reachable-if-body - ;; Note that the above contains - ;; - ;; (block $__inlined_func$byn-split-outlined-B$reachable-if-body - ;; - ;; which indicates that we've inlined the outlined function. That seems odd, - ;; but it is the result of the if's body being just a call. When we outline, - ;; we end up with a function that all it does is make that call - which is - ;; worth inlining in the normal way (to avoid two calls). As a result of all - ;; that, we end up inlining *all* of $reachable-if-body, just by a - ;; roundabout way (split, outline, then inline). While this seems odd, each - ;; step along the way makes sense, and the result is a good one (might be a - ;; little hard to see before opts remove the extra block cruft etc.). - ;; - ;; We could avoid this if we detected that the if body is just a call, and - ;; not done any outlining - just done that call. That would be more - ;; efficient, but it would make the code more complicated, and the result is - ;; the same. - (drop (call $reachable-if-body (ref.null any))) - (drop (call $reachable-if-body (ref.null any))) - ) - - ;; CHECK: (func $reachable-if-body-return (param $x anyref) (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - (func $reachable-if-body-return (param $x anyref) (result anyref) - (if - (ref.is_null - (local.get $x) - ) - (if - (i32.const 1) - ;; The return here prevents the optimization. - (return - (local.get $x) - ) - (call $import) - ) - ) - (local.get $x) - ) - - ;; CHECK: (func $call-reachable-if-body-return - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $reachable-if-body-return - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $reachable-if-body-return - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-reachable-if-body-return - (drop (call $reachable-if-body-return (ref.null any))) - (drop (call $reachable-if-body-return (ref.null any))) - ) - - (func $unreachable-if-body-no-result (param $x anyref) - (if - (ref.is_null - (local.get $x) - ) - ;; The if body is unreachable, but the function has no returned value. - ;; When we outline this code, we should not try to return a value. - (block - (call $import) - (unreachable) - ) - ) - ) - - ;; CHECK: (func $call-unreachable-if-body-no-result - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$unreachable-if-body-no-result - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-B$unreachable-if-body-no-result - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$unreachable-if-body-no-result0 - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-B$unreachable-if-body-no-result - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-unreachable-if-body-no-result - (call $unreachable-if-body-no-result (ref.null any)) - (call $unreachable-if-body-no-result (ref.null any)) - ) - - (func $multi-if (param $x anyref) (result anyref) - (if - (ref.is_null - (local.get $x) - ) - (call $import) - ) - ;; A second if. We can outline both if bodies. - (if - (ref.is_func - (local.get $x) - ) - (loop $x - (call $import) - (br_if $x - (global.get $glob) - ) - ) - ) - (local.get $x) - ) - - ;; CHECK: (func $call-multi-if - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local $1 anyref) - ;; CHECK-NEXT: (local $2 anyref) - ;; CHECK-NEXT: (local $3 anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$multi-if (result anyref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$multi-if - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_func - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_0 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$multi-if0 (result anyref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$multi-if0 - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_func - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-multi-if - (drop (call $multi-if (ref.null any))) - (drop (call $multi-if (ref.null func))) - ) - - ;; CHECK: (func $too-many-ifs (param $x anyref) (result anyref) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $import) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - (func $too-many-ifs (param $x anyref) (result anyref) - ;; 5 ifs, which is too many. - (if - (ref.is_null - (local.get $x) - ) - (call $import) - ) - (if - (ref.is_null - (local.get $x) - ) - (call $import) - ) - (if - (ref.is_null - (local.get $x) - ) - (call $import) - ) - (if - (ref.is_null - (local.get $x) - ) - (call $import) - ) - (if - (ref.is_null - (local.get $x) - ) - (call $import) - ) - (local.get $x) - ) - - ;; CHECK: (func $call-too-many-ifs - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $too-many-ifs - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $too-many-ifs - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-too-many-ifs - (drop (call $too-many-ifs (ref.null any))) - (drop (call $too-many-ifs (ref.null func))) - ) -) - -;; CHECK: (func $byn-split-outlined-A$maybe-work-hard (param $x i32) -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-B$just-if (param $x i32) -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br_if $l -;; CHECK-NEXT: (local.get $x) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$many-params (param $x i64) (param $y i32) (param $z f64) -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$condition-eqz (param $x i32) -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$condition-global -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$condition-ref.is (param $x anyref) -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$start-used-globally -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$colliding-name_0 (param $x i32) -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-B$error-if-null (param $x anyref) (result anyref) -;; CHECK-NEXT: (block $block -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-B$unreachable-if-body-no-result (param $x anyref) -;; CHECK-NEXT: (block $block -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-B$multi-if_0 (param $x anyref) -;; CHECK-NEXT: (loop $x -;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (br_if $x -;; CHECK-NEXT: (global.get $glob) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $none_=>_none (func)) - (type $none_=>_none (func)) - ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) - (global $global$0 (mut i32) (i32.const 10)) - ;; CHECK: (export "0" (func $0)) - (export "0" (func $0)) - ;; CHECK: (export "1" (func $1)) - (export "1" (func $1)) - ;; CHECK: (func $0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$10 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - ;; A function that is a good candidate to partially inline. - (if - (global.get $global$0) - (return) - ) - (call $1) - (call $1) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-A$0 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$1 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$00 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$10 - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$01 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $global$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $byn-split-outlined-A$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $1 - ;; This and the previous function are mutually recursive. As a result, we - ;; can keep partially inlining between them, creating new functions as we - ;; go, even though that is not very useful. - (call $0) - ) - - ;; Add a lot more functions, so the # of functions is high which would - ;; otherwise limit the # of iterations that we run. - ;; CHECK: (func $2 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $2 - (nop) - ) - ;; CHECK: (func $3 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $3 - (nop) - ) - ;; CHECK: (func $4 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $4 - (nop) - ) - ;; CHECK: (func $5 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $5 - (nop) - ) - ;; CHECK: (func $6 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $6 - (nop) - ) - ;; CHECK: (func $7 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $7 - (nop) - ) - ;; CHECK: (func $8 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $8 - (nop) - ) - ;; CHECK: (func $9 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $9 - (nop) - ) - ;; CHECK: (func $10 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $10 - (nop) - ) - ;; CHECK: (func $11 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $11 - (nop) - ) - ;; CHECK: (func $12 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $12 - (nop) - ) - ;; CHECK: (func $13 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $13 - (nop) - ) - ;; CHECK: (func $14 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $14 - (nop) - ) - ;; CHECK: (func $15 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $15 - (nop) - ) - ;; CHECK: (func $16 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $16 - (nop) - ) - ;; CHECK: (func $17 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $17 - (nop) - ) - ;; CHECK: (func $18 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $18 - (nop) - ) -) -;; CHECK: (func $byn-split-outlined-A$0 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$1 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0 -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.eqz -;; CHECK-NEXT: (global.get $global$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $byn-split-outlined-A$0_0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$10 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$00 -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.eqz -;; CHECK-NEXT: (global.get $global$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $byn-split-outlined-A$0_0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$0_0 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$1 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0 -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.eqz -;; CHECK-NEXT: (global.get $global$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $byn-split-outlined-A$0_1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$10 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$00 -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.eqz -;; CHECK-NEXT: (global.get $global$0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $byn-split-outlined-A$0_1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn-split-outlined-A$0_1 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$1 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (call $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (block $__inlined_func$10 -;; CHECK-NEXT: (block -;; CHECK-NEXT: (call $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast binaryen-99/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast --- binaryen-108/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/instrument-locals_all-features_disable-typed-function-references.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,296 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --instrument-locals --all-features --disable-typed-function-references -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - - ;; CHECK: (type $i32_i32_i64_=>_i64 (func (param i32 i32 i64) (result i64))) - - ;; CHECK: (type $i32_i32_f32_=>_f32 (func (param i32 i32 f32) (result f32))) - - ;; CHECK: (type $i32_i32_f64_=>_f64 (func (param i32 i32 f64) (result f64))) - - ;; CHECK: (type $i32_i32_funcref_=>_funcref (func (param i32 i32 funcref) (result funcref))) - - ;; CHECK: (type $i32_i32_anyref_=>_anyref (func (param i32 i32 anyref) (result anyref))) - - ;; CHECK: (type $i32_i32_eqref_=>_eqref (func (param i32 i32 eqref) (result eqref))) - - ;; CHECK: (type $i32_i32_i31ref_=>_i31ref (func (param i32 i32 i31ref) (result i31ref))) - - ;; CHECK: (type $i32_i32_dataref_=>_dataref (func (param i32 i32 dataref) (result dataref))) - - ;; CHECK: (type $i32_i32_v128_=>_v128 (func (param i32 i32 v128) (result v128))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "get_i32" (func $get_i32 (param i32 i32 i32) (result i32))) - - ;; CHECK: (import "env" "get_i64" (func $get_i64 (param i32 i32 i64) (result i64))) - - ;; CHECK: (import "env" "get_f32" (func $get_f32 (param i32 i32 f32) (result f32))) - - ;; CHECK: (import "env" "get_f64" (func $get_f64 (param i32 i32 f64) (result f64))) - - ;; CHECK: (import "env" "set_i32" (func $set_i32 (param i32 i32 i32) (result i32))) - - ;; CHECK: (import "env" "set_i64" (func $set_i64 (param i32 i32 i64) (result i64))) - - ;; CHECK: (import "env" "set_f32" (func $set_f32 (param i32 i32 f32) (result f32))) - - ;; CHECK: (import "env" "set_f64" (func $set_f64 (param i32 i32 f64) (result f64))) - - ;; CHECK: (import "env" "get_funcref" (func $get_funcref (param i32 i32 funcref) (result funcref))) - - ;; CHECK: (import "env" "set_funcref" (func $set_funcref (param i32 i32 funcref) (result funcref))) - - ;; CHECK: (import "env" "get_anyref" (func $get_anyref (param i32 i32 anyref) (result anyref))) - - ;; CHECK: (import "env" "set_anyref" (func $set_anyref (param i32 i32 anyref) (result anyref))) - - ;; CHECK: (import "env" "get_eqref" (func $get_eqref (param i32 i32 eqref) (result eqref))) - - ;; CHECK: (import "env" "set_eqref" (func $set_eqref (param i32 i32 eqref) (result eqref))) - - ;; CHECK: (import "env" "get_i31ref" (func $get_i31ref (param i32 i32 i31ref) (result i31ref))) - - ;; CHECK: (import "env" "set_i31ref" (func $set_i31ref (param i32 i32 i31ref) (result i31ref))) - - ;; CHECK: (import "env" "get_dataref" (func $get_dataref (param i32 i32 dataref) (result dataref))) - - ;; CHECK: (import "env" "set_dataref" (func $set_dataref (param i32 i32 dataref) (result dataref))) - - ;; CHECK: (import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128))) - - ;; CHECK: (import "env" "set_v128" (func $set_v128 (param i32 i32 v128) (result v128))) - - ;; CHECK: (elem declare func $test) - - ;; CHECK: (func $test - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i64) - ;; CHECK-NEXT: (local $z f32) - ;; CHECK-NEXT: (local $w f64) - ;; CHECK-NEXT: (local $F funcref) - ;; CHECK-NEXT: (local $X anyref) - ;; CHECK-NEXT: (local $S v128) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_f32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_f64 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_funcref - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.get $F) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_anyref - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_i32 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_f32 - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_f64 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_funcref - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.get $F) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_anyref - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $set_i32 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (call $set_f32 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (f32.const 3.2100000381469727) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (call $set_f64 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (f64.const 4.321) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $F - ;; CHECK-NEXT: (ref.func $test) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $X - ;; CHECK-NEXT: (call $set_anyref - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (call $get_anyref - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (call $set_i32 - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i64.const 22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (call $set_f32 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (f32.const 33.209999084472656) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (call $set_f64 - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (f64.const 44.321) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $F - ;; CHECK-NEXT: (call $set_funcref - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (call $get_funcref - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.get $F) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $X - ;; CHECK-NEXT: (call $set_anyref - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (call $get_anyref - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $get_v128 - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (local.get $S) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $S - ;; CHECK-NEXT: (call $set_v128 - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000001 0x00000002 0x00000003) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (local $x i32) - (local $y i64) - (local $z f32) - (local $w f64) - (local $F funcref) - (local $X externref) - (local $S v128) - - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - (drop (local.get $F)) - (drop (local.get $X)) - - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - (drop (local.get $F)) - (drop (local.get $X)) - - (local.set $x (i32.const 1)) - (local.set $y (i64.const 2)) - (local.set $z (f32.const 3.21)) - (local.set $w (f64.const 4.321)) - (local.set $F (ref.func $test)) - (local.set $X (local.get $X)) - - (local.set $x (i32.const 11)) - (local.set $y (i64.const 22)) - (local.set $z (f32.const 33.21)) - (local.set $w (f64.const 44.321)) - (local.set $F (local.get $F)) - (local.set $X (local.get $X)) - - ;; Add new instructions here so expected output doesn't change too much, it - ;; depends on order of instructions in this file. - (drop (local.get $S)) - (local.set $S (v128.const i32x4 0x00000000 0x00000001 0x00000002 0x00000003)) - ) -) diff -Nru binaryen-108/test/lit/passes/instrument-locals-eh.wast binaryen-99/test/lit/passes/instrument-locals-eh.wast --- binaryen-108/test/lit/passes/instrument-locals-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/instrument-locals-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --instrument-locals -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e (param i32)) - (tag $e (param i32)) - - ;; CHECK: (func $test - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (local $x i32) - (try - (do) - (catch $e - ;; Pop instructions should not be instrumented - (local.set $x (pop i32)) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/instrument-memory64.wast binaryen-99/test/lit/passes/instrument-memory64.wast --- binaryen-108/test/lit/passes/instrument-memory64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/instrument-memory64.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,679 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --instrument-memory --enable-memory64 -S -o - | filecheck %s - -(module - (memory i64 256 256) - ;; CHECK: (type $1 (func)) - (type $1 (func)) - ;; CHECK: (type $i32_i32_i64_i64_=>_i64 (func (param i32 i32 i64 i64) (result i64))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i32_i64_=>_i64 (func (param i32 i64) (result i64))) - - ;; CHECK: (type $i32_f32_=>_f32 (func (param i32 f32) (result f32))) - - ;; CHECK: (type $i32_f64_=>_f64 (func (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "load_ptr" (func $load_ptr (param i32 i32 i64 i64) (result i64))) - - ;; CHECK: (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "store_ptr" (func $store_ptr (param i32 i32 i64 i64) (result i64))) - - ;; CHECK: (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (memory $0 i64 256 256) - - ;; CHECK: (func $A - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i64.load8_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i64.load8_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.load16_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i64.load16_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i64.load32_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i64.load32_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i64.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f32 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f64 - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.load8_s offset=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: (i32.load16_s offset=3 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.load16_u offset=4 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: (i32.load offset=5 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i64.load8_s offset=6 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 6) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: (i64.load8_u offset=7 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 7) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (i64.load16_s offset=8 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 8) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: (i64.load16_u offset=9 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 9) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (i64.load32_s offset=10 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 10) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i64.load32_u offset=11 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 11) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: (i64.load offset=12 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 12) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f32 - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: (f32.load offset=13 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 13) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f64 - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: (f64.load offset=14 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 14) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $A (type $1) - (drop (i32.load8_s (i64.const 0))) - (drop (i32.load8_u (i64.const 0))) - (drop (i32.load16_s (i64.const 0))) - (drop (i32.load16_u (i64.const 0))) - (drop (i32.load (i64.const 0))) - (drop (i64.load8_s (i64.const 0))) - (drop (i64.load8_u (i64.const 0))) - (drop (i64.load16_s (i64.const 0))) - (drop (i64.load16_u (i64.const 0))) - (drop (i64.load32_s (i64.const 0))) - (drop (i64.load32_u (i64.const 0))) - (drop (i64.load (i64.const 0))) - (drop (f32.load (i64.const 0))) - (drop (f64.load (i64.const 0))) - - (drop (i32.load8_s align=1 offset=1 (i64.const 0))) - (drop (i32.load8_u align=1 offset=2 (i64.const 0))) - (drop (i32.load16_s align=1 offset=3 (i64.const 0))) - (drop (i32.load16_u align=1 offset=4 (i64.const 0))) - (drop (i32.load align=2 offset=5 (i64.const 0))) - (drop (i64.load8_s align=1 offset=6 (i64.const 0))) - (drop (i64.load8_u align=1 offset=7 (i64.const 0))) - (drop (i64.load16_s align=1 offset=8 (i64.const 0))) - (drop (i64.load16_u align=1 offset=9 (i64.const 0))) - (drop (i64.load32_s align=2 offset=10 (i64.const 0))) - (drop (i64.load32_u align=2 offset=11 (i64.const 0))) - (drop (i64.load align=2 offset=12 (i64.const 0))) - (drop (f32.load align=2 offset=13 (i64.const 0))) - (drop (f64.load align=2 offset=14 (i64.const 0))) - ) - - ;; CHECK: (func $B - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store8 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store16 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i64.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: (i64.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f32 - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: (f32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f64 - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: (f64.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 38) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 38) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 align=1 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 39) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 39) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=3 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store8 offset=4 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store16 offset=5 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store32 offset=6 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 6) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: (i64.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store offset=7 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 7) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (i64.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store offset=8 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 8) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f32 - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: (f32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=9 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 46) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 9) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f64 - ;; CHECK-NEXT: (i32.const 46) - ;; CHECK-NEXT: (f64.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $B (type $1) - (i32.store8 (i64.const 0) (i32.const 1)) - (i32.store16 (i64.const 0) (i32.const 2)) - (i32.store (i64.const 0) (i32.const 3)) - (i64.store8 (i64.const 0) (i64.const 4)) - (i64.store16 (i64.const 0) (i64.const 5)) - (i64.store32 (i64.const 0) (i64.const 6)) - (i64.store (i64.const 0) (i64.const 7)) - (f32.store (i64.const 0) (f32.const 8)) - (f64.store (i64.const 0) (f64.const 9)) - - (i32.store8 align=1 offset=1 (i64.const 0) (i32.const 1)) - (i32.store16 align=1 offset=2 (i64.const 0) (i32.const 2)) - (i32.store align=2 offset=3 (i64.const 0) (i32.const 3)) - (i64.store8 align=1 offset=4 (i64.const 0) (i64.const 4)) - (i64.store16 align=2 offset=5 (i64.const 0) (i64.const 5)) - (i64.store32 align=2 offset=6 (i64.const 0) (i64.const 6)) - (i64.store align=2 offset=7 (i64.const 0) (i64.const 7)) - (f32.store align=2 offset=8 (i64.const 0) (f32.const 8)) - (f64.store align=2 offset=9 (i64.const 0) (f64.const 9)) - ) -) diff -Nru binaryen-108/test/lit/passes/instrument-memory-gc.wast binaryen-99/test/lit/passes/instrument-memory-gc.wast --- binaryen-108/test/lit/passes/instrument-memory-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/instrument-memory-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,293 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: foreach %s %t wasm-opt --instrument-memory -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt --instrument-memory --nominal -all -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i32_i64_=>_i64 (func (param i32 i64) (result i64))) - - ;; CHECK: (type $i32_f32_=>_f32 (func (param i32 f32) (result f32))) - - ;; CHECK: (type $i32_f64_=>_f64 (func (param i32 f64) (result f64))) - - ;; CHECK: (type $struct (struct (field (mut i32)) (field f32) (field $named f64))) - ;; NOMNL: (type $i32_i32_=>_i32 (func_subtype (param i32 i32) (result i32) func)) - - ;; NOMNL: (type $i32_i64_=>_i64 (func_subtype (param i32 i64) (result i64) func)) - - ;; NOMNL: (type $i32_f32_=>_f32 (func_subtype (param i32 f32) (result f32) func)) - - ;; NOMNL: (type $i32_f64_=>_f64 (func_subtype (param i32 f64) (result f64) func)) - - ;; NOMNL: (type $struct (struct_subtype (field (mut i32)) (field f32) (field $named f64) data)) - (type $struct (struct - (field (mut i32)) - (field f32) - (field $named f64) - )) - ;; CHECK: (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (type $ref|$struct|_=>_none (func (param (ref $struct)))) - - ;; CHECK: (type $ref|$array|_=>_none (func (param (ref $array)))) - - ;; CHECK: (type $array (array (mut f64))) - ;; NOMNL: (type $i32_i32_i32_i32_=>_i32 (func_subtype (param i32 i32 i32 i32) (result i32) func)) - - ;; NOMNL: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; NOMNL: (type $ref|$array|_=>_none (func_subtype (param (ref $array)) func)) - - ;; NOMNL: (type $array (array_subtype (mut f64) data)) - (type $array (array (mut f64))) - - ;; CHECK: (import "env" "load_ptr" (func $load_ptr (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "store_ptr" (func $store_ptr (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "struct_get_val_i32" (func $struct_get_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "struct_get_val_i64" (func $struct_get_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "struct_get_val_f32" (func $struct_get_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "struct_get_val_f64" (func $struct_get_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "struct_set_val_i32" (func $struct_set_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "struct_set_val_i64" (func $struct_set_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "struct_set_val_f32" (func $struct_set_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "struct_set_val_f64" (func $struct_set_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "array_get_val_i32" (func $array_get_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "array_get_val_i64" (func $array_get_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "array_get_val_f32" (func $array_get_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "array_get_val_f64" (func $array_get_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "array_set_val_i32" (func $array_set_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "array_set_val_i64" (func $array_set_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "array_set_val_f32" (func $array_set_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "array_set_val_f64" (func $array_set_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "array_get_index" (func $array_get_index (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "array_set_index" (func $array_set_index (param i32 i32) (result i32))) - - ;; CHECK: (func $structs (param $x (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $struct_get_val_i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $struct_get_val_f32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (struct.get $struct 1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $struct_get_val_f64 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (struct.get $struct $named - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $struct_set_val_i32 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (import "env" "load_ptr" (func $load_ptr (param i32 i32 i32 i32) (result i32))) - - ;; NOMNL: (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) - - ;; NOMNL: (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) - - ;; NOMNL: (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) - - ;; NOMNL: (import "env" "store_ptr" (func $store_ptr (param i32 i32 i32 i32) (result i32))) - - ;; NOMNL: (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) - - ;; NOMNL: (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) - - ;; NOMNL: (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) - - ;; NOMNL: (import "env" "struct_get_val_i32" (func $struct_get_val_i32 (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "struct_get_val_i64" (func $struct_get_val_i64 (param i32 i64) (result i64))) - - ;; NOMNL: (import "env" "struct_get_val_f32" (func $struct_get_val_f32 (param i32 f32) (result f32))) - - ;; NOMNL: (import "env" "struct_get_val_f64" (func $struct_get_val_f64 (param i32 f64) (result f64))) - - ;; NOMNL: (import "env" "struct_set_val_i32" (func $struct_set_val_i32 (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "struct_set_val_i64" (func $struct_set_val_i64 (param i32 i64) (result i64))) - - ;; NOMNL: (import "env" "struct_set_val_f32" (func $struct_set_val_f32 (param i32 f32) (result f32))) - - ;; NOMNL: (import "env" "struct_set_val_f64" (func $struct_set_val_f64 (param i32 f64) (result f64))) - - ;; NOMNL: (import "env" "array_get_val_i32" (func $array_get_val_i32 (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "array_get_val_i64" (func $array_get_val_i64 (param i32 i64) (result i64))) - - ;; NOMNL: (import "env" "array_get_val_f32" (func $array_get_val_f32 (param i32 f32) (result f32))) - - ;; NOMNL: (import "env" "array_get_val_f64" (func $array_get_val_f64 (param i32 f64) (result f64))) - - ;; NOMNL: (import "env" "array_set_val_i32" (func $array_set_val_i32 (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "array_set_val_i64" (func $array_set_val_i64 (param i32 i64) (result i64))) - - ;; NOMNL: (import "env" "array_set_val_f32" (func $array_set_val_f32 (param i32 f32) (result f32))) - - ;; NOMNL: (import "env" "array_set_val_f64" (func $array_set_val_f64 (param i32 f64) (result f64))) - - ;; NOMNL: (import "env" "array_get_index" (func $array_get_index (param i32 i32) (result i32))) - - ;; NOMNL: (import "env" "array_set_index" (func $array_set_index (param i32 i32) (result i32))) - - ;; NOMNL: (func $structs (type $ref|$struct|_=>_none) (param $x (ref $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $struct_get_val_i32 - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $struct_get_val_f32 - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (struct.get $struct 1 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $struct_get_val_f64 - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (struct.get $struct $named - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (call $struct_set_val_i32 - ;; NOMNL-NEXT: (i32.const 3) - ;; NOMNL-NEXT: (i32.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $structs (param $x (ref $struct)) - (drop - (struct.get $struct 0 (local.get $x)) - ) - (drop - (struct.get $struct 1 (local.get $x)) - ) - (drop - (struct.get $struct 2 (local.get $x)) - ) - (struct.set $struct 0 (local.get $x) (i32.const 42)) - ) - - ;; CHECK: (func $arrays (param $x (ref $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $array_get_val_f64 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (array.get $array - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $array_get_index - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (array.set $array - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $array_set_index - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $array_set_val_f64 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $arrays (type $ref|$array|_=>_none) (param $x (ref $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $array_get_val_f64 - ;; NOMNL-NEXT: (i32.const 5) - ;; NOMNL-NEXT: (array.get $array - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (call $array_get_index - ;; NOMNL-NEXT: (i32.const 4) - ;; NOMNL-NEXT: (i32.const 10) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (array.set $array - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (call $array_set_index - ;; NOMNL-NEXT: (i32.const 6) - ;; NOMNL-NEXT: (i32.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $array_set_val_f64 - ;; NOMNL-NEXT: (i32.const 7) - ;; NOMNL-NEXT: (f64.const 3.14159) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $arrays (param $x (ref $array)) - (drop - (array.get $array (local.get $x) (i32.const 10)) - ) - (array.set $array (local.get $x) (i32.const 42) (f64.const 3.14159)) - ) -) diff -Nru binaryen-108/test/lit/passes/instrument-memory.wast binaryen-99/test/lit/passes/instrument-memory.wast --- binaryen-108/test/lit/passes/instrument-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/instrument-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,679 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --instrument-memory -S -o - | filecheck %s - -(module - (memory 256 256) - ;; CHECK: (type $1 (func)) - (type $1 (func)) - ;; CHECK: (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i32_i64_=>_i64 (func (param i32 i64) (result i64))) - - ;; CHECK: (type $i32_f32_=>_f32 (func (param i32 f32) (result f32))) - - ;; CHECK: (type $i32_f64_=>_f64 (func (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "load_ptr" (func $load_ptr (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (import "env" "store_ptr" (func $store_ptr (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) - - ;; CHECK: (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) - - ;; CHECK: (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) - - ;; CHECK: (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) - - ;; CHECK: (memory $0 256 256) - - ;; CHECK: (func $A - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i64.load8_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i64.load8_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.load16_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i64.load16_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i64.load32_s - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i64.load32_u - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i64.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f32 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f64 - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.load8_s offset=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.load8_u offset=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: (i32.load16_s offset=3 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.load16_u offset=4 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i32 - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: (i32.load offset=5 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i64.load8_s offset=6 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: (i64.load8_u offset=7 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (i64.load16_s offset=8 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: (i64.load16_u offset=9 align=1 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (i64.load32_s offset=10 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i64.load32_u offset=11 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_i64 - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: (i64.load offset=12 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f32 - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: (f32.load offset=13 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $load_val_f64 - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: (f64.load offset=14 align=2 - ;; CHECK-NEXT: (call $load_ptr - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $A (type $1) - (drop (i32.load8_s (i32.const 0))) - (drop (i32.load8_u (i32.const 0))) - (drop (i32.load16_s (i32.const 0))) - (drop (i32.load16_u (i32.const 0))) - (drop (i32.load (i32.const 0))) - (drop (i64.load8_s (i32.const 0))) - (drop (i64.load8_u (i32.const 0))) - (drop (i64.load16_s (i32.const 0))) - (drop (i64.load16_u (i32.const 0))) - (drop (i64.load32_s (i32.const 0))) - (drop (i64.load32_u (i32.const 0))) - (drop (i64.load (i32.const 0))) - (drop (f32.load (i32.const 0))) - (drop (f64.load (i32.const 0))) - - (drop (i32.load8_s align=1 offset=1 (i32.const 0))) - (drop (i32.load8_u align=1 offset=2 (i32.const 0))) - (drop (i32.load16_s align=1 offset=3 (i32.const 0))) - (drop (i32.load16_u align=1 offset=4 (i32.const 0))) - (drop (i32.load align=2 offset=5 (i32.const 0))) - (drop (i64.load8_s align=1 offset=6 (i32.const 0))) - (drop (i64.load8_u align=1 offset=7 (i32.const 0))) - (drop (i64.load16_s align=1 offset=8 (i32.const 0))) - (drop (i64.load16_u align=1 offset=9 (i32.const 0))) - (drop (i64.load32_s align=2 offset=10 (i32.const 0))) - (drop (i64.load32_u align=2 offset=11 (i32.const 0))) - (drop (i64.load align=2 offset=12 (i32.const 0))) - (drop (f32.load align=2 offset=13 (i32.const 0))) - (drop (f64.load align=2 offset=14 (i32.const 0))) - ) - - ;; CHECK: (func $B - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store8 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store16 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i64.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: (i64.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f32 - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: (f32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f64 - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: (f64.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 offset=1 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 38) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 38) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 offset=2 align=1 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 39) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 39) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=3 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i32 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store8 offset=4 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: (i64.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store16 offset=5 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store32 offset=6 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: (i64.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store offset=7 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_i64 - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (i64.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store offset=8 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f32 - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: (f32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=9 align=2 - ;; CHECK-NEXT: (call $store_ptr - ;; CHECK-NEXT: (i32.const 46) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $store_val_f64 - ;; CHECK-NEXT: (i32.const 46) - ;; CHECK-NEXT: (f64.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $B (type $1) - (i32.store8 (i32.const 0) (i32.const 1)) - (i32.store16 (i32.const 0) (i32.const 2)) - (i32.store (i32.const 0) (i32.const 3)) - (i64.store8 (i32.const 0) (i64.const 4)) - (i64.store16 (i32.const 0) (i64.const 5)) - (i64.store32 (i32.const 0) (i64.const 6)) - (i64.store (i32.const 0) (i64.const 7)) - (f32.store (i32.const 0) (f32.const 8)) - (f64.store (i32.const 0) (f64.const 9)) - - (i32.store8 align=1 offset=1 (i32.const 0) (i32.const 1)) - (i32.store16 align=1 offset=2 (i32.const 0) (i32.const 2)) - (i32.store align=2 offset=3 (i32.const 0) (i32.const 3)) - (i64.store8 align=1 offset=4 (i32.const 0) (i64.const 4)) - (i64.store16 align=2 offset=5 (i32.const 0) (i64.const 5)) - (i64.store32 align=2 offset=6 (i32.const 0) (i64.const 6)) - (i64.store align=2 offset=7 (i32.const 0) (i64.const 7)) - (f32.store align=2 offset=8 (i32.const 0) (f32.const 8)) - (f64.store align=2 offset=9 (i32.const 0) (f64.const 9)) - ) -) diff -Nru binaryen-108/test/lit/passes/intrinsic-lowering.wast binaryen-99/test/lit/passes/intrinsic-lowering.wast --- binaryen-108/test/lit/passes/intrinsic-lowering.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/intrinsic-lowering.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --intrinsic-lowering -all -S -o - | filecheck %s - -(module - ;; CHECK: (type $none (func)) - (type $none (func)) - - ;; call.without.effects with no params. - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $cwe-v (param funcref) (result i32))) - (import "binaryen-intrinsics" "call.without.effects" (func $cwe-v (param funcref) (result i32))) - - ;; call.without.effects with some params. - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $cwe-dif (param f64 i32 funcref) (result f32))) - (import "binaryen-intrinsics" "call.without.effects" (func $cwe-dif (param f64) (param i32) (param funcref) (result f32))) - - ;; call.without.effects with no result. - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $cwe-n (param funcref))) - (import "binaryen-intrinsics" "call.without.effects" (func $cwe-n (param funcref))) - - ;; CHECK: (func $test (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $test) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $dif - ;; CHECK-NEXT: (f64.const 3.14159) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $test (result i32) - ;; These will be lowered into calls. - (drop (call $cwe-v (ref.func $test))) - (drop (call $cwe-dif (f64.const 3.14159) (i32.const 42) (ref.func $dif))) - ;; The last must be a call_ref, as we don't see a constant ref.func - (call $cwe-n - (ref.null $none) - ) - (i32.const 1) - ) - - ;; CHECK: (func $dif (param $0 f64) (param $1 i32) (result f32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $dif (param f64) (param i32) (result f32) - ;; Helper function for the above. - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/passes/local-cse_all-features.wast binaryen-99/test/lit/passes/local-cse_all-features.wast --- binaryen-108/test/lit/passes/local-cse_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/local-cse_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,363 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --local-cse --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (elem declare func $calls $ref.func) - - ;; CHECK: (func $calls (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (ref.func $calls) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (ref.func $calls) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - (func $calls (param $x i32) (result i32) - ;; The side effects of calls prevent optimization. - (drop - (call_ref (i32.const 10) (ref.func $calls)) - ) - (drop - (call_ref (i32.const 10) (ref.func $calls)) - ) - (i32.const 20) - ) - - ;; CHECK: (func $ref.func - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $ref.func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $ref.func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref.func - ;; RefFunc and other constants should be ignored - don't undo the effects - ;; of constant propagation. - (drop - (ref.func $ref.func) - ) - (drop - (ref.func $ref.func) - ) - ) -) - -(module - ;; CHECK: (type $A (struct (field i32))) - (type $A (struct (field i32))) - - ;; CHECK: (type $B (array (mut i32))) - (type $B (array (mut i32))) - - - ;; CHECK: (type $ref|$A|_=>_none (func (param (ref $A)))) - - ;; CHECK: (type $ref?|$A|_=>_none (func (param (ref null $A)))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $ref?|$B|_ref|$A|_=>_none (func (param (ref null $B) (ref $A)))) - - ;; CHECK: (func $struct-gets-nullable (param $ref (ref null $A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $struct-gets-nullable (param $ref (ref null $A)) - ;; Repeated loads from a struct can be optimized, even with a nullable - ;; reference: if we trap, it does not matter that we replaced the later - ;; expressions). - (drop - (struct.get $A 0 - (local.get $ref) - ) - ) - (drop - (struct.get $A 0 - (local.get $ref) - ) - ) - (drop - (struct.get $A 0 - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $struct-gets (param $ref (ref $A)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $struct-gets (param $ref (ref $A)) - ;; Repeated loads from a struct can be optimized. - ;; - ;; A potential trap would not stop us (see previous testcase), but here - ;; there is also no trap possible anyhow, and we should optimize. - (drop - (struct.get $A 0 - (local.get $ref) - ) - ) - (drop - (struct.get $A 0 - (local.get $ref) - ) - ) - (drop - (struct.get $A 0 - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $non-nullable-value (param $ref (ref $A)) - ;; CHECK-NEXT: (local $1 (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (select (result (ref $A)) - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $non-nullable-value (param $ref (ref $A)) - ;; The value that is repeated is non-nullable, which we must do some fixups - ;; for after creating a local of that type. - (drop - (select (result (ref $A)) - (local.get $ref) - (local.get $ref) - (i32.const 1) - ) - ) - (drop - (select (result (ref $A)) - (local.get $ref) - (local.get $ref) - (i32.const 1) - ) - ) - ) - - ;; CHECK: (func $creations - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $A - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_with_rtt $A - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.new_with_rtt $B - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.new_with_rtt $B - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $creations - ;; Allocating GC data has no side effects, but each allocation is unique - ;; and so we cannot replace separate allocations with a single one. - (drop - (struct.new_with_rtt $A - (i32.const 1) - (rtt.canon $A) - ) - ) - (drop - (struct.new_with_rtt $A - (i32.const 1) - (rtt.canon $A) - ) - ) - (drop - (array.new_with_rtt $B - (i32.const 1) - (i32.const 1) - (rtt.canon $B) - ) - ) - (drop - (array.new_with_rtt $B - (i32.const 1) - (i32.const 1) - (rtt.canon $B) - ) - ) - ) - - ;; CHECK: (func $structs-and-arrays-do-not-alias (param $array (ref null $B)) (param $struct (ref $A)) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (array.set $B - ;; CHECK-NEXT: (local.get $array) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (struct.get $A 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (array.set $B - ;; CHECK-NEXT: (local.get $array) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (array.set $B - ;; CHECK-NEXT: (local.get $array) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $structs-and-arrays-do-not-alias (param $array (ref null $B)) (param $struct (ref $A)) - ;; ArraySets to consecutive elements, using some fixed StructGet value. This - ;; common pattern in j2cl can be optimized, as structs and arrays do not - ;; alias. - (array.set $B - (local.get $array) - (i32.const 0) - (struct.get $A 0 - (local.get $struct) - ) - ) - (array.set $B - (local.get $array) - (i32.const 1) - (struct.get $A 0 - (local.get $struct) - ) - ) - (array.set $B - (local.get $array) - (i32.const 2) - (struct.get $A 0 - (local.get $struct) - ) - ) - ) -) - -(module - ;; Real-world testcase from AssemblyScript, containing multiple nested things - ;; that can be optimized. The inputs to the add (the xors) are identical, and - ;; we can avoid repeating them. - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (func $div16_internal (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $div16_internal (param $0 i32) (param $1 i32) (result i32) - (i32.add - (i32.xor - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 16) - ) - (i32.const 16) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 16) - ) - (i32.const 16) - ) - ) - (i32.xor - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 16) - ) - (i32.const 16) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/local-cse.wast binaryen-99/test/lit/passes/local-cse.wast --- binaryen-108/test/lit/passes/local-cse.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/local-cse.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,434 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --local-cse -S -o - | filecheck %s - -(module - (memory 100 100) - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_i64 (func (result i64))) - - ;; CHECK: (memory $0 100 100) - - ;; CHECK: (func $basics - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $basics) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $basics - (local $x i32) - (local $y i32) - ;; These two adds can be optimized. - (drop - (i32.add (i32.const 1) (i32.const 2)) - ) - (drop - (i32.add (i32.const 1) (i32.const 2)) - ) - (if (i32.const 0) (nop)) - ;; This add is after an if, which means we are no longer in the same basic - ;; block - which means we cannot optimize it with the previous identical - ;; adds. - (drop - (i32.add (i32.const 1) (i32.const 2)) - ) - ;; More adds with different contents than the previous, but all three are - ;; identical. - (drop - (i32.add (local.get $x) (local.get $y)) - ) - (drop - (i32.add (local.get $x) (local.get $y)) - ) - (drop - (i32.add (local.get $x) (local.get $y)) - ) - ;; Calls have side effects, but that is not a problem for these adds which - ;; only use locals, so we can optimize the add after the call. - (call $basics) - (drop - (i32.add (local.get $x) (local.get $y)) - ) - ;; Modify $x, which means we cannot optimize the add after the set. - (local.set $x (i32.const 100)) - (drop - (i32.add (local.get $x) (local.get $y)) - ) - ) - - ;; CHECK: (func $recursive1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $recursive1 - (local $x i32) - (local $y i32) - ;; The first two dropped things are identical and can be optimized. - (drop - (i32.add - (i32.const 1) - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - (drop - (i32.add - (i32.const 1) - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - ;; The last thing here appears inside the previous pattern, and can still - ;; be optimized, with another local. - (drop - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - - ;; CHECK: (func $recursive2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $recursive2 - (local $x i32) - (local $y i32) - ;; As before, but the order is different, with the sub-pattern in the - ;; middle. - (drop - (i32.add - (i32.const 1) - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - (drop - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - (drop - (i32.add - (i32.const 1) - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - ) - - ;; CHECK: (func $self - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $self - (local $x i32) - (local $y i32) - ;; As before, with just the large pattern and the sub pattern, but no - ;; repeats of the large pattern. - (drop - (i32.add - (i32.add - (i32.const 2) - (i32.const 3) - ) - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - (drop - (i32.add - (i32.const 2) - (i32.const 3) - ) - ) - ) - - ;; CHECK: (func $loads - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $loads - ;; The possible trap on loads does not prevent optimization, since if we - ;; trap then it doesn't matter that we replaced the later expression. - (drop - (i32.load (i32.const 10)) - ) - (drop - (i32.load (i32.const 10)) - ) - ) - - ;; CHECK: (func $calls (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $calls - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $calls - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - (func $calls (param $x i32) (result i32) - ;; The side effects of calls prevent optimization. - (drop - (call $calls (i32.const 10)) - ) - (drop - (call $calls (i32.const 10)) - ) - (i32.const 10) - ) - - ;; CHECK: (func $many-sets (result i64) - ;; CHECK-NEXT: (local $temp i64) - ;; CHECK-NEXT: (local $1 i64) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i64.add - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i64.const 9999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - (func $many-sets (result i64) - (local $temp i64) - ;; Assign to $temp three times here. We can optimize the add regardless of - ;; that, and should not be confused by the sets themselves having effects - ;; that are in conflict (the value is what matters). - (local.set $temp - (i64.add - (i64.const 1) - (i64.const 2) - ) - ) - (local.set $temp - (i64.const 9999) - ) - (local.set $temp - (i64.add - (i64.const 1) - (i64.const 2) - ) - ) - (local.get $temp) - ) - - ;; CHECK: (func $switch-children (param $x i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $label$1 (result i32) - ;; CHECK-NEXT: (br_table $label$1 $label$1 - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $switch-children (param $x i32) (result i32) - (block $label$1 (result i32) - ;; We can optimize the two children of this switch. This test verifies - ;; that we do so properly and do not hit an assertion involving the - ;; ordering of the switch's children, which was incorrect in the past. - (br_table $label$1 $label$1 - (i32.and - (local.get $x) - (i32.const 3) - ) - (i32.and - (local.get $x) - (i32.const 3) - ) - ) - ) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $glob (mut i32) (i32.const 1)) - (global $glob (mut i32) (i32.const 1)) - - ;; CHECK: (global $other-glob (mut i32) (i32.const 1)) - (global $other-glob (mut i32) (i32.const 1)) - - ;; CHECK: (func $global - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $other-glob - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $glob - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $global - ;; We should optimize redundant global.get operations. - (drop (global.get $glob)) - (drop (global.get $glob)) - ;; We can do it past a write to another global - (global.set $other-glob (i32.const 100)) - (drop (global.get $glob)) - ;; But we can't do it past a write to our global. - (global.set $glob (i32.const 200)) - (drop (global.get $glob)) - ) -) diff -Nru binaryen-108/test/lit/passes/local-subtyping-nn.wast binaryen-99/test/lit/passes/local-subtyping-nn.wast --- binaryen-108/test/lit/passes/local-subtyping-nn.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/local-subtyping-nn.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --local-subtyping -all --enable-gc-nn-locals -S -o - \ -;; RUN: | filecheck %s -;; RUN: wasm-opt %s --local-subtyping -all --enable-gc-nn-locals --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $struct (struct )) - ;; NOMNL: (type $struct (struct_subtype data)) - (type $struct (struct)) - - ;; CHECK: (import "out" "i32" (func $i32 (result i32))) - ;; NOMNL: (import "out" "i32" (func $i32 (result i32))) - (import "out" "i32" (func $i32 (result i32))) - - ;; CHECK: (func $non-nullable - ;; CHECK-NEXT: (local $x (ref $struct)) - ;; CHECK-NEXT: (local $y (ref $none_=>_i32)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $non-nullable (type $none_=>_none) - ;; NOMNL-NEXT: (local $x (ref $struct)) - ;; NOMNL-NEXT: (local $y (ref $none_=>_i32)) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $y - ;; NOMNL-NEXT: (ref.func $i32) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $non-nullable - (local $x (ref null $struct)) - (local $y anyref) - ;; x is assigned a value that is non-nullable. - (local.set $x - (ref.as_non_null (ref.null $struct)) - ) - ;; y is assigned a value that is non-nullable, and also allows a more - ;; specific heap type. - (local.set $y - (ref.func $i32) - ) - ;; Verify that the presence of a get does not alter things. - (drop - (local.get $x) - ) - ) - - ;; CHECK: (func $uses-default (param $i i32) - ;; CHECK-NEXT: (local $x (ref null $struct)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $uses-default (type $i32_=>_none) (param $i i32) - ;; NOMNL-NEXT: (local $x (ref null $struct)) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $i) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $uses-default (param $i i32) - (local $x (ref null any)) - (if - (local.get $i) - ;; The only set to this local uses a non-nullable type. - (local.set $x - (ref.as_non_null (ref.null $struct)) - ) - ) - (drop - ;; This get may use the null value, so we can refine the heap type but not - ;; alter nullability. - (local.get $x) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/local-subtyping.wast binaryen-99/test/lit/passes/local-subtyping.wast --- binaryen-108/test/lit/passes/local-subtyping.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/local-subtyping.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,385 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --local-subtyping -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (type ${} (struct )) - (type ${} (struct_subtype data)) - - ;; CHECK: (type ${i32} (struct (field i32))) - (type ${i32} (struct_subtype (field i32) data)) - - ;; CHECK: (import "out" "i32" (func $i32 (result i32))) - (import "out" "i32" (func $i32 (result i32))) - ;; CHECK: (import "out" "i64" (func $i64 (result i64))) - (import "out" "i64" (func $i64 (result i64))) - - ;; Refinalization can find a more specific type, where the declared type was - ;; not the optimal LUB. - ;; CHECK: (func $refinalize (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result (ref func)) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result (ref func)) - ;; CHECK-NEXT: (br $block - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $refinalize (param $x i32) - (drop - (if (result anyref) - (local.get $x) - (ref.func $i32) - (ref.func $i64) - ) - ) - (drop - (block $block (result anyref) - (br $block - (ref.func $i32) - ) - (ref.func $i64) - ) - ) - ) - - ;; A simple case where a local has a single assignment that we can use as a - ;; more specific type. A similar thing with a parameter, however, is not a - ;; thing we can optimize. Also, ignore a local with zero assignments. - ;; CHECK: (func $simple-local-but-not-param (param $x anyref) - ;; CHECK-NEXT: (local $y (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local $unused anyref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $simple-local-but-not-param (param $x anyref) - (local $y anyref) - (local $unused anyref) - (local.set $x - (ref.func $i32) - ) - (local.set $y - (ref.func $i32) - ) - ) - - ;; CHECK: (func $locals-with-multiple-assignments - ;; CHECK-NEXT: (local $x funcref) - ;; CHECK-NEXT: (local $y (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local $z (ref null $none_=>_i64)) - ;; CHECK-NEXT: (local $w funcref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $locals-with-multiple-assignments - (local $x anyref) - (local $y anyref) - (local $z anyref) - (local $w funcref) - ;; x is assigned two different types with a new LUB possible - (local.set $x - (ref.func $i32) - ) - (local.set $x - (ref.func $i64) - ) - ;; y and z are assigned the same more specific type twice - (local.set $y - (ref.func $i32) - ) - (local.set $y - (ref.func $i32) - ) - (local.set $z - (ref.func $i64) - ) - (local.set $z - (ref.func $i64) - ) - ;; w is assigned two different types *without* a new LUB possible, as it - ;; already had the optimal LUB - (local.set $w - (ref.func $i32) - ) - (local.set $w - (ref.func $i64) - ) - ) - - ;; In some cases multiple iterations are necessary, as one inferred new type - ;; applies to a get which then allows another inference. - ;; CHECK: (func $multiple-iterations - ;; CHECK-NEXT: (local $x (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local $y (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local $z (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multiple-iterations - (local $x anyref) - (local $y anyref) - (local $z anyref) - (local.set $x - (ref.func $i32) - ) - (local.set $y - (local.get $x) - ) - (local.set $z - (local.get $y) - ) - ) - - ;; Sometimes a refinalize is necessary in between the iterations. - ;; CHECK: (func $multiple-iterations-refinalize (param $i i32) - ;; CHECK-NEXT: (local $x (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local $y (ref null $none_=>_i64)) - ;; CHECK-NEXT: (local $z funcref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (ref.func $i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (select (result funcref) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multiple-iterations-refinalize (param $i i32) - (local $x anyref) - (local $y anyref) - (local $z anyref) - (local.set $x - (ref.func $i32) - ) - (local.set $y - (ref.func $i64) - ) - (local.set $z - (select - (local.get $x) - (local.get $y) - (local.get $i) - ) - ) - ) - - ;; CHECK: (func $nondefaultable - ;; CHECK-NEXT: (local $x (anyref anyref)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: (ref.func $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nondefaultable - (local $x (anyref anyref)) - ;; This tuple is assigned non-nullable values, which means the subtype is - ;; nondefaultable, and we must not apply it. - (local.set $x - (tuple.make - (ref.func $i32) - (ref.func $i32) - ) - ) - ) - - ;; CHECK: (func $uses-default (param $i i32) - ;; CHECK-NEXT: (local $x (ref null $i32_=>_none)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $uses-default) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $uses-default (param $i i32) - (local $x anyref) - (if - (local.get $i) - ;; The only set to this local uses a more specific type than anyref. - (local.set $x (ref.func $uses-default)) - ) - (drop - ;; This get may use the default value, but it is ok to have a null of a - ;; more refined type in the local. - (local.get $x) - ) - ) - - ;; CHECK: (func $unreachables (result funcref) - ;; CHECK-NEXT: (local $temp (ref null $none_=>_funcref)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.func $unreachables) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result (ref null $none_=>_funcref)) - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (ref.func $unreachables) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - (func $unreachables (result funcref) - (local $temp funcref) - ;; Set a value that allows us to refine the local's type. - (local.set $temp - (ref.func $unreachables) - ) - (unreachable) - ;; A tee that is not reachable. We must still update its type, and the - ;; parents. - (drop - (block (result funcref) - (local.tee $temp - (ref.func $unreachables) - ) - ) - ) - ;; A get that is not reachable. We must still update its type. - (local.get $temp) - ) - - ;; CHECK: (func $incompatible-sets (result i32) - ;; CHECK-NEXT: (local $temp (ref null $none_=>_i32)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.func $incompatible-sets) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $incompatible-sets (result i32) - (local $temp funcref) - ;; Set a value that allows us to specialize the local type. - (local.set $temp - (ref.func $incompatible-sets) - ) - ;; Make all code unreachable from here. - (unreachable) - ;; In unreachable code, assign values that are not compatible with the more - ;; specific type we will optimize to. Those cannot be left as they are, and - ;; will be fixed up so that they validate. (All we need is validation, as - ;; their contents do not matter, given they are not reached.) - (drop - (local.tee $temp - (ref.null func) - ) - ) - (local.set $temp - (ref.null func) - ) - (unreachable) - ) - - ;; CHECK: (func $update-nulls - ;; CHECK-NEXT: (local $x (ref null ${})) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_default ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.null ${}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.null ${i32}) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $update-nulls - (local $x anyref) - (local.set $x (ref.null any)) - (local.set $x (ref.null eq)) - ;; All the nulls can be changed into other nulls here, for the new LUB, - ;; which will be ${} - (local.set $x (struct.new ${})) - (local.set $x (ref.null data)) - ;; Note that this func null is even of a type that is incompatible with the - ;; new lub (func vs data). Still, we can just update it along with the - ;; others. - (local.set $x (ref.null func)) - ;; This null is equal to the LUB we'll find, and will not change. - (local.set $x (ref.null ${})) - ;; This null is more specific than the LUB we'll find, and will not change, - ;; as there is no point to making something less specific in type. - (local.set $x (ref.null ${i32})) - ) -) diff -Nru binaryen-108/test/lit/passes/memory-packing_all-features.wast binaryen-99/test/lit/passes/memory-packing_all-features.wast --- binaryen-108/test/lit/passes/memory-packing_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/memory-packing_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,2299 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --memory-packing --all-features -S -o - | filecheck %s - -(module - ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - (import "env" "memoryBase" (global $memoryBase i32)) - ;; nothing -) - -(module - ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - (import "env" "memoryBase" (global $memoryBase i32)) - (data (i32.const 4066) "") ;; empty -) - -(module - ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - (import "env" "memoryBase" (global $memoryBase i32)) - - (data (global.get $memoryBase) "waka this cannot be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we don't know where it will go") -) - -;; CHECK: (data (global.get $memoryBase) "waka this cannot be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we don\'t know where it will go") -(module - (memory 1 1) - - (data (i32.const 1024) "waka this CAN be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we DO know where it will go") - - (data (i32.const 2000) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeros before") - - (data (i32.const 3000) "zeros after\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") - - (data (i32.const 4000) "zeros\00in\00the\00middle\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00nice skip here\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00another\00but no") - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (data (i32.const 1024) "waka this CAN be optimized") - - ;; CHECK: (data (i32.const 1107) "we DO know where it will go") - - ;; CHECK: (data (i32.const 2057) "zeros before") - - ;; CHECK: (data (i32.const 3000) "zeros after") - - ;; CHECK: (data (i32.const 4000) "zeros\00in\00the\00middle") - - ;; CHECK: (data (i32.const 4035) "nice skip here") - - ;; CHECK: (data (i32.const 4066) "another\00but no") - - ;; CHECK: (func $nonzero-size-init-of-active-will-trap - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nonzero-size-init-of-active-will-trap - (memory.init 0 - (i32.const 42) - (i32.const 0) - (i32.const 13) - ) - (data.drop 0) - ) - - ;; CHECK: (func $nonzero-offset-init-of-active-will-trap - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nonzero-offset-init-of-active-will-trap - (memory.init 0 - (i32.const 42) - (i32.const 13) - (i32.const 0) - ) - (data.drop 0) - ) - - ;; CHECK: (func $zero-offset-size-init-of-active-may-trap - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $zero-offset-size-init-of-active-may-trap - (memory.init 0 - (i32.const 42) - (i32.const 0) - (i32.const 0) - ) - (data.drop 0) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $__mem_segment_drop_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_0 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_1 (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - - (data "not referenced, delete me") ;; 0 - - ;; CHECK: (data "zeroes at start") - - ;; CHECK: (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes at start") - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes at start") ;; 1 - - ;; CHECK: (data "\00\00\00few zeroes at start") - - ;; CHECK: (data "zeroes at end") - - ;; CHECK: (data "zeroes at end\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") - - ;; CHECK: (data "few zeroes at end\00\00\00") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "in middle") - - ;; CHECK: (data "zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00in middle") - - ;; CHECK: (data "few zeroes\00\00\00in middle") - - ;; CHECK: (data "multiple") - - ;; CHECK: (data "spans") - - ;; CHECK: (data "of zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "no zeroes") - - ;; CHECK: (func $zeroes-at-start - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 0 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zeroes-at-start - (memory.init 1 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (data.drop 1) - ) - - ;; the not-split tests have too many memory.init and data.drop instructions for splitting to be worth it - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes at start") ;; 2 - - ;; CHECK: (func $zeroes-at-start-not-split - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 1) - ;; CHECK-NEXT: ) - (func $zeroes-at-start-not-split - (memory.init 2 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (memory.init 2 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (memory.init 2 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (memory.init 2 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (data.drop 2) - ) - - (data "\00\00\00few zeroes at start") ;; 3 - - ;; CHECK: (func $few-zeroes-at-start - ;; CHECK-NEXT: (memory.init 2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 2) - ;; CHECK-NEXT: ) - (func $few-zeroes-at-start - (memory.init 3 - (i32.const 0) - (i32.const 0) - (i32.const 22) - ) - (data.drop 3) - ) - - (data "zeroes at end\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 4 - - ;; CHECK: (func $zeroes-at-end - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (memory.init 3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 3) - ;; CHECK-NEXT: ) - (func $zeroes-at-end - (memory.init 4 - (i32.const 0) - (i32.const 0) - (i32.const 43) - ) - (data.drop 4) - ) - - (data "zeroes at end\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 5 - - ;; CHECK: (func $zeroes-at-end-not-split - ;; CHECK-NEXT: (memory.init 4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 4) - ;; CHECK-NEXT: ) - (func $zeroes-at-end-not-split - (memory.init 5 - (i32.const 0) - (i32.const 0) - (i32.const 43) - ) - (memory.init 5 - (i32.const 0) - (i32.const 0) - (i32.const 43) - ) - (memory.init 5 - (i32.const 0) - (i32.const 0) - (i32.const 43) - ) - (memory.init 5 - (i32.const 0) - (i32.const 0) - (i32.const 43) - ) - (data.drop 5) - ) - - (data "few zeroes at end\00\00\00") ;; 6 - - ;; CHECK: (func $few-zeroes-at-end - ;; CHECK-NEXT: (memory.init 5 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 5) - ;; CHECK-NEXT: ) - (func $few-zeroes-at-end - (memory.init 6 - (i32.const 0) - (i32.const 0) - (i32.const 20) - ) - (data.drop 6) - ) - - (data "zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00in middle") ;; 7 - - ;; CHECK: (func $zeroes-in-middle - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (memory.init 6 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 7 - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (data.drop 6) - ;; CHECK-NEXT: (data.drop 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zeroes-in-middle - (memory.init 7 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (data.drop 7) - ) - - (data "zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00in middle") ;; 8 - - ;; CHECK: (func $zeroes-in-middle-not-split - ;; CHECK-NEXT: (memory.init 8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 8) - ;; CHECK-NEXT: ) - (func $zeroes-in-middle-not-split - (memory.init 8 - (i32.const 0) - (i32.const 0) - (i32.const 35) - ) - (memory.init 8 - (i32.const 0) - (i32.const 0) - (i32.const 45) - ) - (data.drop 8) - ) - - (data "few zeroes\00\00\00in middle") ;; 9 - - ;; CHECK: (func $few-zeroes-in-middle - ;; CHECK-NEXT: (memory.init 9 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 9) - ;; CHECK-NEXT: ) - (func $few-zeroes-in-middle - (memory.init 9 - (i32.const 0) - (i32.const 0) - (i32.const 22) - ) - (data.drop 9) - ) - - (data "multiple\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00spans\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00of zeroes") ;; 10 - - ;; CHECK: (func $multiple-spans-of-zeroes - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (memory.init 10 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 11 - ;; CHECK-NEXT: (i32.const 38) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 12 - ;; CHECK-NEXT: (i32.const 73) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (data.drop 10) - ;; CHECK-NEXT: (data.drop 11) - ;; CHECK-NEXT: (data.drop 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $multiple-spans-of-zeroes - (memory.init 10 - (i32.const 0) - (i32.const 0) - (i32.const 82) - ) - (data.drop 10) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 11 - - ;; CHECK: (func $even-more-zeroes - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 13 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 14 - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 68) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 15 - ;; CHECK-NEXT: (i32.const 98) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 13) - ;; CHECK-NEXT: (data.drop 14) - ;; CHECK-NEXT: (data.drop 15) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $even-more-zeroes - (memory.init 11 - (i32.const 0) - (i32.const 0) - (i32.const 134) - ) - (data.drop 11) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 12 - - ;; CHECK: (func $only-zeroes - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $only-zeroes - (memory.init 12 - (i32.const 0) - (i32.const 0) - (i32.const 30) - ) - (data.drop 12) - ) - - (data "no zeroes") ;; 13 - - ;; CHECK: (func $no-zeroes - ;; CHECK-NEXT: (memory.init 16 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 16) - ;; CHECK-NEXT: ) - (func $no-zeroes - (memory.init 13 - (i32.const 0) - (i32.const 0) - (i32.const 9) - ) - (data.drop 13) - ) - - (data "") ;; 14 - - ;; CHECK: (func $empty - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $empty - (memory.init 14 - (i32.const 13) - (i32.const 0) - (i32.const 0) - ) - (data.drop 14) - ) - - (data "only dropped") ;; 15 - - ;; CHECK: (func $only-dropped - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $only-dropped - (data.drop 15) - (data.drop 15) - ) - - (data "\00\00\00\00\00") ;; 16 - - ;; CHECK: (func $only-dropped-zeroes - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $only-dropped-zeroes - (data.drop 16) - (data.drop 16) - ) - - (data "") ;; not referenced - - (data "\00\00\00\00\00") ;; not referenced -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "param" (global $param i32)) - - ;; CHECK: (global $__mem_segment_drop_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_0 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_1 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_2 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_3 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_4 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_5 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_6 (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - (import "env" "param" (global $param i32)) - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 0 - - ;; CHECK: (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (data "even") - - ;; CHECK: (data "more") - - ;; CHECK: (data "zeroes") - - ;; CHECK: (func $nonconst-dest - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (global.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 68) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 98) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 0) - ;; CHECK-NEXT: (data.drop 1) - ;; CHECK-NEXT: (data.drop 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nonconst-dest - (memory.init 0 - (global.get $param) - (i32.const 0) - (i32.const 134) - ) - (data.drop 0) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 1 - - ;; CHECK: (func $nonconst-offset - ;; CHECK-NEXT: (memory.init 3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $param) - ;; CHECK-NEXT: (i32.const 134) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 3) - ;; CHECK-NEXT: ) - (func $nonconst-offset - (memory.init 1 - (i32.const 0) - (global.get $param) - (i32.const 134) - ) - (data.drop 1) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 2 - - ;; CHECK: (func $nonconst-size - ;; CHECK-NEXT: (memory.init 4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (global.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 4) - ;; CHECK-NEXT: ) - (func $nonconst-size - (memory.init 2 - (i32.const 0) - (i32.const 0) - (global.get $param) - ) - (data.drop 2) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 3 - - ;; CHECK: (func $partial-skip-start - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 5 - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 6 - ;; CHECK-NEXT: (i32.const 54) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 58) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 7 - ;; CHECK-NEXT: (i32.const 88) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 94) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 5) - ;; CHECK-NEXT: (data.drop 6) - ;; CHECK-NEXT: (data.drop 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial-skip-start - (memory.init 3 - (i32.const 0) - (i32.const 10) - (i32.const 124) - ) - (data.drop 3) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 4 - - ;; CHECK: (func $full-skip-start - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (memory.init 8 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 9 - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 36) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 10 - ;; CHECK-NEXT: (i32.const 66) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 72) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (data.drop 8) - ;; CHECK-NEXT: (data.drop 9) - ;; CHECK-NEXT: (data.drop 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $full-skip-start - (memory.init 4 - (i32.const 0) - (i32.const 32) - (i32.const 102) - ) - (data.drop 4) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 5 - - ;; CHECK: (func $partial-skip-end - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 11 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 12 - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 68) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 13 - ;; CHECK-NEXT: (i32.const 98) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 11) - ;; CHECK-NEXT: (data.drop 12) - ;; CHECK-NEXT: (data.drop 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial-skip-end - (memory.init 5 - (i32.const 0) - (i32.const 0) - (i32.const 124) - ) - (data.drop 5) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 6 - - ;; CHECK: (func $full-skip-end - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_2) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 14 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 15 - ;; CHECK-NEXT: (i32.const 64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 68) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 16 - ;; CHECK-NEXT: (i32.const 98) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 14) - ;; CHECK-NEXT: (data.drop 15) - ;; CHECK-NEXT: (data.drop 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $full-skip-end - (memory.init 6 - (i32.const 0) - (i32.const 0) - (i32.const 102) - ) - (data.drop 6) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 7 - - ;; CHECK: (func $slice-zeroes - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_3) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_3 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 17) - ;; CHECK-NEXT: (data.drop 18) - ;; CHECK-NEXT: (data.drop 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $slice-zeroes - (memory.init 7 - (i32.const 0) - (i32.const 35) - (i32.const 10) - ) - (data.drop 7) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 8 - - ;; CHECK: (func $slice-nonzeroes - ;; CHECK-NEXT: (memory.init 20 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (data.drop 20) - ;; CHECK-NEXT: (data.drop 21) - ;; CHECK-NEXT: (data.drop 22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $slice-nonzeroes - (memory.init 8 - (i32.const 0) - (i32.const 31) - (i32.const 2) - ) - (data.drop 8) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 9 - - ;; CHECK: (func $zero-size - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 23) - ;; CHECK-NEXT: (data.drop 24) - ;; CHECK-NEXT: (data.drop 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-size - (memory.init 9 - (i32.const 13) - (i32.const 40) - (i32.const 0) - ) - (data.drop 9) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 10 - - ;; CHECK: (func $zero-size-undropped - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-size-undropped - (memory.init 10 - (i32.const 13) - (i32.const 40) - (i32.const 0) - ) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 11 - - ;; CHECK: (func $out-of-bounds-offset - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 135) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $out-of-bounds-offset - (memory.init 11 - (i32.const 0) - (i32.const 135) - (i32.const 1) - ) - (data.drop 11) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 12 - - ;; CHECK: (func $zero-size-out-of-bounds-offset - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 135) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $zero-size-out-of-bounds-offset - (memory.init 12 - (i32.const 0) - (i32.const 135) - (i32.const 0) - ) - (data.drop 12) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 13 - - ;; CHECK: (func $out-of-bounds-size - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 135) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $out-of-bounds-size - (memory.init 13 - (i32.const 0) - (i32.const 0) - (i32.const 135) - ) - (data.drop 13) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 14 - - ;; CHECK: (func $zero-size-at-bounds-offset - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_6 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 29) - ;; CHECK-NEXT: (data.drop 30) - ;; CHECK-NEXT: (data.drop 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-size-at-bounds-offset - (memory.init 14 - (i32.const 0) - (i32.const 134) - (i32.const 0) - ) - (data.drop 14) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $__mem_segment_drop_state (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_0 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_1 (mut i32) (i32.const 0)) - - ;; CHECK: (global $__mem_segment_drop_state_2 (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - (data "hi\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 0 - - ;; CHECK: (data "hi") - - ;; CHECK: (data "even") - - ;; CHECK: (data "hi") - - ;; CHECK: (data "hi") - - ;; CHECK: (data "even") - - ;; CHECK: (data "hi") - - ;; CHECK: (data "even") - - ;; CHECK: (data "hi") - - ;; CHECK: (data "even") - - ;; CHECK: (data "hi") - - ;; CHECK: (func $zero-length-init-zeroes - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 0) - ;; CHECK-NEXT: (data.drop 1) - ;; CHECK-NEXT: (data.drop 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-length-init-zeroes - (memory.init 0 - (i32.const 13) - (i32.const 10) - (i32.const 0) - ) - (data.drop 0) - ) - - (data "hi\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 1 - - ;; CHECK: (func $zero-length-init-nonzeroes - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 3) - ;; CHECK-NEXT: (data.drop 4) - ;; CHECK-NEXT: (data.drop 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-length-init-nonzeroes - (memory.init 1 - (i32.const 13) - (i32.const 33) - (i32.const 0) - ) - (data.drop 1) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 2 - - ;; CHECK: (func $zero-length-init-zeroes-2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 6) - ;; CHECK-NEXT: (data.drop 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-length-init-zeroes-2 - (memory.init 2 - (i32.const 13) - (i32.const 10) - (i32.const 0) - ) - (data.drop 2) - ) - - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 3 - - ;; CHECK: (func $zero-length-init-nonzeroes-2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state_2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (global.set $__mem_segment_drop_state_2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (data.drop 8) - ;; CHECK-NEXT: (data.drop 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-length-init-nonzeroes-2 - (memory.init 3 - (i32.const 13) - (i32.const 31) - (i32.const 0) - ) - (data.drop 3) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 2048 2048) - (memory $0 2048 2048) - (data "a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a") ;; 64 ranges of zeroes - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (data "a") - - ;; CHECK: (func $init-lots - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (memory.init 0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 2 - ;; CHECK-NEXT: (i32.const 62) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 63) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 3 - ;; CHECK-NEXT: (i32.const 93) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 94) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 4 - ;; CHECK-NEXT: (i32.const 124) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 125) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 5 - ;; CHECK-NEXT: (i32.const 155) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 156) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 6 - ;; CHECK-NEXT: (i32.const 186) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 187) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 7 - ;; CHECK-NEXT: (i32.const 217) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 218) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 8 - ;; CHECK-NEXT: (i32.const 248) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 249) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 9 - ;; CHECK-NEXT: (i32.const 279) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 280) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 10 - ;; CHECK-NEXT: (i32.const 310) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 311) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 11 - ;; CHECK-NEXT: (i32.const 341) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 342) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 12 - ;; CHECK-NEXT: (i32.const 372) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 373) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 13 - ;; CHECK-NEXT: (i32.const 403) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 404) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 14 - ;; CHECK-NEXT: (i32.const 434) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 435) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 15 - ;; CHECK-NEXT: (i32.const 465) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 466) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 16 - ;; CHECK-NEXT: (i32.const 496) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 497) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 17 - ;; CHECK-NEXT: (i32.const 527) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 528) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 18 - ;; CHECK-NEXT: (i32.const 558) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 559) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 19 - ;; CHECK-NEXT: (i32.const 589) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 590) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 20 - ;; CHECK-NEXT: (i32.const 620) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 621) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 21 - ;; CHECK-NEXT: (i32.const 651) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 652) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 22 - ;; CHECK-NEXT: (i32.const 682) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 683) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 23 - ;; CHECK-NEXT: (i32.const 713) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 714) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 24 - ;; CHECK-NEXT: (i32.const 744) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 745) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 25 - ;; CHECK-NEXT: (i32.const 775) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 776) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 26 - ;; CHECK-NEXT: (i32.const 806) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 807) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 27 - ;; CHECK-NEXT: (i32.const 837) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 838) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 28 - ;; CHECK-NEXT: (i32.const 868) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 869) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 29 - ;; CHECK-NEXT: (i32.const 899) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 900) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 30 - ;; CHECK-NEXT: (i32.const 930) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 931) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 31 - ;; CHECK-NEXT: (i32.const 961) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 962) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 32 - ;; CHECK-NEXT: (i32.const 992) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 993) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 33 - ;; CHECK-NEXT: (i32.const 1023) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 34 - ;; CHECK-NEXT: (i32.const 1054) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1055) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 35 - ;; CHECK-NEXT: (i32.const 1085) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1086) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 36 - ;; CHECK-NEXT: (i32.const 1116) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1117) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 37 - ;; CHECK-NEXT: (i32.const 1147) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1148) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 38 - ;; CHECK-NEXT: (i32.const 1178) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1179) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 39 - ;; CHECK-NEXT: (i32.const 1209) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1210) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 40 - ;; CHECK-NEXT: (i32.const 1240) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1241) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 41 - ;; CHECK-NEXT: (i32.const 1271) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1272) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 42 - ;; CHECK-NEXT: (i32.const 1302) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1303) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 43 - ;; CHECK-NEXT: (i32.const 1333) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 1334) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (data.drop 0) - ;; CHECK-NEXT: (data.drop 1) - ;; CHECK-NEXT: (data.drop 2) - ;; CHECK-NEXT: (data.drop 3) - ;; CHECK-NEXT: (data.drop 4) - ;; CHECK-NEXT: (data.drop 5) - ;; CHECK-NEXT: (data.drop 6) - ;; CHECK-NEXT: (data.drop 7) - ;; CHECK-NEXT: (data.drop 8) - ;; CHECK-NEXT: (data.drop 9) - ;; CHECK-NEXT: (data.drop 10) - ;; CHECK-NEXT: (data.drop 11) - ;; CHECK-NEXT: (data.drop 12) - ;; CHECK-NEXT: (data.drop 13) - ;; CHECK-NEXT: (data.drop 14) - ;; CHECK-NEXT: (data.drop 15) - ;; CHECK-NEXT: (data.drop 16) - ;; CHECK-NEXT: (data.drop 17) - ;; CHECK-NEXT: (data.drop 18) - ;; CHECK-NEXT: (data.drop 19) - ;; CHECK-NEXT: (data.drop 20) - ;; CHECK-NEXT: (data.drop 21) - ;; CHECK-NEXT: (data.drop 22) - ;; CHECK-NEXT: (data.drop 23) - ;; CHECK-NEXT: (data.drop 24) - ;; CHECK-NEXT: (data.drop 25) - ;; CHECK-NEXT: (data.drop 26) - ;; CHECK-NEXT: (data.drop 27) - ;; CHECK-NEXT: (data.drop 28) - ;; CHECK-NEXT: (data.drop 29) - ;; CHECK-NEXT: (data.drop 30) - ;; CHECK-NEXT: (data.drop 31) - ;; CHECK-NEXT: (data.drop 32) - ;; CHECK-NEXT: (data.drop 33) - ;; CHECK-NEXT: (data.drop 34) - ;; CHECK-NEXT: (data.drop 35) - ;; CHECK-NEXT: (data.drop 36) - ;; CHECK-NEXT: (data.drop 37) - ;; CHECK-NEXT: (data.drop 38) - ;; CHECK-NEXT: (data.drop 39) - ;; CHECK-NEXT: (data.drop 40) - ;; CHECK-NEXT: (data.drop 41) - ;; CHECK-NEXT: (data.drop 42) - ;; CHECK-NEXT: (data.drop 43) - ;; CHECK-NEXT: (data.drop 44) - ;; CHECK-NEXT: (data.drop 45) - ;; CHECK-NEXT: (data.drop 46) - ;; CHECK-NEXT: (data.drop 47) - ;; CHECK-NEXT: (data.drop 48) - ;; CHECK-NEXT: (data.drop 49) - ;; CHECK-NEXT: (data.drop 50) - ;; CHECK-NEXT: (data.drop 51) - ;; CHECK-NEXT: (data.drop 52) - ;; CHECK-NEXT: (data.drop 53) - ;; CHECK-NEXT: (data.drop 54) - ;; CHECK-NEXT: (data.drop 55) - ;; CHECK-NEXT: (data.drop 56) - ;; CHECK-NEXT: (data.drop 57) - ;; CHECK-NEXT: (data.drop 58) - ;; CHECK-NEXT: (data.drop 59) - ;; CHECK-NEXT: (data.drop 60) - ;; CHECK-NEXT: (data.drop 61) - ;; CHECK-NEXT: (data.drop 62) - ;; CHECK-NEXT: (data.drop 63) - ;; CHECK-NEXT: (data.drop 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $init-lots - (memory.init 0 - (i32.const 0) - (i32.const 0) - (i32.const 1345) - ) - (data.drop 0) - ) -) -(module - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (data (i32.const 1024) "x") - (data (i32.const 1024) "\00") ;; this tramples the "x", and so must be kept. -) -;; CHECK: (data (i32.const 1024) "x") - -;; CHECK: (data (i32.const 1024) "\00") -(module - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (data (i32.const 1024) "x") - (data (i32.const 1025) "\00") -) -;; CHECK: (data (i32.const 1024) "x") -(module - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (data (i32.const 1024) "x") - (data (i32.const 1023) "\00") -) -;; CHECK: (data (i32.const 1024) "x") -(module - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (data (i32.const 1024) "x") - (data (i32.const 1024) "\00") ;; when we see one bad thing, we give up - (data (i32.const 4096) "\00") -) -;; CHECK: (data (i32.const 1024) "x") - -;; CHECK: (data (i32.const 1024) "\00") - -;; CHECK: (data (i32.const 4096) "\00") -(module - ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (import "env" "memoryBase" (global $memoryBase i32)) - (data (i32.const 1024) "x") - (data (global.get $memoryBase) "\00") ;; this could trample, or not -) -;; CHECK: (data (i32.const 1024) "x") - -;; CHECK: (data (global.get $memoryBase) "\00") -(module - ;; CHECK: (import "env" "memoryBase" (global $memoryBase i32)) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (import "env" "memoryBase" (global $memoryBase i32)) - (data (i32.const 1024) "\00") ;; this could trample, or not - (data (global.get $memoryBase) "x") -) -;; CHECK: (data (i32.const 1024) "\00") - -;; CHECK: (data (global.get $memoryBase) "x") -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $__mem_segment_drop_state (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (data "skipped\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00included") - ;; CHECK: (data "skipped") - - ;; CHECK: (data "included") - - ;; CHECK: (export "func_54" (func $0)) - (export "func_54" (func $0)) - ;; CHECK: (func $0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $__mem_segment_drop_state) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.init 1 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (memory.init 0 - (i32.const 0) - (i32.const 7) - (i32.const 38) - ) - ) -) -(module - ;; we can't optimize on an imported memory without zeroFilledMemory being set. - ;; CHECK: (import "env" "memory" (memory $0 1 1)) - (import "env" "memory" (memory $0 1 1)) - (data (i32.const 1024) "x") - (data (i32.const 2048) "\00") -) -;; CHECK: (data (i32.const 1024) "x") - -;; CHECK: (data (i32.const 2048) "\00") -(module - ;; we can when not imported - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (data (i32.const 1024) "x") - (data (i32.const 2048) "\00") -) - -;; CHECK: (data (i32.const 1024) "x") -(module - ;; Regression test for a bug where referrers were accidentally associated with - ;; the wrong segments in the presence of unreferenced segments. - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (memory $0 (shared 1 1)) - (memory $0 (shared 1 1)) - (data (i32.const 0) "") - ;; CHECK: (data "foo") - (data "foo") - ;; CHECK: (func $0 - ;; CHECK-NEXT: (memory.init 0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 - (memory.init 1 - (i32.const 0) - (i32.const 1) - (i32.const 1) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/memory-packing_zero-filled-memory.wast binaryen-99/test/lit/passes/memory-packing_zero-filled-memory.wast --- binaryen-108/test/lit/passes/memory-packing_zero-filled-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/memory-packing_zero-filled-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: wasm-opt %s --memory-packing -all --zero-filled-memory -S -o - | filecheck %s - -(module - ;; we can optimize on an imported memory with zeroFilledMemory being set. - ;; CHECK: (import "env" "memory" (memory $0 1 1)) - (import "env" "memory" (memory $0 1 1)) - - (data (i32.const 1024) "x") - (data (i32.const 1023) "\00") -) -;; CHECK: (data (i32.const 1024) "x") diff -Nru binaryen-108/test/lit/passes/merge-blocks.wast binaryen-99/test/lit/passes/merge-blocks.wast --- binaryen-108/test/lit/passes/merge-blocks.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/merge-blocks.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,408 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names --merge-blocks -all -S -o - \ -;; RUN: | filecheck %s -;; -;; --remove-unused-names lets --merge-blocks assume blocks without names have no -;; branch targets. - -(module - (type $anyref_=>_none (func (param anyref))) - - ;; CHECK: (type $struct (struct (field (mut i32)))) - (type $struct (struct (field (mut i32)))) - - ;; CHECK: (type $array (array (mut i32))) - (type $array (array (mut i32))) - - ;; CHECK: (func $br_on_to_drop - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $label$1 (result (ref null i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_i31 $label$1 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_to_drop - (nop) ;; ensure a block at the function level - (drop - (block $label$1 (result (ref null i31)) ;; this block type must stay, we - ;; cannot remove it due to the br_on - (drop - (br_on_i31 $label$1 - (ref.null any) - ) - ) - (ref.null i31) ;; this must not end up dropped - ) - ) - ) - - ;; CHECK: (func $struct.set - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $struct.set - (block - (nop) - (struct.set $struct 0 - (block (result (ref null $struct)) - (drop (i32.const 1234)) - (ref.null $struct) - ) - (i32.const 5) - ) - (nop) - ) - ) - - ;; CHECK: (func $struct.get - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $struct.get - (block - (nop) - (drop - (struct.get $struct 0 - (block (result (ref null $struct)) - (drop (i32.const 1234)) - (ref.null $struct) - ) - ) - ) - (nop) - ) - ) - - ;; CHECK: (func $array.set (param $foo (ref $array)) - ;; CHECK-NEXT: (local $bar (ref null $array)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (array.set $array - ;; CHECK-NEXT: (local.tee $bar - ;; CHECK-NEXT: (local.get $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $array.set (param $foo (ref $array)) - (local $bar (ref null $array)) - (array.set $array - (block $block (result (ref null $array)) - (nop) - (nop) - (nop) - ;; Side effects in the first item on the array.set do not prevent moving - ;; the nops outside. - (local.tee $bar - (local.get $foo) - ) - ) - (i32.const 0) - (i32.const 37) - ) - ) - - ;; CHECK: (func $array.set-no-1 (param $foo (ref $array)) - ;; CHECK-NEXT: (local $bar i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (array.set $array - ;; CHECK-NEXT: (local.get $foo) - ;; CHECK-NEXT: (local.tee $bar - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $array.set-no-1 (param $foo (ref $array)) - (local $bar i32) - (array.set $array - (local.get $foo) - (block $block (result i32) - (nop) - (nop) - (nop) - ;; Side effects in the second item do prevent optimizations, currently. - (local.tee $bar - (i32.const 0) - ) - ) - (i32.const 37) - ) - ) - - ;; CHECK: (func $array.set-no-2 (param $foo (ref $array)) - ;; CHECK-NEXT: (local $bar i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (array.set $array - ;; CHECK-NEXT: (local.get $foo) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $bar - ;; CHECK-NEXT: (i32.const 37) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $array.set-no-2 (param $foo (ref $array)) - (local $bar i32) - (array.set $array - (local.get $foo) - (i32.const 0) - (block $block (result i32) - (nop) - (nop) - (nop) - ;; Side effects in the third item do prevent optimizations, currently. - (local.tee $bar - (i32.const 37) - ) - ) - ) - ) - - ;; CHECK: (func $if-condition (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-condition (result i32) - ;; Content can be moved out of an if condition, but not anywhere else. - (if (result i32) - (block (result i32) - (drop (i32.const 0)) - (i32.const 1) - ) - (block (result i32) - (drop (i32.const 2)) - (i32.const 3) - ) - (block (result i32) - (drop (i32.const 4)) - (i32.const 5) - ) - ) - ) - - ;; CHECK: (func $subsequent-children (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $subsequent-children - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subsequent-children (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; Both of the calls to helper can be moved outside. Those calls remain in - ;; order after doing so, so there is no problem, and none of them are moved - ;; across anything with side effects. This leaves only consts in the call to - ;; $subsequent-children. - (call $subsequent-children - (block (result i32) - (drop (call $helper (i32.const 0))) - (i32.const 1) - ) - (i32.const 2) - (block (result i32) - (drop (call $helper (i32.const 3))) - (i32.const 4) - ) - ) - ) - - ;; CHECK: (func $subsequent-children-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $subsequent-children-1 - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subsequent-children-1 (param $x i32) (param $y i32) (param $z i32) (result i32) - (call $subsequent-children-1 - (block (result i32) - (drop (call $helper (i32.const 0))) - (call $helper (i32.const 1)) ;; Compared to before, this is now a call, so - ;; it has side effects, and the call with arg - ;; 3 cannot be moved past it. - ) - (i32.const 2) - (block (result i32) - (drop (call $helper (i32.const 3))) - (i32.const 4) - ) - ) - ) - - ;; CHECK: (func $subsequent-children-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $subsequent-children-2 - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subsequent-children-2 (param $x i32) (param $y i32) (param $z i32) (result i32) - (call $subsequent-children-2 - (block (result i32) - (drop (call $helper (i32.const 0))) - (call $helper (i32.const 1)) - ) - ;; Similar to the above, but with the main call's last two arguments flipped. - ;; This should not have an effect on the output: we still can't pull out the - ;; call with arg 3. - (block (result i32) - (drop (call $helper (i32.const 3))) - (i32.const 4) - ) - (i32.const 2) - ) - ) - - ;; CHECK: (func $subsequent-children-3 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $subsequent-children-3 - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subsequent-children-3 (param $x i32) (param $y i32) (param $z i32) (result i32) - (call $subsequent-children-3 - (block (result i32) - (drop (i32.const 0)) ;; Similar to the above, but this is just a const now - ;; and not a call. We still can't pull out the call - ;; with arg 3, due to the call with arg 1. - (call $helper (i32.const 1)) - ) - (block (result i32) - (drop (call $helper (i32.const 3))) - (i32.const 4) - ) - (i32.const 2) - ) - ) - - ;; CHECK: (func $subsequent-children-4 (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $subsequent-children-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subsequent-children-4 (param $x i32) (param $y i32) (param $z i32) (result i32) - (call $subsequent-children-4 - (block (result i32) - (drop (i32.const 0)) - ;; Similar to the above, but remove the call on arg 1 as well. Now we *can* - ;; pull out the call with arg 3. - (i32.const 1) - ) - (block (result i32) - (drop (call $helper (i32.const 3))) - (i32.const 4) - ) - (i32.const 2) - ) - ) - - ;; CHECK: (func $helper (param $x i32) (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $helper (param $x i32) (result i32) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/passes/merge-similar-functions_all-features.wast binaryen-99/test/lit/passes/merge-similar-functions_all-features.wast --- binaryen-108/test/lit/passes/merge-similar-functions_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/merge-similar-functions_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: foreach %s %t wasm-opt --all-features --merge-similar-functions -S -o - | filecheck %s - -(module - ;; CHECK: (type $[i8] (array i8)) - (type $[i8] (array i8)) - - ;; CHECK: (func $take-ref-null-data (param $0 (ref null data)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $take-ref-null-data (param (ref null data)) - (unreachable) - ) - ;; CHECK: (func $take-ref-eq (param $0 (ref eq)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $take-ref-eq (param (ref eq)) - (unreachable) - ) - - ;; NOTE: When type A is a subtype of type B and type C, - ;; and func X takes a type B arg, and func Y takes a type C arg. - ;; Then both func X and Y are callable with a type A arg. - ;; But in general, type B and C don't have a common subtype, so - ;; we can't merge call instructions of func X and Y. - - ;; CHECK: (func $no-call-subtyping-same-operand-0 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $take-ref-null-data - ;; CHECK-NEXT: (array.init_static $[i8]) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-call-subtyping-same-operand-0 - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $take-ref-null-data - (array.init_static $[i8]) - ) - ) - ;; CHECK: (func $no-call-subtyping-same-operand-1 - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $take-ref-eq - ;; CHECK-NEXT: (array.init_static $[i8]) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-call-subtyping-same-operand-1 - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $take-ref-eq - (array.init_static $[i8]) - ) - ) - -) diff -Nru binaryen-108/test/lit/passes/merge-similar-functions_types.wast binaryen-99/test/lit/passes/merge-similar-functions_types.wast --- binaryen-108/test/lit/passes/merge-similar-functions_types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/merge-similar-functions_types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,323 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --merge-similar-functions -all -S -o - \ -;; RUN: | filecheck %s -;; RUN: foreach %s %t wasm-opt --merge-similar-functions -all --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix=NOMNL - -;; Calls to functions $2 and $3 are the only differences between the contents -;; of $0 and $1, so we want to merge them and pass ref.funcs of $2 and $3. -;; However, their nominal types differ, so in nominal typing we cannot do so. -(module - ;; CHECK: (type $type$0 (func)) - ;; NOMNL: (type $type$0 (func_subtype func)) - (type $type$0 (func_subtype func)) - ;; NOMNL: (type $type$1 (func_subtype func)) - (type $type$1 (func_subtype func)) - ;; NOMNL: (type $type$2 (func_subtype func)) - (type $type$2 (func_subtype func)) - (type $type$3 (func_subtype (param f32) (result f32) func)) - (type $type$4 (func_subtype (param f64) (result f64) func)) - ;; CHECK: (type $ref|$type$0|_=>_none (func (param (ref $type$0)))) - - ;; CHECK: (elem declare func $2 $3) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (call $byn$mgfn-shared$0 - ;; CHECK-NEXT: (ref.func $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $0 (type $type$0) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (call $2) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $0 (type $type$0) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (call $2) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (call $byn$mgfn-shared$0 - ;; CHECK-NEXT: (ref.func $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $type$0) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (call $3) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $1 (type $type$0) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (call $3) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - ) - ;; CHECK: (func $2 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $2 (type $type$1) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 17) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $2 (type $type$1) - (drop - (i32.const 17) - ) - ) - ;; CHECK: (func $3 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $3 (type $type$2) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 999) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $3 (type $type$2) - (drop - (i32.const 999) - ) - ) -) - - - - -;; CHECK: (func $byn$mgfn-shared$0 (param $0 (ref $type$0)) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (call_ref -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: ) -(module - ;; As above, but now the nominal types do match, so we can optimize in all - ;; modes. - - ;; CHECK: (type $type$0 (func)) - ;; NOMNL: (type $type$1 (func_subtype func)) - - ;; NOMNL: (type $type$0 (func_subtype func)) - (type $type$0 (func_subtype func)) - (type $type$1 (func_subtype func)) - (type $type$3 (func_subtype (param f32) (result f32) func)) - (type $type$4 (func_subtype (param f64) (result f64) func)) - ;; CHECK: (type $ref|$type$0|_=>_none (func (param (ref $type$0)))) - - ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) - ;; NOMNL: (type $ref|$type$1|_=>_none (func_subtype (param (ref $type$1)) func)) - - ;; NOMNL: (global $global$0 (mut i32) (i32.const 10)) - (global $global$0 (mut i32) (i32.const 10)) - ;; CHECK: (memory $0 (shared 16 17)) - ;; NOMNL: (memory $0 (shared 16 17)) - (memory $0 (shared 16 17)) - ;; CHECK: (elem declare func $2 $3) - - ;; CHECK: (func $0 - ;; CHECK-NEXT: (call $byn$mgfn-shared$0 - ;; CHECK-NEXT: (ref.func $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (elem declare func $2 $3) - - ;; NOMNL: (func $0 (type $type$0) - ;; NOMNL-NEXT: (call $byn$mgfn-shared$0 - ;; NOMNL-NEXT: (ref.func $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $0 (type $type$0) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (call $2) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - ) - ;; CHECK: (func $1 - ;; CHECK-NEXT: (call $byn$mgfn-shared$0 - ;; CHECK-NEXT: (ref.func $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $1 (type $type$0) - ;; NOMNL-NEXT: (call $byn$mgfn-shared$0 - ;; NOMNL-NEXT: (ref.func $3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $1 (type $type$0) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (call $3) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - ) - ;; CHECK: (func $2 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $2 (type $type$1) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 17) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $2 (type $type$1) - (drop - (i32.const 17) - ) - ) - ;; CHECK: (func $3 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 999) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $3 (type $type$1) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 999) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $3 (type $type$1) - (drop - (i32.const 999) - ) - ) -) -;; CHECK: (func $byn$mgfn-shared$0 (param $0 (ref $type$0)) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (call_ref -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: ) - -;; NOMNL: (func $byn$mgfn-shared$0 (type $ref|$type$1|_=>_none) (param $0 (ref $type$1)) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (call_ref -;; NOMNL-NEXT: (local.get $0) -;; NOMNL-NEXT: ) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: (nop) -;; NOMNL-NEXT: ) diff -Nru binaryen-108/test/lit/passes/merge-similar-functions.wast binaryen-99/test/lit/passes/merge-similar-functions.wast --- binaryen-108/test/lit/passes/merge-similar-functions.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/merge-similar-functions.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,497 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --enable-reference-types --enable-typed-function-references --merge-similar-functions -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (func $big-const-42 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$big-const-42 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $big-const-42 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.const 42) - ) - - ;; same as $big-const-42, but the set of $big-const-* derives {42, 42, 43} params - ;; CHECK: (func $big-const-42-1 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$big-const-42 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $big-const-42-1 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.const 42) - ) - ;; CHECK: (func $big-const-43 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$big-const-42 - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $big-const-43 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.const 43) - ) - - ;; CHECK: (func $small-const-44 (result i32) - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - (func $small-const-44 (result i32) - (i32.const 44) - ) - ;; CHECK: (func $small-const-45 (result i32) - ;; CHECK-NEXT: (i32.const 45) - ;; CHECK-NEXT: ) - (func $small-const-45 (result i32) - (i32.const 45) - ) -) - -;; offset locals for extra params -;; CHECK: (func $byn$mgfn-shared$big-const-42 (param $0 i32) (result i32) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (func $take-param-and-local-0 (param $0 i32) (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$take-param-and-local-0 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $take-param-and-local-0 (param $0 i32) (result i32) - (local $1 i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.add (i32.add (i32.const 42) (local.get $0)) (local.get $1)) - ) - ;; CHECK: (func $take-param-and-local-1 (param $0 i32) (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$take-param-and-local-0 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $take-param-and-local-1 (param $0 i32) (result i32) - (local $1 i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.add (i32.add (i32.const 43) (local.get $0)) (local.get $1)) - ) - -) - -;; different callees -;; CHECK: (func $byn$mgfn-shared$take-param-and-local-0 (param $0 i32) (param $1 i32) (result i32) -;; CHECK-NEXT: (local $2 i32) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (i32.add -;; CHECK-NEXT: (i32.add -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $ref|none_->_i32|_=>_i32 (func (param (ref $none_=>_i32)) (result i32))) - - ;; CHECK: (type $ref|i32_->_i32|_i32_=>_i32 (func (param (ref $i32_=>_i32) i32) (result i32))) - - ;; CHECK: (elem declare func $callee-0 $callee-1 $callee-2 $callee-take-arg-0 $callee-take-arg-1) - - ;; CHECK: (func $callee-0 (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $callee-0 (result i32) (i32.const 0)) - ;; CHECK: (func $callee-1 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $callee-1 (result i32) (i32.const 1)) - ;; CHECK: (func $callee-2 (result i32) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - (func $callee-2 (result i32) (i32.const 2)) - - ;; CHECK: (func $callee-take-arg-0 (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $callee-take-arg-0 (param i32) (result i32) (i32.const 0)) - ;; CHECK: (func $callee-take-arg-1 (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $callee-take-arg-1 (param i32) (result i32) (i32.const 1)) - ;; CHECK: (func $callee-take-arg-2 (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - (func $callee-take-arg-2 (param i32) (result i32) (i32.const 2)) - - ;; CHECK: (func $yes-call-callee-0 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-call-callee-0 - ;; CHECK-NEXT: (ref.func $callee-0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-call-callee-0 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-0) - ) - ;; CHECK: (func $yes-call-callee-1 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-call-callee-0 - ;; CHECK-NEXT: (ref.func $callee-1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-call-callee-1 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-1) - ) - ;; CHECK: (func $yes-call-callee-2 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-call-callee-0 - ;; CHECK-NEXT: (ref.func $callee-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-call-callee-2 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-2) - ) - - - ;; CHECK: (func $yes-call-callee-take-arg-0 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-call-callee-take-arg-0 - ;; CHECK-NEXT: (ref.func $callee-take-arg-0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-call-callee-take-arg-0 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-take-arg-0 (i32.const 0)) - ) - ;; CHECK: (func $yes-call-callee-take-arg-1 (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-call-callee-take-arg-0 - ;; CHECK-NEXT: (ref.func $callee-take-arg-1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-call-callee-take-arg-1 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-take-arg-1 (i32.const 1)) - ) - - - ;; NOTE: calls with different argument expressions are not mergeable - - ;; CHECK: (func $no-call-callee-take-arg-0 (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $callee-take-arg-0 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-call-callee-take-arg-0 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-take-arg-0 - (block (result i32) - (drop (i32.const 0)) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $no-call-callee-take-arg-1 (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $callee-take-arg-1 - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $no-call-callee-take-arg-1 (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (call $callee-take-arg-1 - (block (result i32) - (drop (i32.const 0)) - (drop (i32.const 0)) - (i32.const 0) - ) - ) - ) - -) - -;; CHECK: (func $byn$mgfn-shared$yes-call-callee-0 (param $0 (ref $none_=>_i32)) (result i32) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (call_ref -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $byn$mgfn-shared$yes-call-callee-take-arg-0 (param $0 (ref $i32_=>_i32)) (param $1 i32) (result i32) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (call_ref -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (func $use-42-twice (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$use-42-twice - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $use-42-twice (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.add - (i32.const 42) - (i32.const 42) - ) - ) - ;; CHECK: (func $use-43-twice (result i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$use-42-twice - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $use-43-twice (result i32) - (nop) (nop) (nop) (nop) (nop) (nop) - (nop) (nop) (nop) (nop) (nop) (nop) - (i32.add - (i32.const 43) - (i32.const 43) - ) - ) - -) - -;; CHECK: (func $byn$mgfn-shared$use-42-twice (param $0 i32) (result i32) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (nop) -;; CHECK-NEXT: (i32.add -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - - ;; CHECK: (func $yes-offset-local-indices-1 (param $a i32) (param $b i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-offset-local-indices-1 - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-offset-local-indices-1 (param $a i32) (param $b i32) - (local $x i32) - (local $y i32) - (drop (local.get $a)) - (drop (local.get $b)) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.tee $x (local.get $x))) - (drop (local.tee $y (local.get $y))) - (drop (local.tee $a (local.get $a))) - (drop (local.tee $b (local.get $b))) - (drop (i32.const 1)) - ) - ;; CHECK: (func $yes-offset-local-indices-2 (param $a i32) (param $b i32) - ;; CHECK-NEXT: (call $byn$mgfn-shared$yes-offset-local-indices-1 - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $yes-offset-local-indices-2 (param $a i32) (param $b i32) - (local $x i32) - (local $y i32) - (drop (local.get $a)) - (drop (local.get $b)) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.tee $x (local.get $x))) - (drop (local.tee $y (local.get $y))) - (drop (local.tee $a (local.get $a))) - (drop (local.tee $b (local.get $b))) - (drop (i32.const 2)) - ) - -) -;; CHECK: (func $byn$mgfn-shared$yes-offset-local-indices-1 (param $0 i32) (param $1 i32) (param $2 i32) -;; CHECK-NEXT: (local $3 i32) -;; CHECK-NEXT: (local $4 i32) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.get $3) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.get $4) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.tee $3 -;; CHECK-NEXT: (local.get $3) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.tee $4 -;; CHECK-NEXT: (local.get $4) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.tee $0 -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.tee $1 -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (local.get $2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/name-types.wast binaryen-99/test/lit/passes/name-types.wast --- binaryen-108/test/lit/passes/name-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/name-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: wasm-opt %s -all --name-types -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --name-types --nominal -S -o - | filecheck %s --check-prefix=NOMNL - -(module - ;; An obnoxious name that will be renamed. - (type $obnoxious-super-long-type-name_____________________________1 (struct)) - - ;; A reasonable name that will be kept. - ;; CHECK: (type $type$0 (func (param (ref $type$1) (ref $reasonable-name)))) - - ;; CHECK: (type $type$1 (struct )) - - ;; CHECK: (type $reasonable-name (struct (field i32))) - ;; NOMNL: (type $type$0 (func_subtype (param (ref $type$1) (ref $reasonable-name)) func)) - - ;; NOMNL: (type $type$1 (struct_subtype data)) - - ;; NOMNL: (type $reasonable-name (struct_subtype (field i32) data)) - (type $reasonable-name (struct (field i32))) - - ;; CHECK: (func $foo (param $x (ref $type$1)) (param $y (ref $reasonable-name)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $type$0) (param $x (ref $type$1)) (param $y (ref $reasonable-name)) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $foo - ;; Use the types to keep them alive. - (param $x (ref $obnoxious-super-long-type-name_____________________________1)) - (param $y (ref $reasonable-name)) - ) -) diff -Nru binaryen-108/test/lit/passes/O1.wast binaryen-99/test/lit/passes/O1.wast --- binaryen-108/test/lit/passes/O1.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/O1.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -O1 -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - (global $global$0 (mut i32) (i32.const 10)) - (func "foo" (result i32) - (i32.load offset=4 align=1 - (i32.and - (block $label$1 (result i32) - (global.set $global$0 - (i32.const 0) - ) - (i32.const -64) - ) - (i32.const 15) - ) - ) - ) - (func $signed-overflow (param $0 f32) (result i32) - (i32.sub - (i32.const 268435456) - (i32.const -2147483648) - ) - ) -) - - -;; CHECK: (export "foo" (func $0)) - -;; CHECK: (func $0 (result i32) -;; CHECK-NEXT: (drop -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.load align=1 -;; CHECK-NEXT: (i32.const 4) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast binaryen-99/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast --- binaryen-108/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,186 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -O3 --inline-functions-with-loops --flexible-inline-max-function-size=30 -S -o - | filecheck %s - -(module - ;; CHECK: (type $t0 (func (param i32) (result i32))) - (type $t0 (func (param i32) (result i32))) - ;; CHECK: (memory $memory 0) - - ;; CHECK: (export "fib" (func $fib)) - - ;; CHECK: (export "looped" (func $looped)) - - ;; CHECK: (export "t0" (func $looped)) - - ;; CHECK: (export "t1" (func $t1)) - - ;; CHECK: (export "t2" (func $t2)) - - ;; CHECK: (export "t3" (func $t3)) - - ;; CHECK: (export "memory" (memory $memory)) - - ;; CHECK: (func $fib (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (call $fib - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $fib - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fib (export "fib") (type $t0) (param $p0 i32) (result i32) - (if $I0 - (i32.le_s - (local.get $p0) - (i32.const 2) - ) - (then - (return - (local.get $p0) - ) - ) - ) - (i32.add - (call $fib - (i32.sub - (local.get $p0) - (i32.const 1) - ) - ) - (call $fib - (i32.sub - (local.get $p0) - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $looped (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (loop $L0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $L0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $looped (export "looped") (type $t0) (param $p0 i32) (result i32) - (loop $L0 - (if $I1 - (i32.ge_s - (local.get $p0) - (i32.const 0) - ) - (then - (local.set $p0 - (i32.sub - (local.get $p0) - (i32.const 1) - ) - ) - (br $L0) - ) - ) - ) - (local.get $p0) - ) - - (func $t0 (export "t0") (type $t0) (param $p0 i32) (result i32) - (call $looped - (local.get $p0) - ) - ) - - ;; CHECK: (func $t1 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $L0 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $L0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $t1 (export "t1") (type $t0) (param $p0 i32) (result i32) - (call $looped - (i32.add - (local.get $p0) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $t2 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (call $fib - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $t2 (export "t2") (type $t0) (param $p0 i32) (result i32) - (call $fib - (local.get $p0) - ) - ) - - ;; CHECK: (func $t3 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (call $fib - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $t3 (export "t3") (type $t0) (param $p0 i32) (result i32) - (call $fib - (i32.add - (local.get $p0) - (i32.const 1) - ) - ) - ) - (memory $memory (export "memory") 0) -) diff -Nru binaryen-108/test/lit/passes/O3_inlining.wast binaryen-99/test/lit/passes/O3_inlining.wast --- binaryen-108/test/lit/passes/O3_inlining.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/O3_inlining.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -O3 --inlining -S -o - | filecheck %s - -(module - (global $global$0 (mut f64) (f64.const -32768)) - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (global $global$1 (mut i32) (i32.const 100)) - (global $global$1 (mut i32) (i32.const 100)) - ;; CHECK: (memory $0 1 1) - (memory $0 1 1) - ;; CHECK: (export "func_217" (func $1)) - (export "func_217" (func $1)) - (func $0 - (if - (global.get $global$1) - (unreachable) - ) - (global.set $global$1 - (i32.const 0) - ) - (block $label$2 - (global.set $global$0 - (block $label$3 (result f64) - (br_if $label$2 - (if (result i32) - (i32.load16_u offset=3 - (i32.const 0) - ) - (i32.const 1) - (i32.const 0) - ) - ) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $1 (param $0 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global$1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global$1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $1 (param $var$0 i32) - (drop - (call $2 - (f32.const 1) - (i32.const 1) - (i32.const 0) - ) - ) - ) - (func $2 (param $var$0 f32) (param $var$1 i32) (param $var$2 i32) (result i32) - (call $0) - (i32.const 0) - ) -) diff -Nru binaryen-108/test/lit/passes/O4_disable-bulk-memory.wast binaryen-99/test/lit/passes/O4_disable-bulk-memory.wast --- binaryen-108/test/lit/passes/O4_disable-bulk-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/O4_disable-bulk-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,3025 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -O4 --disable-bulk-memory -S -o - | filecheck %s - -(module - ;; CHECK: (type $0 (func)) - (type $0 (func)) - (global $global$0 (mut i32) (i32.const 10)) - ;; CHECK: (export "func_59_invoker" (func $0)) - (export "func_59_invoker" (func $0)) - ;; CHECK: (func $0 (; has Stack IR ;) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $0 (; 0 ;) (type $0) - (if - (block $label$1 (result i32) - (global.set $global$0 - (i32.const 0) - ) - (i32.const 127) - ) - (unreachable) - ) - (global.set $global$0 - (i32.const -1) - ) - (if - (global.get $global$0) - (unreachable) - ) - (unreachable) - ) -) -;; AssemblyScript n-body benchmark -(module - ;; CHECK: (type $0 (func)) - (type $0 (func)) - (type $1 (func (param i32 i32) (result i32))) - (type $2 (func (param i32 f64 f64 f64) (result i32))) - ;; CHECK: (type $3 (func (param i32) (result i32))) - (type $3 (func (param i32) (result i32))) - (type $4 (func (result i32))) - (type $5 (func (param i32 f64 f64 f64 f64 f64 f64 f64) (result i32))) - (type $6 (func (param i32 i32 i32 i32))) - (type $7 (func (param i32 i32 i32))) - ;; CHECK: (type $11 (func (param i32))) - - ;; CHECK: (type $f64_f64_f64_f64_f64_f64_f64_=>_i32 (func (param f64 f64 f64 f64 f64 f64 f64) (result i32))) - - ;; CHECK: (type $8 (func (result f64))) - (type $8 (func (result f64))) - (type $9 (func (param i32 f64))) - (type $10 (func (param i32) (result f64))) - (type $11 (func (param i32))) - ;; CHECK: (import "env" "memory" (memory $1 1)) - (import "env" "memory" (memory $1 1)) - (data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00") - (data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00") - (import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32))) - ;; CHECK: (data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00") - - ;; CHECK: (data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00") - - ;; CHECK: (global $global$0 (mut i32) (i32.const 0)) - - ;; CHECK: (global $global$1 (mut i32) (i32.const 0)) - - ;; CHECK: (global $global$5 (mut i32) (i32.const 0)) - - ;; CHECK: (table $0 1 funcref) - (table $0 1 funcref) - (elem (i32.const 0) $null) - (global $global$0 (mut i32) (i32.const 0)) - (global $global$1 (mut i32) (i32.const 0)) - (global $global$2 f64 (f64.const 3.141592653589793)) - (global $global$3 f64 (f64.const 39.47841760435743)) - (global $global$4 f64 (f64.const 365.24)) - (global $global$5 (mut i32) (i32.const 0)) - (global $global$6 i32 (i32.const 100)) - ;; CHECK: (elem (i32.const 0) $null) - - ;; CHECK: (export "memory" (memory $0)) - (export "memory" (memory $0)) - ;; CHECK: (export "table" (table $0)) - (export "table" (table $0)) - ;; CHECK: (export "init" (func $assembly/index/init)) - (export "init" (func $assembly/index/init)) - ;; CHECK: (export "step" (func $assembly/index/step)) - (export "step" (func $assembly/index/step)) - ;; CHECK: (export "bench" (func $assembly/index/bench)) - (export "bench" (func $assembly/index/bench)) - ;; CHECK: (export "getBody" (func $assembly/index/getBody)) - (export "getBody" (func $assembly/index/getBody)) - ;; CHECK: (start $start) - (start $start) - (func $start:~lib/allocator/arena (; 1 ;) (type $0) - (global.set $global$0 - (i32.and - (i32.add - (global.get $global$6) - (i32.const 7) - ) - (i32.xor - (i32.const 7) - (i32.const -1) - ) - ) - ) - (global.set $global$1 - (global.get $global$0) - ) - ) - (func $start:assembly/index (; 2 ;) (type $0) - (call $start:~lib/allocator/arena) - ) - (func $~lib/array/Array#__unchecked_get (; 3 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local.set $2 - (i32.load - (local.get $0) - ) - ) - (local.set $3 - (local.get $1) - ) - (local.set $4 - (i32.const 0) - ) - (i32.load offset=8 - (i32.add - (i32.add - (local.get $2) - (i32.shl - (local.get $3) - (i32.const 2) - ) - ) - (local.get $4) - ) - ) - ) - (func $~lib/array/Array#__get (; 4 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $2 - (i32.load - (local.get $0) - ) - ) - (if (result i32) - (i32.lt_u - (local.get $1) - (i32.shr_u - (i32.load - (local.get $2) - ) - (i32.const 2) - ) - ) - (block (result i32) - (local.set $3 - (local.get $2) - ) - (local.set $4 - (local.get $1) - ) - (local.set $5 - (i32.const 0) - ) - (i32.load offset=8 - (i32.add - (i32.add - (local.get $3) - (i32.shl - (local.get $4) - (i32.const 2) - ) - ) - (local.get $5) - ) - ) - ) - (unreachable) - ) - ) - (func $assembly/index/Body#offsetMomentum (; 5 ;) (type $2) (param $0 i32) (param $1 f64) (param $2 f64) (param $3 f64) (result i32) - (f64.store offset=24 - (local.get $0) - (f64.div - (f64.neg - (local.get $1) - ) - (global.get $global$3) - ) - ) - (f64.store offset=32 - (local.get $0) - (f64.div - (f64.neg - (local.get $2) - ) - (global.get $global$3) - ) - ) - (f64.store offset=40 - (local.get $0) - (f64.div - (f64.neg - (local.get $3) - ) - (global.get $global$3) - ) - ) - (local.get $0) - ) - ;; CHECK: (func $~lib/allocator/arena/__memory_allocate (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1073741824) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (global.get $global$1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (memory.size) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (memory.grow - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -65536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (memory.grow - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global$1 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $~lib/allocator/arena/__memory_allocate (; 6 ;) (type $3) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (if - (i32.gt_u - (local.get $0) - (i32.const 1073741824) - ) - (unreachable) - ) - (local.set $1 - (global.get $global$1) - ) - (local.set $4 - (i32.and - (i32.add - (i32.add - (local.get $1) - (select - (local.tee $2 - (local.get $0) - ) - (local.tee $3 - (i32.const 1) - ) - (i32.gt_u - (local.get $2) - (local.get $3) - ) - ) - ) - (i32.const 7) - ) - (i32.xor - (i32.const 7) - (i32.const -1) - ) - ) - ) - (local.set $5 - (memory.size) - ) - (if - (i32.gt_u - (local.get $4) - (i32.shl - (local.get $5) - (i32.const 16) - ) - ) - (block - (local.set $2 - (i32.shr_u - (i32.and - (i32.add - (i32.sub - (local.get $4) - (local.get $1) - ) - (i32.const 65535) - ) - (i32.xor - (i32.const 65535) - (i32.const -1) - ) - ) - (i32.const 16) - ) - ) - (local.set $3 - (select - (local.tee $3 - (local.get $5) - ) - (local.tee $6 - (local.get $2) - ) - (i32.gt_s - (local.get $3) - (local.get $6) - ) - ) - ) - (if - (i32.lt_s - (memory.grow - (local.get $3) - ) - (i32.const 0) - ) - (if - (i32.lt_s - (memory.grow - (local.get $2) - ) - (i32.const 0) - ) - (unreachable) - ) - ) - ) - ) - (global.set $global$1 - (local.get $4) - ) - (local.get $1) - ) - (func $~lib/memory/memory.allocate (; 7 ;) (type $3) (param $0 i32) (result i32) - (return - (call $~lib/allocator/arena/__memory_allocate - (local.get $0) - ) - ) - ) - (func $assembly/index/NBodySystem#constructor (; 8 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 f64) - (local $6 f64) - (local $7 f64) - (local $8 f64) - (local.set $5 - (f64.const 0) - ) - (local.set $6 - (f64.const 0) - ) - (local.set $7 - (f64.const 0) - ) - (local.set $3 - (block $label$1 (result i32) - (local.set $2 - (local.get $1) - ) - (i32.load offset=4 - (local.get $2) - ) - ) - ) - (block $label$2 - (local.set $2 - (i32.const 0) - ) - (loop $label$3 - (br_if $label$2 - (i32.eqz - (i32.lt_s - (local.get $2) - (local.get $3) - ) - ) - ) - (block $label$4 - (local.set $4 - (call $~lib/array/Array#__unchecked_get - (local.get $1) - (local.get $2) - ) - ) - (local.set $8 - (f64.load offset=48 - (local.get $4) - ) - ) - (local.set $5 - (f64.add - (local.get $5) - (f64.mul - (f64.load offset=24 - (local.get $4) - ) - (local.get $8) - ) - ) - ) - (local.set $6 - (f64.add - (local.get $6) - (f64.mul - (f64.load offset=32 - (local.get $4) - ) - (local.get $8) - ) - ) - ) - (local.set $7 - (f64.add - (local.get $7) - (f64.mul - (f64.load offset=40 - (local.get $4) - ) - (local.get $8) - ) - ) - ) - ) - (local.set $2 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (br $label$3) - ) - ) - (drop - (call $assembly/index/Body#offsetMomentum - (call $~lib/array/Array#__get - (local.get $1) - (i32.const 0) - ) - (local.get $5) - (local.get $6) - (local.get $7) - ) - ) - (if - (i32.eqz - (local.get $0) - ) - (local.set $0 - (call $~lib/memory/memory.allocate - (i32.const 4) - ) - ) - ) - (i32.store - (local.get $0) - (local.get $1) - ) - (local.get $0) - ) - ;; CHECK: (func $assembly/index/Body#constructor (; has Stack IR ;) (param $0 f64) (param $1 f64) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 f64) (param $6 f64) (result i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (call $~lib/allocator/arena/__memory_allocate - ;; CHECK-NEXT: (i32.const 56) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=8 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=16 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=24 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=32 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=40 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=48 - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - (func $assembly/index/Body#constructor (; 9 ;) (type $5) (param $0 i32) (param $1 f64) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 f64) (param $6 f64) (param $7 f64) (result i32) - (if - (i32.eqz - (local.get $0) - ) - (local.set $0 - (call $~lib/memory/memory.allocate - (i32.const 56) - ) - ) - ) - (f64.store - (local.get $0) - (local.get $1) - ) - (f64.store offset=8 - (local.get $0) - (local.get $2) - ) - (f64.store offset=16 - (local.get $0) - (local.get $3) - ) - (f64.store offset=24 - (local.get $0) - (local.get $4) - ) - (f64.store offset=32 - (local.get $0) - (local.get $5) - ) - (f64.store offset=40 - (local.get $0) - (local.get $6) - ) - (f64.store offset=48 - (local.get $0) - (local.get $7) - ) - (local.get $0) - ) - (func $assembly/index/Sun (; 10 ;) (type $4) (result i32) - (call $assembly/index/Body#constructor - (i32.const 0) - (f64.const 0) - (f64.const 0) - (f64.const 0) - (f64.const 0) - (f64.const 0) - (f64.const 0) - (global.get $global$3) - ) - ) - (func $assembly/index/Jupiter (; 11 ;) (type $4) (result i32) - (call $assembly/index/Body#constructor - (i32.const 0) - (f64.const 4.841431442464721) - (f64.const -1.1603200440274284) - (f64.const -0.10362204447112311) - (f64.mul - (f64.const 0.001660076642744037) - (global.get $global$4) - ) - (f64.mul - (f64.const 0.007699011184197404) - (global.get $global$4) - ) - (f64.mul - (f64.const -6.90460016972063e-05) - (global.get $global$4) - ) - (f64.mul - (f64.const 9.547919384243266e-04) - (global.get $global$3) - ) - ) - ) - (func $assembly/index/Saturn (; 12 ;) (type $4) (result i32) - (call $assembly/index/Body#constructor - (i32.const 0) - (f64.const 8.34336671824458) - (f64.const 4.124798564124305) - (f64.const -0.4035234171143214) - (f64.mul - (f64.const -0.002767425107268624) - (global.get $global$4) - ) - (f64.mul - (f64.const 0.004998528012349172) - (global.get $global$4) - ) - (f64.mul - (f64.const 2.3041729757376393e-05) - (global.get $global$4) - ) - (f64.mul - (f64.const 2.858859806661308e-04) - (global.get $global$3) - ) - ) - ) - (func $assembly/index/Uranus (; 13 ;) (type $4) (result i32) - (call $assembly/index/Body#constructor - (i32.const 0) - (f64.const 12.894369562139131) - (f64.const -15.111151401698631) - (f64.const -0.22330757889265573) - (f64.mul - (f64.const 0.002964601375647616) - (global.get $global$4) - ) - (f64.mul - (f64.const 2.3784717395948095e-03) - (global.get $global$4) - ) - (f64.mul - (f64.const -2.9658956854023756e-05) - (global.get $global$4) - ) - (f64.mul - (f64.const 4.366244043351563e-05) - (global.get $global$3) - ) - ) - ) - (func $assembly/index/Neptune (; 14 ;) (type $4) (result i32) - (call $assembly/index/Body#constructor - (i32.const 0) - (f64.const 15.379697114850917) - (f64.const -25.919314609987964) - (f64.const 0.17925877295037118) - (f64.mul - (f64.const 2.6806777249038932e-03) - (global.get $global$4) - ) - (f64.mul - (f64.const 0.001628241700382423) - (global.get $global$4) - ) - (f64.mul - (f64.const -9.515922545197159e-05) - (global.get $global$4) - ) - (f64.mul - (f64.const 5.1513890204661145e-05) - (global.get $global$3) - ) - ) - ) - (func $~lib/internal/arraybuffer/computeSize (; 15 ;) (type $3) (param $0 i32) (result i32) - (i32.shl - (i32.const 1) - (i32.sub - (i32.const 32) - (i32.clz - (i32.sub - (i32.add - (local.get $0) - (i32.const 8) - ) - (i32.const 1) - ) - ) - ) - ) - ) - (func $~lib/internal/arraybuffer/allocateUnsafe (; 16 ;) (type $3) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (if - (i32.eqz - (i32.le_u - (local.get $0) - (i32.const 1073741816) - ) - ) - (block - (call $~lib/env/abort - (i32.const 0) - (i32.const 40) - (i32.const 26) - (i32.const 2) - ) - (unreachable) - ) - ) - (local.set $1 - (block $label$2 (result i32) - (local.set $2 - (call $~lib/internal/arraybuffer/computeSize - (local.get $0) - ) - ) - (br $label$2 - (call $~lib/allocator/arena/__memory_allocate - (local.get $2) - ) - ) - ) - ) - (i32.store - (local.get $1) - (local.get $0) - ) - (local.get $1) - ) - (func $~lib/internal/memory/memset (; 17 ;) (type $7) (param $0 i32) (param $1 i32) (param $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i64) - (if - (i32.eqz - (local.get $2) - ) - (return) - ) - (i32.store8 - (local.get $0) - (local.get $1) - ) - (i32.store8 - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 1) - ) - (local.get $1) - ) - (if - (i32.le_u - (local.get $2) - (i32.const 2) - ) - (return) - ) - (i32.store8 - (i32.add - (local.get $0) - (i32.const 1) - ) - (local.get $1) - ) - (i32.store8 - (i32.add - (local.get $0) - (i32.const 2) - ) - (local.get $1) - ) - (i32.store8 - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 2) - ) - (local.get $1) - ) - (i32.store8 - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 3) - ) - (local.get $1) - ) - (if - (i32.le_u - (local.get $2) - (i32.const 6) - ) - (return) - ) - (i32.store8 - (i32.add - (local.get $0) - (i32.const 3) - ) - (local.get $1) - ) - (i32.store8 - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 4) - ) - (local.get $1) - ) - (if - (i32.le_u - (local.get $2) - (i32.const 8) - ) - (return) - ) - (local.set $3 - (i32.and - (i32.sub - (i32.const 0) - (local.get $0) - ) - (i32.const 3) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (local.get $3) - ) - ) - (local.set $2 - (i32.sub - (local.get $2) - (local.get $3) - ) - ) - (local.set $2 - (i32.and - (local.get $2) - (i32.const -4) - ) - ) - (local.set $4 - (i32.mul - (i32.div_u - (i32.const -1) - (i32.const 255) - ) - (i32.and - (local.get $1) - (i32.const 255) - ) - ) - ) - (i32.store - (local.get $0) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 4) - ) - (local.get $4) - ) - (if - (i32.le_u - (local.get $2) - (i32.const 8) - ) - (return) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 4) - ) - (local.get $4) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 8) - ) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 12) - ) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 8) - ) - (local.get $4) - ) - (if - (i32.le_u - (local.get $2) - (i32.const 24) - ) - (return) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 12) - ) - (local.get $4) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 16) - ) - (local.get $4) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 20) - ) - (local.get $4) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 24) - ) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 28) - ) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 24) - ) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 20) - ) - (local.get $4) - ) - (i32.store - (i32.sub - (i32.add - (local.get $0) - (local.get $2) - ) - (i32.const 16) - ) - (local.get $4) - ) - (local.set $3 - (i32.add - (i32.const 24) - (i32.and - (local.get $0) - (i32.const 4) - ) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (local.get $3) - ) - ) - (local.set $2 - (i32.sub - (local.get $2) - (local.get $3) - ) - ) - (local.set $5 - (i64.or - (i64.extend_i32_u - (local.get $4) - ) - (i64.shl - (i64.extend_i32_u - (local.get $4) - ) - (i64.const 32) - ) - ) - ) - (block $label$7 - (loop $label$8 - (if - (i32.ge_u - (local.get $2) - (i32.const 32) - ) - (block - (block $label$10 - (i64.store - (local.get $0) - (local.get $5) - ) - (i64.store - (i32.add - (local.get $0) - (i32.const 8) - ) - (local.get $5) - ) - (i64.store - (i32.add - (local.get $0) - (i32.const 16) - ) - (local.get $5) - ) - (i64.store - (i32.add - (local.get $0) - (i32.const 24) - ) - (local.get $5) - ) - (local.set $2 - (i32.sub - (local.get $2) - (i32.const 32) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - ) - (br $label$8) - ) - ) - ) - ) - ) - (func $~lib/array/Array#constructor (; 18 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (if - (i32.gt_u - (local.get $1) - (i32.const 268435454) - ) - (block - (call $~lib/env/abort - (i32.const 0) - (i32.const 8) - (i32.const 45) - (i32.const 39) - ) - (unreachable) - ) - ) - (local.set $2 - (i32.shl - (local.get $1) - (i32.const 2) - ) - ) - (local.set $3 - (call $~lib/internal/arraybuffer/allocateUnsafe - (local.get $2) - ) - ) - (i32.store - (block $label$2 (result i32) - (if - (i32.eqz - (local.get $0) - ) - (local.set $0 - (call $~lib/memory/memory.allocate - (i32.const 8) - ) - ) - ) - (i32.store - (local.get $0) - (i32.const 0) - ) - (i32.store offset=4 - (local.get $0) - (i32.const 0) - ) - (local.get $0) - ) - (local.get $3) - ) - (i32.store offset=4 - (local.get $0) - (local.get $1) - ) - (block $label$4 - (local.set $4 - (i32.add - (local.get $3) - (i32.const 8) - ) - ) - (local.set $5 - (i32.const 0) - ) - (local.set $6 - (local.get $2) - ) - (call $~lib/internal/memory/memset - (local.get $4) - (local.get $5) - (local.get $6) - ) - ) - (local.get $0) - ) - (func $~lib/array/Array#__unchecked_set (; 19 ;) (type $7) (param $0 i32) (param $1 i32) (param $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local.set $3 - (i32.load - (local.get $0) - ) - ) - (local.set $4 - (local.get $1) - ) - (local.set $5 - (local.get $2) - ) - (local.set $6 - (i32.const 0) - ) - (i32.store offset=8 - (i32.add - (i32.add - (local.get $3) - (i32.shl - (local.get $4) - (i32.const 2) - ) - ) - (local.get $6) - ) - (local.get $5) - ) - ) - ;; CHECK: (func $assembly/index/init (; has Stack IR ;) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 f64) - ;; CHECK-NEXT: (local $5 f64) - ;; CHECK-NEXT: (local $6 f64) - ;; CHECK-NEXT: (local $7 f64) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (call $~lib/allocator/arena/__memory_allocate - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (call $~lib/allocator/arena/__memory_allocate - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $__inlined_func$~lib/internal/memory/memset - ;; CHECK-NEXT: (br_if $__inlined_func$~lib/internal/memory/memset - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $__inlined_func$~lib/internal/memory/memset - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 28) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$8 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $assembly/index/Body#constructor - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 39.47841760435743) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $assembly/index/Body#constructor - ;; CHECK-NEXT: (f64.const 4.841431442464721) - ;; CHECK-NEXT: (f64.const -1.1603200440274284) - ;; CHECK-NEXT: (f64.const -0.10362204447112311) - ;; CHECK-NEXT: (f64.const 0.606326392995832) - ;; CHECK-NEXT: (f64.const 2.81198684491626) - ;; CHECK-NEXT: (f64.const -0.02521836165988763) - ;; CHECK-NEXT: (f64.const 0.03769367487038949) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $assembly/index/Body#constructor - ;; CHECK-NEXT: (f64.const 8.34336671824458) - ;; CHECK-NEXT: (f64.const 4.124798564124305) - ;; CHECK-NEXT: (f64.const -0.4035234171143214) - ;; CHECK-NEXT: (f64.const -1.0107743461787924) - ;; CHECK-NEXT: (f64.const 1.8256623712304119) - ;; CHECK-NEXT: (f64.const 0.008415761376584154) - ;; CHECK-NEXT: (f64.const 0.011286326131968767) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $assembly/index/Body#constructor - ;; CHECK-NEXT: (f64.const 12.894369562139131) - ;; CHECK-NEXT: (f64.const -15.111151401698631) - ;; CHECK-NEXT: (f64.const -0.22330757889265573) - ;; CHECK-NEXT: (f64.const 1.0827910064415354) - ;; CHECK-NEXT: (f64.const 0.8687130181696082) - ;; CHECK-NEXT: (f64.const -0.010832637401363636) - ;; CHECK-NEXT: (f64.const 1.7237240570597112e-03) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $assembly/index/Body#constructor - ;; CHECK-NEXT: (f64.const 15.379697114850917) - ;; CHECK-NEXT: (f64.const -25.919314609987964) - ;; CHECK-NEXT: (f64.const 0.17925877295037118) - ;; CHECK-NEXT: (f64.const 0.979090732243898) - ;; CHECK-NEXT: (f64.const 0.5946989986476762) - ;; CHECK-NEXT: (f64.const -0.034755955504078104) - ;; CHECK-NEXT: (f64.const 2.0336868699246304e-03) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.load offset=48 - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.load offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.load offset=32 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.load offset=40 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=24 - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (f64.const -39.47841760435743) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=32 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (f64.const -39.47841760435743) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=40 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (f64.const -39.47841760435743) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (call $~lib/allocator/arena/__memory_allocate - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global$5 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $assembly/index/init (; 20 ;) (type $0) - (local $0 i32) - (global.set $global$5 - (call $assembly/index/NBodySystem#constructor - (i32.const 0) - (block $label$1 (result i32) - (local.set $0 - (call $~lib/array/Array#constructor - (i32.const 0) - (i32.const 5) - ) - ) - (call $~lib/array/Array#__unchecked_set - (local.get $0) - (i32.const 0) - (call $assembly/index/Sun) - ) - (call $~lib/array/Array#__unchecked_set - (local.get $0) - (i32.const 1) - (call $assembly/index/Jupiter) - ) - (call $~lib/array/Array#__unchecked_set - (local.get $0) - (i32.const 2) - (call $assembly/index/Saturn) - ) - (call $~lib/array/Array#__unchecked_set - (local.get $0) - (i32.const 3) - (call $assembly/index/Uranus) - ) - (call $~lib/array/Array#__unchecked_set - (local.get $0) - (i32.const 4) - (call $assembly/index/Neptune) - ) - (local.get $0) - ) - ) - ) - ) - ;; CHECK: (func $assembly/index/NBodySystem#advance (; has Stack IR ;) (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 f64) - ;; CHECK-NEXT: (local $5 f64) - ;; CHECK-NEXT: (local $6 f64) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local $8 f64) - ;; CHECK-NEXT: (local $9 f64) - ;; CHECK-NEXT: (local $10 f64) - ;; CHECK-NEXT: (local $11 f64) - ;; CHECK-NEXT: (local $12 i32) - ;; CHECK-NEXT: (local $13 i32) - ;; CHECK-NEXT: (local $14 f64) - ;; CHECK-NEXT: (local $15 f64) - ;; CHECK-NEXT: (local $16 f64) - ;; CHECK-NEXT: (local $17 f64) - ;; CHECK-NEXT: (local.set $13 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $12 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$3 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $14 - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $15 - ;; CHECK-NEXT: (f64.load offset=8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (f64.load offset=16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.load offset=24 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.load offset=32 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (f64.load offset=40 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 - ;; CHECK-NEXT: (f64.load offset=48 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$6 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $17) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (f64.const 0.01) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (f64.load offset=8 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $11 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (f64.load offset=16 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.sqrt - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $4 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.load offset=48 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=32 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load offset=32 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=40 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load offset=40 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $11) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=24 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=32 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=40 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (f64.const 0.01) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load offset=8 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (f64.const 0.01) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store offset=16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load offset=16 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (f64.const 0.01) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $assembly/index/NBodySystem#advance (; 21 ;) (type $9) (param $0 i32) (param $1 f64) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 f64) - (local $9 f64) - (local $10 f64) - (local $11 f64) - (local $12 f64) - (local $13 f64) - (local $14 f64) - (local $15 f64) - (local $16 f64) - (local $17 f64) - (local $18 f64) - (local $19 f64) - (local $20 f64) - (local $21 f64) - (local $22 f64) - (local.set $2 - (i32.load - (local.get $0) - ) - ) - (local.set $4 - (block $label$1 (result i32) - (local.set $3 - (local.get $2) - ) - (i32.load offset=4 - (local.get $3) - ) - ) - ) - (block $label$2 - (local.set $3 - (i32.const 0) - ) - (loop $label$3 - (br_if $label$2 - (i32.eqz - (i32.lt_u - (local.get $3) - (local.get $4) - ) - ) - ) - (block $label$4 - (local.set $5 - (call $~lib/array/Array#__unchecked_get - (local.get $2) - (local.get $3) - ) - ) - (local.set $8 - (f64.load - (local.get $5) - ) - ) - (local.set $9 - (f64.load offset=8 - (local.get $5) - ) - ) - (local.set $10 - (f64.load offset=16 - (local.get $5) - ) - ) - (local.set $11 - (f64.load offset=24 - (local.get $5) - ) - ) - (local.set $12 - (f64.load offset=32 - (local.get $5) - ) - ) - (local.set $13 - (f64.load offset=40 - (local.get $5) - ) - ) - (local.set $14 - (f64.load offset=48 - (local.get $5) - ) - ) - (block $label$5 - (local.set $6 - (i32.add - (local.get $3) - (i32.const 1) - ) - ) - (loop $label$6 - (br_if $label$5 - (i32.eqz - (i32.lt_u - (local.get $6) - (local.get $4) - ) - ) - ) - (block $label$7 - (local.set $7 - (call $~lib/array/Array#__unchecked_get - (local.get $2) - (local.get $6) - ) - ) - (local.set $15 - (f64.sub - (local.get $8) - (f64.load - (local.get $7) - ) - ) - ) - (local.set $16 - (f64.sub - (local.get $9) - (f64.load offset=8 - (local.get $7) - ) - ) - ) - (local.set $17 - (f64.sub - (local.get $10) - (f64.load offset=16 - (local.get $7) - ) - ) - ) - (local.set $18 - (f64.add - (f64.add - (f64.mul - (local.get $15) - (local.get $15) - ) - (f64.mul - (local.get $16) - (local.get $16) - ) - ) - (f64.mul - (local.get $17) - (local.get $17) - ) - ) - ) - (local.set $19 - (block $label$8 (result f64) - (local.set $19 - (local.get $18) - ) - (f64.sqrt - (local.get $19) - ) - ) - ) - (local.set $20 - (f64.div - (local.get $1) - (f64.mul - (local.get $18) - (local.get $19) - ) - ) - ) - (local.set $21 - (f64.mul - (local.get $14) - (local.get $20) - ) - ) - (local.set $22 - (f64.mul - (f64.load offset=48 - (local.get $7) - ) - (local.get $20) - ) - ) - (local.set $11 - (f64.sub - (local.get $11) - (f64.mul - (local.get $15) - (local.get $22) - ) - ) - ) - (local.set $12 - (f64.sub - (local.get $12) - (f64.mul - (local.get $16) - (local.get $22) - ) - ) - ) - (local.set $13 - (f64.sub - (local.get $13) - (f64.mul - (local.get $17) - (local.get $22) - ) - ) - ) - (f64.store offset=24 - (local.get $7) - (f64.add - (f64.load offset=24 - (local.get $7) - ) - (f64.mul - (local.get $15) - (local.get $21) - ) - ) - ) - (f64.store offset=32 - (local.get $7) - (f64.add - (f64.load offset=32 - (local.get $7) - ) - (f64.mul - (local.get $16) - (local.get $21) - ) - ) - ) - (f64.store offset=40 - (local.get $7) - (f64.add - (f64.load offset=40 - (local.get $7) - ) - (f64.mul - (local.get $17) - (local.get $21) - ) - ) - ) - ) - (local.set $6 - (i32.add - (local.get $6) - (i32.const 1) - ) - ) - (br $label$6) - ) - ) - (f64.store offset=24 - (local.get $5) - (local.get $11) - ) - (f64.store offset=32 - (local.get $5) - (local.get $12) - ) - (f64.store offset=40 - (local.get $5) - (local.get $13) - ) - (f64.store - (local.get $5) - (f64.add - (f64.load - (local.get $5) - ) - (f64.mul - (local.get $1) - (local.get $11) - ) - ) - ) - (f64.store offset=8 - (local.get $5) - (f64.add - (f64.load offset=8 - (local.get $5) - ) - (f64.mul - (local.get $1) - (local.get $12) - ) - ) - ) - (f64.store offset=16 - (local.get $5) - (f64.add - (f64.load offset=16 - (local.get $5) - ) - (f64.mul - (local.get $1) - (local.get $13) - ) - ) - ) - ) - (local.set $3 - (i32.add - (local.get $3) - (i32.const 1) - ) - ) - (br $label$3) - ) - ) - ) - (func $assembly/index/NBodySystem#energy (; 22 ;) (type $10) (param $0 i32) (result f64) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 f64) - (local $8 f64) - (local $9 f64) - (local $10 f64) - (local $11 f64) - (local $12 f64) - (local $13 f64) - (local $14 f64) - (local $15 f64) - (local $16 f64) - (local $17 f64) - (local $18 f64) - (local.set $7 - (f64.const 0) - ) - (local.set $1 - (i32.load - (local.get $0) - ) - ) - (block $label$1 - (block $label$2 - (local.set $2 - (i32.const 0) - ) - (local.set $3 - (block $label$3 (result i32) - (local.set $3 - (local.get $1) - ) - (i32.load offset=4 - (local.get $3) - ) - ) - ) - ) - (loop $label$4 - (br_if $label$1 - (i32.eqz - (i32.lt_u - (local.get $2) - (local.get $3) - ) - ) - ) - (block $label$5 - (local.set $4 - (call $~lib/array/Array#__unchecked_get - (local.get $1) - (local.get $2) - ) - ) - (local.set $8 - (f64.load - (local.get $4) - ) - ) - (local.set $9 - (f64.load offset=8 - (local.get $4) - ) - ) - (local.set $10 - (f64.load offset=16 - (local.get $4) - ) - ) - (local.set $11 - (f64.load offset=24 - (local.get $4) - ) - ) - (local.set $12 - (f64.load offset=32 - (local.get $4) - ) - ) - (local.set $13 - (f64.load offset=40 - (local.get $4) - ) - ) - (local.set $14 - (f64.load offset=48 - (local.get $4) - ) - ) - (local.set $7 - (f64.add - (local.get $7) - (f64.mul - (f64.mul - (f64.const 0.5) - (local.get $14) - ) - (f64.add - (f64.add - (f64.mul - (local.get $11) - (local.get $11) - ) - (f64.mul - (local.get $12) - (local.get $12) - ) - ) - (f64.mul - (local.get $13) - (local.get $13) - ) - ) - ) - ) - ) - (block $label$6 - (local.set $5 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (loop $label$7 - (br_if $label$6 - (i32.eqz - (i32.lt_u - (local.get $5) - (local.get $3) - ) - ) - ) - (block $label$8 - (local.set $6 - (call $~lib/array/Array#__unchecked_get - (local.get $1) - (local.get $5) - ) - ) - (local.set $15 - (f64.sub - (local.get $8) - (f64.load - (local.get $6) - ) - ) - ) - (local.set $16 - (f64.sub - (local.get $9) - (f64.load offset=8 - (local.get $6) - ) - ) - ) - (local.set $17 - (f64.sub - (local.get $10) - (f64.load offset=16 - (local.get $6) - ) - ) - ) - (local.set $18 - (block $label$9 (result f64) - (local.set $18 - (f64.add - (f64.add - (f64.mul - (local.get $15) - (local.get $15) - ) - (f64.mul - (local.get $16) - (local.get $16) - ) - ) - (f64.mul - (local.get $17) - (local.get $17) - ) - ) - ) - (f64.sqrt - (local.get $18) - ) - ) - ) - (local.set $7 - (f64.sub - (local.get $7) - (f64.div - (f64.mul - (local.get $14) - (f64.load offset=48 - (local.get $6) - ) - ) - (local.get $18) - ) - ) - ) - ) - (local.set $5 - (i32.add - (local.get $5) - (i32.const 1) - ) - ) - (br $label$7) - ) - ) - ) - (local.set $2 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (br $label$4) - ) - ) - (local.get $7) - ) - ;; CHECK: (func $assembly/index/step (; has Stack IR ;) (result f64) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 f64) - ;; CHECK-NEXT: (local $7 f64) - ;; CHECK-NEXT: (local $8 f64) - ;; CHECK-NEXT: (local $9 f64) - ;; CHECK-NEXT: (local $10 f64) - ;; CHECK-NEXT: (call $assembly/index/NBodySystem#advance - ;; CHECK-NEXT: (global.get $global$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $4 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $global$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$4 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (f64.load offset=8 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (f64.load offset=16 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $10 - ;; CHECK-NEXT: (f64.load offset=48 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 0.5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (f64.load offset=24 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (f64.load offset=32 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (f64.load offset=40 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $label$7 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (f64.load offset=48 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.sqrt - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (f64.load offset=8 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (f64.load offset=16 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $assembly/index/step (; 23 ;) (type $8) (result f64) - (call $assembly/index/NBodySystem#advance - (global.get $global$5) - (f64.const 0.01) - ) - (call $assembly/index/NBodySystem#energy - (global.get $global$5) - ) - ) - ;; CHECK: (func $assembly/index/bench (; has Stack IR ;) (param $0 i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (loop $label$2 - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $assembly/index/NBodySystem#advance - ;; CHECK-NEXT: (global.get $global$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $assembly/index/bench (; 24 ;) (type $11) (param $0 i32) - (local $1 i32) - (block $label$1 - (local.set $1 - (i32.const 0) - ) - (loop $label$2 - (br_if $label$1 - (i32.eqz - (i32.lt_u - (local.get $1) - (local.get $0) - ) - ) - ) - (call $assembly/index/NBodySystem#advance - (global.get $global$5) - (f64.const 0.01) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (br $label$2) - ) - ) - ) - ;; CHECK: (func $assembly/index/getBody (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (global.get $global$5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $assembly/index/getBody (; 25 ;) (type $3) (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (i32.load - (global.get $global$5) - ) - ) - (if (result i32) - (i32.lt_u - (local.get $0) - (block $label$1 (result i32) - (local.set $2 - (local.get $1) - ) - (i32.load offset=4 - (local.get $2) - ) - ) - ) - (call $~lib/array/Array#__get - (local.get $1) - (local.get $0) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $start (; has Stack IR ;) - ;; CHECK-NEXT: (global.set $global$0 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global$1 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $start (; 26 ;) (type $0) - (call $start:assembly/index) - ) - ;; CHECK: (func $null (; has Stack IR ;) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $null (; 27 ;) (type $0) - ) -) diff -Nru binaryen-108/test/lit/passes/O_fast-math.wast binaryen-99/test/lit/passes/O_fast-math.wast --- binaryen-108/test/lit/passes/O_fast-math.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/O_fast-math.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -O --fast-math -S -o - | filecheck %s - -;; with fast-math we can optimize some of these patterns -(module - (func "div" (result f32) - (f32.div - (f32.const -nan:0x23017a) - (f32.const 1) - ) - ) - (func "mul1" (result f32) - (f32.mul - (f32.const -nan:0x34546d) - (f32.const 1) - ) - ) - (func "mul2" (result f32) - (f32.mul - (f32.const 1) - (f32.const -nan:0x34546d) - ) - ) - (func "add1" (result f32) - (f32.add - (f32.const -nan:0x34546d) - (f32.const -0) - ) - ) - (func "add2" (result f32) - (f32.add - (f32.const -0) - (f32.const -nan:0x34546d) - ) - ) - (func "add3" (result f32) - (f32.add - (f32.const -nan:0x34546d) - (f32.const 0) - ) - ) - (func "add4" (result f32) - (f32.add - (f32.const 0) - (f32.const -nan:0x34546d) - ) - ) - (func "sub1" (result f32) - (f32.sub - (f32.const -nan:0x34546d) - (f32.const 0) - ) - ) - (func "sub2" (result f32) - (f32.sub - (f32.const -nan:0x34546d) - (f32.const -0) - ) - ) - (func "mul_neg_one1" (param $x f32) (result f32) - (f32.mul - (local.get $x) - (f32.const -1) - ) - ) - (func "mul_neg_one2" (param $x f64) (result f64) - (f64.mul - (local.get $x) - (f64.const -1) - ) - ) - (func "abs_sub_zero1" (param $x f32) (result f32) - ;; abs(0 - x) ==> abs(x) - (f32.abs - (f32.sub - (f32.const 0) - (local.get $x) - ) - ) - ) - (func "abs_sub_zero2" (param $x f64) (result f64) - ;; abs(0 - x) ==> abs(x) - (f64.abs - (f64.sub - (f64.const 0) - (local.get $x) - ) - ) - ) -) -;; CHECK: (type $none_=>_f32 (func (result f32))) - -;; CHECK: (type $f32_=>_f32 (func (param f32) (result f32))) - -;; CHECK: (type $f64_=>_f64 (func (param f64) (result f64))) - -;; CHECK: (export "div" (func $0)) - -;; CHECK: (export "mul1" (func $1)) - -;; CHECK: (export "mul2" (func $2)) - -;; CHECK: (export "add1" (func $1)) - -;; CHECK: (export "add2" (func $2)) - -;; CHECK: (export "add3" (func $2)) - -;; CHECK: (export "add4" (func $2)) - -;; CHECK: (export "sub1" (func $1)) - -;; CHECK: (export "sub2" (func $2)) - -;; CHECK: (export "mul_neg_one1" (func $9)) - -;; CHECK: (export "mul_neg_one2" (func $10)) - -;; CHECK: (export "abs_sub_zero1" (func $11)) - -;; CHECK: (export "abs_sub_zero2" (func $12)) - -;; CHECK: (func $0 (; has Stack IR ;) (result f32) -;; CHECK-NEXT: (f32.const -nan:0x23017a) -;; CHECK-NEXT: ) - -;; CHECK: (func $1 (; has Stack IR ;) (result f32) -;; CHECK-NEXT: (f32.const -nan:0x34546d) -;; CHECK-NEXT: ) - -;; CHECK: (func $2 (; has Stack IR ;) (result f32) -;; CHECK-NEXT: (f32.const nan:0x400000) -;; CHECK-NEXT: ) - -;; CHECK: (func $9 (; has Stack IR ;) (param $0 f32) (result f32) -;; CHECK-NEXT: (f32.neg -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $10 (; has Stack IR ;) (param $0 f64) (result f64) -;; CHECK-NEXT: (f64.neg -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $11 (; has Stack IR ;) (param $0 f32) (result f32) -;; CHECK-NEXT: (f32.abs -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) - -;; CHECK: (func $12 (; has Stack IR ;) (param $0 f64) (result f64) -;; CHECK-NEXT: (f64.abs -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/once-reduction.wast binaryen-99/test/lit/passes/once-reduction.wast --- binaryen-108/test/lit/passes/once-reduction.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/once-reduction.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1429 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --once-reduction -all -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - ;; A minimal "once" function. - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller - ;; Call a once function more than once, in a way that we can optimize: the - ;; first dominates the second. The second call will become a nop. - (call $once) - (call $once) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ;; Add some more content in the function. - (drop (i32.const 100)) - ) - - ;; CHECK: (func $caller-if-1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller-if-1 - ;; Add more calls, and ones that are conditional. - (if - (i32.const 1) - (block - (call $once) - (call $once) - (call $once) - (call $once) - ) - ) - (call $once) - (call $once) - ) - - ;; CHECK: (func $caller-if-2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller-if-2 - ;; Call in both arms. As we only handle dominance, and not merges, the first - ;; call after the if is *not* optimized. - (if - (i32.const 1) - (call $once) - (block - (call $once) - (call $once) - ) - ) - (call $once) - (call $once) - ) - - ;; CHECK: (func $caller-loop-1 - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller-loop-1 - ;; Add calls in a loop. - (loop $loop - (if - (i32.const 1) - (call $once) - ) - (call $once) - (call $once) - (br_if $loop (i32.const 1)) - ) - (call $once) - (call $once) - ) - - ;; CHECK: (func $caller-loop-2 - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller-loop-2 - ;; Add a single conditional call in a loop. - (loop $loop - (if - (i32.const 1) - (call $once) - ) - (br_if $loop (i32.const 1)) - ) - (call $once) - (call $once) - ) - - ;; CHECK: (func $caller-single - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller-single - ;; A short function with a single call. - (call $once) - ) - - ;; CHECK: (func $caller-empty - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller-empty - ;; A tiny function with nothing at all, just to verify we do not crash on - ;; such things. - ) -) - -;; Corner case: Initial value is not zero. We can still optimize this here, -;; though in fact the function will never execute the payload call of foo(), -;; which in theory we could further optimize. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "foo" (func $foo)) - (import "env" "foo" (func $foo)) - - ;; CHECK: (global $once (mut i32) (i32.const 42)) - (global $once (mut i32) (i32.const 42)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - (call $foo) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: function is not quite once, there is code before the if, so no -;; optimization will happen. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "foo" (func $foo)) - (import "env" "foo" (func $foo)) - - ;; CHECK: (global $once (mut i32) (i32.const 42)) - (global $once (mut i32) (i32.const 42)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $once - (nop) - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - (call $foo) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: a nop after the if. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "foo" (func $foo)) - (import "env" "foo" (func $foo)) - - ;; CHECK: (global $once (mut i32) (i32.const 42)) - (global $once (mut i32) (i32.const 42)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (nop) - (global.set $once (i32.const 1)) - (call $foo) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: The if has an else. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "foo" (func $foo)) - (import "env" "foo" (func $foo)) - - ;; CHECK: (global $once (mut i32) (i32.const 42)) - (global $once (mut i32) (i32.const 42)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - (call $foo) - ) - (global.set $once (i32.const 1)) - (call $foo) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: different global names in the get and set -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once1 (mut i32) (i32.const 0)) - (global $once1 (mut i32) (i32.const 0)) - ;; CHECK: (global $once2 (mut i32) (i32.const 0)) - (global $once2 (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once1) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once1) - (return) - ) - (global.set $once2 (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: The global is written a zero. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 0)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: The global is written a zero elsewhere. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - (global.set $once (i32.const 0)) - ) -) - -;; Corner case: The global is written a non-zero value elsewhere. This is ok to -;; optimize, and in fact we can write a value different than 1 both there and -;; in the "once" function, and we can still optimize. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 42)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - (global.set $once (i32.const 1337)) - ) - - ;; CHECK: (func $caller-2 - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller-2 - ;; Reverse order of the above. - (global.set $once (i32.const 1337)) - (call $once) - (call $once) - ) -) - -;; It is ok to call the "once" function inside itself - as that call appears -;; behind a set of the global, the call is redundant and we optimize it away. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - (call $once) - ) -) - -;; Corner case: Non-integer global, which we ignore. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut f64) (f64.const 0)) - (global $once (mut f64) (f64.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.trunc_f64_s - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - ;; We must cast this to an integer for the wasm to validate. - (i32.trunc_f64_s - (global.get $once) - ) - (return) - ) - (global.set $once (f64.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: Non-constant initial value. This is fine, as the initial value -;; does not matter (if it is zero, then this is a "classic" "once" global; if -;; not then it will never be written to, and the "once" function will never run -;; at all, which is fine too) -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "glob" (global $import i32)) - (import "env" "glob" (global $import i32)) - - ;; CHECK: (global $once (mut i32) (global.get $import)) - (global $once (mut i32) (global.get $import)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: Non-constant later value. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.eqz (i32.eqz (i32.const 1)))) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: "Once" function has a param. -(module - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once (param $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once (param $x i32) - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $once (i32.const 1)) - (call $once (i32.const 1)) - ) -) - -;; Corner case: "Once" function has a result. -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - (func $once (result i32) - (if - (global.get $once) - (return (i32.const 2)) - ) - (global.set $once (i32.const 1)) - (i32.const 3) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (drop (call $once)) - (drop (call $once)) - ) -) - -;; Corner case: "Once" function body is not a block. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (loop $loop - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: Once body is too short. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: Additional reads of the global. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - (drop (global.get $once)) - ) -) - -;; Corner case: Additional reads of the global in the "once" func. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - (drop (global.get $once)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: Optimization opportunties in unreachable code (which we can -;; ignore, but should not error on). -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - (unreachable) - (call $once) - (call $once) - ) -) - -;; Add a very long chain of control flow. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $caller - (if - (i32.const 1) - (call $once) - ) - (if - (i32.const 1) - (call $once) - ) - (if - (i32.const 1) - (call $once) - ) - (call $once) - (if - (i32.const 1) - (call $once) - ) - (call $once) - (if - (i32.const 1) - (nop) - (nop) - ) - (call $once) - (if - (i32.const 1) - (nop) - (call $once) - ) - (call $once) - (if - (i32.const 1) - (call $once) - ) - (call $once) - (if - (i32.const 1) - (nop) - (call $once) - ) - (call $once) - (if - (i32.const 1) - (call $once) - ) - (call $once) - (if - (i32.const 1) - (call $once) - ) - (call $once) - (call $once) - ) -) - -;; A test with a try-catch. This verifies that we emit their contents properly -;; in reverse postorder and do not hit any assertions. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (tag $tag (param i32)) - (tag $tag (param i32)) - - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $try-catch - ;; CHECK-NEXT: (try $label$5 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-catch - (try $label$5 - (do - (if - (i32.const 1) - (call $once) - ) - ) - (catch $tag - (drop - (pop i32) - ) - ) - ) - ) -) - -(module - ;; Test a module with more than one global that we can optimize, and more than - ;; one that we cannot. - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once1 (mut i32) (i32.const 0)) - (global $once1 (mut i32) (i32.const 0)) - ;; CHECK: (global $many1 (mut i32) (i32.const 0)) - (global $many1 (mut i32) (i32.const 0)) - ;; CHECK: (global $once2 (mut i32) (i32.const 0)) - (global $once2 (mut i32) (i32.const 0)) - ;; CHECK: (global $many2 (mut i32) (i32.const 0)) - (global $many2 (mut i32) (i32.const 0)) - - ;; CHECK: (func $once1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once1) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (call $once2) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: ) - (func $once1 - (if - (global.get $once1) - (return) - ) - (global.set $once1 (i32.const 1)) - (call $once1) - (call $many1) - (call $once2) - (call $many2) - (call $once1) - (call $many1) - (call $once2) - (call $many2) - ) - - ;; CHECK: (func $many1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $many1) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $many1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (call $once1) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (call $once2) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $many1 - (if - (global.get $many1) - (return) - ) - (global.set $many1 (i32.const 0)) ;; prevent this global being "once" - (call $many2) - (call $once1) - (call $many1) - (call $once2) - (call $many2) - (call $once1) - (call $many1) - (call $once2) - ) - - ;; CHECK: (func $once2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once2) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (call $once1) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: ) - (func $once2 - (if - (global.get $once2) - (return) - ) - (global.set $once2 (i32.const 2)) - (call $once2) - (call $many2) - (call $once1) - (call $many1) - (call $once2) - (call $many2) - (call $once1) - (call $many1) - ) - - ;; CHECK: (func $many2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $many2) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $many1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (call $once2) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (call $once1) - ;; CHECK-NEXT: (call $many1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $many2) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $many2 - (if - (global.get $many2) - (return) - ) - (global.set $many1 (i32.const 0)) - (call $many1) - (call $once2) - (call $many2) - (call $once1) - (call $many1) - (call $once2) - (call $many2) - (call $once1) - ) -) - -;; Test for propagation of information about called functions: if A->B->C->D -;; and D calls some "once" functions, then A can infer that it's call to B does -;; so. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $A - ;; CHECK-NEXT: (call $B) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $A - ;; We can infer that calling B calls C and then D, and D calls this "once" - ;; function, so we can remove the call after it - (call $B) - (call $once) - ) - - ;; CHECK: (func $B - ;; CHECK-NEXT: (call $C) - ;; CHECK-NEXT: ) - (func $B - (call $C) - ) - - ;; CHECK: (func $C - ;; CHECK-NEXT: (call $D) - ;; CHECK-NEXT: ) - (func $C - (call $D) - ) - - ;; CHECK: (func $D - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $D - (call $once) - (call $once) - ) - - ;; CHECK: (func $bad-A - ;; CHECK-NEXT: (call $bad-B) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $bad-A - ;; Call a function that does *not* do anything useful. We should not remove - ;; the second call here. - (call $bad-B) - (call $once) - ) - - ;; CHECK: (func $bad-B - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $bad-B - ) -) - -;; Corner case: Imported mutable global. We cannot optimize it, since the -;; outside may read and write it. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "glob" (global $once (mut i32))) - (import "env" "glob" (global $once (mut i32))) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) - -;; Corner case: Exported mutable global. We cannot optimize it, since the -;; outside may read and write it. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (export "once-global" (global $once)) - (export "once-global" (global $once)) - - ;; CHECK: (func $once - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $once - (if - (global.get $once) - (return) - ) - (global.set $once (i32.const 1)) - ) - - ;; CHECK: (func $caller - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: (call $once) - ;; CHECK-NEXT: ) - (func $caller - (call $once) - (call $once) - ) -) diff -Nru binaryen-108/test/lit/passes/opt_flatten.wast binaryen-99/test/lit/passes/opt_flatten.wast --- binaryen-108/test/lit/passes/opt_flatten.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/opt_flatten.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; Optimize the code, flatten, and run a pass that will verify it is properly -;; flat. -;; RUN: wasm-opt %s -all -O1 --flatten --rereloop -S -o - | filecheck %s - -(module - ;; CHECK: (export "foo" (func $foo)) - (export "foo" (func $foo)) - ;; CHECK: (func $foo (result funcref) - ;; CHECK-NEXT: (local $0 funcref) - ;; CHECK-NEXT: (local $1 (ref null $none_=>_funcref)) - ;; CHECK-NEXT: (local $2 (ref null $none_=>_funcref)) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (result funcref) - ;; the resulting ref.as_non_nulls here must be validated as ok in flat mode. - (drop - (call $foo) - ) - (ref.func $foo) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-for-js.wast binaryen-99/test/lit/passes/optimize-for-js.wast --- binaryen-108/test/lit/passes/optimize-for-js.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-for-js.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-for-js -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (func $is-power-of-2_32 (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $is-power-of-2_32 (param $x i32) (result i32) - (i32.eq - (i32.popcnt (local.get $x)) - (i32.const 1) - ) - ) - ;; CHECK: (func $is-power-of-2_expr_32 (param $x i64) (result i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $is-power-of-2_expr_32 (param $x i64) (result i32) - (i32.eq - (i32.popcnt (i32.wrap_i64 (local.get $x))) - (i32.const 1) - ) - ) - ;; CHECK: (func $is-power-of-2_64 (param $x i64) (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $is-power-of-2_64 (param $x i64) (result i32) - (i64.eq - (i64.popcnt (local.get $x)) - (i64.const 1) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-atomics.wast binaryen-99/test/lit/passes/optimize-instructions-atomics.wast --- binaryen-108/test/lit/passes/optimize-instructions-atomics.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-atomics.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-threads -S -o - | filecheck %s - -(module - ;; CHECK: (import "env" "memory" (memory $0 (shared 256 256))) - (import "env" "memory" (memory $0 (shared 256 256))) - - ;; CHECK: (func $x - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.atomic.load8_u - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $x - (drop - (i32.shr_s - (i32.shl - (i32.atomic.load8_u ;; can't be signed - (i32.const 100) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - - ;; CHECK: (func $dont_simplify_reinterpret_atomic_load_store (param $x i32) (param $y f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (i64.atomic.load - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.atomic.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $dont_simplify_reinterpret_atomic_load_store (param $x i32) (param $y f32) - (drop (f64.reinterpret_i64 (i64.atomic.load (local.get $x)))) ;; skip - (i32.atomic.store (i32.const 8) (i32.reinterpret_f32 (local.get $y))) ;; skip - ) - - ;; CHECK: (func $combine_atomic_load_and_extends (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.atomic.load8_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.atomic.load16_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.atomic.load32_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.atomic.load8_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.atomic.load16_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (i32.atomic.load - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $combine_atomic_load_and_extends (param $x i32) - (drop (i64.extend_i32_u (i32.atomic.load8_u (local.get $x)))) - (drop (i64.extend_i32_u (i32.atomic.load16_u (local.get $x)))) - (drop (i64.extend_i32_u (i32.atomic.load (local.get $x)))) - (drop (i64.extend_i32_s (i32.atomic.load8_u (local.get $x)))) - (drop (i64.extend_i32_s (i32.atomic.load16_u (local.get $x)))) - ;; skips - (drop (i64.extend_i32_s (i32.atomic.load (local.get $x)))) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-bulk-memory.wast binaryen-99/test/lit/passes/optimize-instructions-bulk-memory.wast --- binaryen-108/test/lit/passes/optimize-instructions-bulk-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-bulk-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,592 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-bulk-memory --enable-simd -S -o - | filecheck %s -;; RUN: wasm-opt %s --optimize-instructions --enable-bulk-memory -S -o - | filecheck %s --check-prefix NOSIMD - -(module - (memory 0) - ;; CHECK: (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $sz) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.load16_u align=1 - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.load align=1 - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i64.load align=1 - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (v128.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (v128.load align=1 - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: (local.get $sz) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.copy - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOSIMD: (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $sz) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store8 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.load8_u - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store16 align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.load16_u align=1 - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (i32.const 3) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.load align=1 - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (i32.const 5) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (i32.const 6) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (i32.const 7) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.store align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i64.load align=1 - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (i32.const 16) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $src) - ;; NOSIMD-NEXT: (local.get $sz) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.copy - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: (i32.load - ;; NOSIMD-NEXT: (i32.const 3) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) - (memory.copy ;; skip - (local.get $dst) - (local.get $dst) - (local.get $sz) - ) - - (memory.copy ;; skip - (local.get $dst) - (local.get $src) - (i32.const 0) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 1) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 2) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 3) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 4) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 5) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 6) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 7) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 8) - ) - - (memory.copy - (local.get $dst) - (local.get $src) - (i32.const 16) - ) - - (memory.copy ;; skip - (local.get $dst) - (local.get $src) - (local.get $sz) - ) - - (memory.copy ;; skip - (i32.const 0) - (i32.const 0) - (i32.load - (i32.const 3) ;; side effect - ) - ) - ) - - ;; CHECK: (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $val) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 257) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (v128.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 16843009) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i64.const 72340172838076673) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (v128.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (v128.const i32x4 0x01010101 0x01010101 0x01010101 0x01010101) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (v128.store align=1 - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (v128.const i32x4 0xffffffff 0xffffffff 0xffffffff 0xffffffff) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $val) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $sz) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (local.get $val) - ;; CHECK-NEXT: (local.get $sz) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOSIMD: (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) - ;; NOSIMD-NEXT: (local $3 i32) - ;; NOSIMD-NEXT: (local $4 i32) - ;; NOSIMD-NEXT: (local $5 i32) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store8 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store8 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $val) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store8 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 1) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store8 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 255) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store16 align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store16 align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 257) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store16 align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 65535) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.store align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i64.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (block - ;; NOSIMD-NEXT: (i64.store align=1 - ;; NOSIMD-NEXT: (local.tee $3 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.store offset=8 align=1 - ;; NOSIMD-NEXT: (local.get $3) - ;; NOSIMD-NEXT: (i64.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i32.store align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 16843009) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.store align=1 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i64.const 72340172838076673) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (block - ;; NOSIMD-NEXT: (i64.store align=1 - ;; NOSIMD-NEXT: (local.tee $4 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.const 72340172838076673) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.store offset=8 align=1 - ;; NOSIMD-NEXT: (local.get $4) - ;; NOSIMD-NEXT: (i64.const 72340172838076673) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (block - ;; NOSIMD-NEXT: (i64.store align=1 - ;; NOSIMD-NEXT: (local.tee $5 - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.const -1) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (i64.store offset=8 align=1 - ;; NOSIMD-NEXT: (local.get $5) - ;; NOSIMD-NEXT: (i64.const -1) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $val) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: (local.get $sz) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (local.get $val) - ;; NOSIMD-NEXT: (local.get $sz) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: (i32.const 3) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 1) - ;; NOSIMD-NEXT: (i32.const 3) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (local.get $dst) - ;; NOSIMD-NEXT: (i32.const 0) - ;; NOSIMD-NEXT: (i32.const 17) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: (memory.fill - ;; NOSIMD-NEXT: (unreachable) - ;; NOSIMD-NEXT: (i32.const 1) - ;; NOSIMD-NEXT: (i32.const 16) - ;; NOSIMD-NEXT: ) - ;; NOSIMD-NEXT: ) - (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) - (memory.fill - (local.get $dst) - (i32.const 0) - (i32.const 0) - ) - - (memory.fill - (local.get $dst) - (i32.const 0) - (i32.const 1) - ) - - (memory.fill - (local.get $dst) - (local.get $val) - (i32.const 1) - ) - - (memory.fill - (local.get $dst) - (i32.const 1) - (i32.const 1) - ) - - (memory.fill - (local.get $dst) - (i32.const 1023) - (i32.const 1) - ) - - (memory.fill - (local.get $dst) - (i32.const 0) - (i32.const 2) - ) - - (memory.fill - (local.get $dst) - (i32.const 1) - (i32.const 2) - ) - - (memory.fill - (local.get $dst) - (i32.const 255) - (i32.const 2) - ) - - (memory.fill - (local.get $dst) - (i32.const 0) - (i32.const 4) - ) - - (memory.fill - (local.get $dst) - (i32.const 0) - (i32.const 8) - ) - - (memory.fill - (local.get $dst) - (i32.const 0) - (i32.const 16) - ) - - (memory.fill - (local.get $dst) - (i32.const 1) - (i32.const 4) - ) - - (memory.fill - (local.get $dst) - (i32.const 1) - (i32.const 8) - ) - - (memory.fill - (local.get $dst) - (i32.const 1) - (i32.const 16) - ) - - (memory.fill - (local.get $dst) - (i32.const 1023) - (i32.const 16) - ) - - (memory.fill ;; skip - (local.get $dst) - (local.get $val) - (i32.const 0) - ) - - (memory.fill ;; skip - (local.get $dst) - (i32.const 0) - (local.get $sz) - ) - - (memory.fill ;; skip - (local.get $dst) - (local.get $val) - (local.get $sz) - ) - - (memory.fill ;; skip - (local.get $dst) - (i32.const 0) - (i32.const 3) - ) - - (memory.fill ;; skip - (local.get $dst) - (i32.const 1) - (i32.const 3) - ) - - (memory.fill ;; skip - (local.get $dst) - (i32.const 0) - (i32.const 17) - ) - - (memory.fill ;; skip - (unreachable) - (i32.const 1) - (i32.const 16) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast binaryen-99/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast --- binaryen-108/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: wasm-opt %s --optimize-instructions --nominal --roundtrip --all-features -S -o - | filecheck %s -;; roundtrip to see the effects on heap types in the binary format, specifically -;; regarding nominal heap types - -(module - ;; Create multiple different signature types, all identical structurally but - ;; distinct nominally. The three tables will use different ones, and the - ;; emitted call_indirects should use the corresponding ones. - - ;; CHECK: (type $v1 (func_subtype func)) - (type $v1 (func)) - - ;; CHECK: (type $v2 (func_subtype func)) - (type $v2 (func)) - - ;; CHECK: (type $v3 (func_subtype func)) - (type $v3 (func)) - - ;; CHECK: (type $i32_=>_none (func_subtype (param i32) func)) - - ;; CHECK: (table $table-1 10 (ref null $v1)) - (table $table-1 10 (ref null $v1)) - - ;; CHECK: (table $table-2 10 (ref null $v2)) - (table $table-2 10 (ref null $v2)) - - ;; CHECK: (table $table-3 10 (ref null $v3)) - (table $table-3 10 (ref null $v3)) - - ;; CHECK: (elem $elem-1 (table $table-1) (i32.const 0) (ref null $v1) (ref.func $helper-1)) - (elem $elem-1 (table $table-1) (i32.const 0) (ref null $v1) - (ref.func $helper-1)) - - ;; CHECK: (elem $elem-2 (table $table-2) (i32.const 0) (ref null $v2) (ref.func $helper-2)) - (elem $elem-2 (table $table-2) (i32.const 0) (ref null $v2) - (ref.func $helper-2)) - - ;; CHECK: (elem $elem-3 (table $table-3) (i32.const 0) (ref null $v3) (ref.func $helper-3)) - (elem $elem-3 (table $table-3) (i32.const 0) (ref null $v3) - (ref.func $helper-3)) - - ;; CHECK: (func $helper-1 (type $v1) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper-1 (type $v1)) - ;; CHECK: (func $helper-2 (type $v2) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper-2 (type $v2)) - ;; CHECK: (func $helper-3 (type $v3) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper-3 (type $v3)) - - ;; CHECK: (func $call-table-get (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (call_indirect $table-1 (type $v1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_indirect $table-2 (type $v2) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_indirect $table-3 (type $v3) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-table-get (param $x i32) - ;; The heap type of the call_indirects that we emit here should be the - ;; identical one as on the table that they correspond to. - (call_ref - (table.get $table-1 - (local.get $x) - ) - ) - (call_ref - (table.get $table-2 - (local.get $x) - ) - ) - (call_ref - (table.get $table-3 - (local.get $x) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-call_ref.wast binaryen-99/test/lit/passes/optimize-instructions-call_ref.wast --- binaryen-108/test/lit/passes/optimize-instructions-call_ref.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-call_ref.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,232 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions --all-features -S -o - | filecheck %s -;; remove-unused-names is to allow fallthrough computations to work on blocks - -(module - ;; CHECK: (type $i32_i32_=>_none (func (param i32 i32))) - (type $i32_i32_=>_none (func (param i32 i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $none_=>_none (func)) - (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $data_=>_none (func (param dataref))) - (type $data_=>_none (func (param (ref data)))) - - ;; CHECK: (table $table-1 10 (ref null $i32_i32_=>_none)) - (table $table-1 10 (ref null $i32_i32_=>_none)) - ;; CHECK: (elem $elem-1 (table $table-1) (i32.const 0) (ref null $i32_i32_=>_none) (ref.func $foo)) - (elem $elem-1 (table $table-1) (i32.const 0) (ref null $i32_i32_=>_none) - (ref.func $foo)) - - ;; CHECK: (elem declare func $fallthrough-no-params $fallthrough-non-nullable $return-nothing) - - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param i32) (param i32) - (unreachable) - ) - ;; CHECK: (func $call_ref-to-direct (param $x i32) (param $y i32) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call_ref-to-direct (param $x i32) (param $y i32) - ;; This call_ref should become a direct call. - (call_ref - (local.get $x) - (local.get $y) - (ref.func $foo) - ) - ) - - ;; CHECK: (func $fallthrough (param $x i32) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $i32_i32_=>_none)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fallthrough (param $x i32) - ;; This call_ref should become a direct call, even though it doesn't have a - ;; simple ref.func as the target - we need to look into the fallthrough, and - ;; handle things with locals. - (call_ref - ;; Write to $x before the block, and write to it in the block; we should not - ;; reorder these things as the side effects could alter what value appears - ;; in the get of $x. (There is a risk of reordering here if we naively moved - ;; the call target (the block) to before the first parameter (the tee). - ;; Instead, we append it after the second param (the get) which keeps the - ;; ordering as it was.) - (local.tee $x - (i32.const 1) - ) - (local.get $x) - (block (result (ref $i32_i32_=>_none)) - (local.set $x - (i32.const 2) - ) - (ref.func $foo) - ) - ) - ) - - ;; CHECK: (func $fallthrough-no-params (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $none_=>_i32)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (ref.func $fallthrough-no-params) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $fallthrough-no-params) - ;; CHECK-NEXT: ) - (func $fallthrough-no-params (result i32) - ;; A fallthrough appears here, but there are no operands so this is easier to - ;; optimize: we can just drop the call_ref's target before the call. - (call_ref - (block (result (ref $none_=>_i32)) - (nop) - (ref.func $fallthrough-no-params) - ) - ) - ) - - ;; CHECK: (func $fallthrough-non-nullable (param $x dataref) - ;; CHECK-NEXT: (local $1 (ref null data)) - ;; CHECK-NEXT: (call $fallthrough-non-nullable - ;; CHECK-NEXT: (block (result dataref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $data_=>_none)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (ref.func $fallthrough-non-nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fallthrough-non-nullable (param $x (ref data)) - ;; A fallthrough appears here, and in addition the last operand is non- - ;; nullable, which means we must be careful when we create a temp local for - ;; it: the local should be nullable, and gets of it should use a - ;; ref.as_non_null so that we validate. - (call_ref - (local.get $x) - (block (result (ref $data_=>_none)) - (nop) - (ref.func $fallthrough-non-nullable) - ) - ) - ) - - ;; CHECK: (func $fallthrough-bad-type (result i32) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (block (result (ref $none_=>_i32)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $return-nothing) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $none_=>_i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fallthrough-bad-type (result i32) - ;; A fallthrough appears here, and we cast the function type to something else - ;; in a way that is bad: the actual target function has a different return - ;; type than the cast type. The cast will definitely fail, and we should not - ;; emit non-validating code here, which would happen if we replace the - ;; call_ref that returns nothing with a call that returns an i32. In fact, we - ;; end up optimizing the cast into an unreachable. - (call_ref - (ref.cast - (ref.func $return-nothing) - (rtt.canon $none_=>_i32) - ) - ) - ) - - ;; Helper function for the above test. - ;; CHECK: (func $return-nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $return-nothing) - - ;; CHECK: (func $fallthrough-unreachable - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (block (result (ref $i32_i32_=>_none)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fallthrough-unreachable - ;; If the call is not reached, do not optimize it. - (call_ref - (unreachable) - (unreachable) - (block (result (ref $i32_i32_=>_none)) - (nop) - (ref.func $foo) - ) - ) - ) - - ;; CHECK: (func $ignore-unreachable - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $ignore-unreachable - ;; Ignore an unreachable call_ref target entirely. - (call_ref - (unreachable) - ) - ) - - ;; CHECK: (func $call-table-get (param $x i32) - ;; CHECK-NEXT: (call_indirect $table-1 (type $i32_i32_=>_none) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-table-get (param $x i32) - (call_ref - (i32.const 1) - (i32.const 2) - (table.get $table-1 - (local.get $x) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-eh.wast binaryen-99/test/lit/passes/optimize-instructions-eh.wast --- binaryen-108/test/lit/passes/optimize-instructions-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,255 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (tag $e (param i32)) - - ;; CHECK: (func $dummy - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $dummy) - (tag $e (param i32)) - - ;; The following are the unit tests for Properties::getFallthrough for EH - ;; instructions, which are used in one of binary optimizations in - ;; OptimizeInstructions::visitBinary(). - - ;; When a pattern of (i32.add (expr) (expr with all 1s)) is detected and - ;; 'expr' is guaranteed to take equal or less bits than the number of bits in - ;; the second expression, the i32.add can be dropped and we can only leave - ;; (expr). For example: - ;; (i32.add (local.get $x) (i32.const 7)) can be just (local.get $x) when $x - ;; is guaranteed to contain a value equal to or less than 7. - - - ;; CHECK: (func $getFallthrough-try-no-throw - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $getFallthrough-try-no-throw - (local $x i32) - (local.set $x - (try (result i32) - (do - (i32.const 1) - ) - (catch_all - (i32.const 3) - ) - ) - ) - ;; The 'try' above is guaranteed not to throw, so we can be sure the $x - ;; contains 1 at this point, which is smaller than 7 (0b111), so we know the - ;; masking with 0b111 is not ncessary and we can only leave (local.set $x). - (drop (i32.and (local.get $x) (i32.const 7))) - ) - - ;; CHECK: (func $getFallthrough-try-may-throw - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $dummy) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $getFallthrough-try-may-throw - (local $x i32) - (local.set $x - (try (result i32) - (do - (call $dummy) - (i32.const 1) - ) - (catch_all - (i32.const 3) - ) - ) - ) - ;; The 'try' body above may throw because of the call, so we are not sure - ;; what $x contains at this point, so we can't remove the masking here. - (drop (i32.and (local.get $x) (i32.const 7))) - ) - - ;; CHECK: (func $getFallthrough-nested-try-0 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $dummy) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $getFallthrough-nested-try-0 - (local $x i32) - (local.set $x - (try (result i32) - (do - (try - (do - (call $dummy) - ) - (catch $e - (drop (pop i32)) - ) - ) - (i32.const 1) - ) - (catch $e - (drop (pop i32)) - (i32.const 3) - ) - ) - ) - ;; The inner 'try' may throw and it may not be caught by both the inner and - ;; outer catches, so we are not sure what $x contains at this point, which - ;; prevents the masking optimization. - (drop (i32.and (local.get $x) (i32.const 7))) - ) - - ;; CHECK: (func $getFallthrough-nested-try-1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $dummy) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $getFallthrough-nested-try-1 - (local $x i32) - (local.set $x - (try (result i32) - (do - (try - (do - (call $dummy) - ) - (catch_all) - ) - (i32.const 1) - ) - (catch_all - (i32.const 3) - ) - ) - ) - ;; The inner try may throw, but it will caught by the inner catch_all, and - ;; $x will be set to 1. So we can do the masking optimization and remove - ;; i32.and here. - (drop (i32.and (local.get $x) (i32.const 7))) - ) - - ;; CHECK: (func $getFallthrough-nested-try-2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (call $dummy) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $getFallthrough-nested-try-2 - (local $x i32) - (local.set $x - (try (result i32) - (do - (try - (do) - (catch_all - (call $dummy) - ) - ) - (i32.const 3) - ) - (catch_all - (i32.const 1) - ) - ) - ) - ;; Depending on whether (call $dummy) throws or not, we are not sure whether - ;; $x will contain 1 or 3 at this point, which prevents the masking - ;; optimization. - (drop (i32.and (local.get $x) (i32.const 7))) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-exceptions.wast binaryen-99/test/lit/passes/optimize-instructions-exceptions.wast --- binaryen-108/test/lit/passes/optimize-instructions-exceptions.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-exceptions.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-reference-types \ -;; RUN: --enable-exception-handling -S -o - | filecheck %s - -(module - ;; CHECK: (func $test - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (try $try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 456) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $test - (if - (try (result i32) - (do - (i32.eqz - (i32.eqz - (i32.const 123) - ) - ) - ) - (catch_all - (i32.eqz - (i32.eqz - (i32.const 456) - ) - ) - ) - ) - (nop) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-gc-heap.wast binaryen-99/test/lit/passes/optimize-instructions-gc-heap.wast --- binaryen-108/test/lit/passes/optimize-instructions-gc-heap.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-gc-heap.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,768 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions -all -S -o - \ -;; RUN: | filecheck %s -;; -;; --remove-unused-names allows the optimizer to see that the blocks have no -;; breaks to them, and so they have no nonlinear control flow. - -(module - ;; CHECK: (type $struct (struct (field (mut i32)))) - (type $struct (struct (field (mut i32)))) - - ;; CHECK: (type $struct2 (struct (field (mut i32)) (field (mut i32)))) - (type $struct2 (struct (field (mut i32)) (field (mut i32)))) - - ;; CHECK: (type $struct3 (struct (field (mut i32)) (field (mut i32)) (field (mut i32)))) - (type $struct3 (struct (field (mut i32)) (field (mut i32)) (field (mut i32)))) - - ;; CHECK: (func $tee - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $tee - (local $ref (ref null $struct)) - ;; The set is not needed as we can apply the 20 in the new. - (struct.set $struct 0 - (local.tee $ref - (struct.new $struct - (i32.const 10) - ) - ) - (i32.const 20) - ) - ) - - ;; CHECK: (func $side-effects-in-old-value - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-old-value - (local $ref (ref null $struct)) - (struct.set $struct 0 - (local.tee $ref - (struct.new $struct - ;; Side effects here force us to keep the old value around. - (call $helper-i32 (i32.const 0)) - ) - ) - (i32.const 20) - ) - ) - - ;; CHECK: (func $side-effects-in-new-value - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-new-value - (local $ref (ref null $struct)) - (struct.set $struct 0 - (local.tee $ref - (struct.new $struct - (i32.const 10) - ) - ) - ;; Side effects here are not a problem. - (call $helper-i32 (i32.const 0)) - ) - ) - - ;; CHECK: (func $many-fields - ;; CHECK-NEXT: (local $ref (ref null $struct2)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct2 - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct2 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 60) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $many-fields - (local $ref (ref null $struct2)) - ;; Set to the first field. - (struct.set $struct2 0 - (local.tee $ref - (struct.new $struct2 - (i32.const 10) - (i32.const 20) - ) - ) - (i32.const 30) - ) - ;; Set to the second. - (struct.set $struct2 1 - (local.tee $ref - (struct.new $struct2 - (i32.const 40) - (i32.const 50) - ) - ) - (i32.const 60) - ) - ) - - ;; CHECK: (func $side-effect-conflict - ;; CHECK-NEXT: (local $ref (ref null $struct2)) - ;; CHECK-NEXT: (struct.set $struct2 0 - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new $struct2 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effect-conflict - (local $ref (ref null $struct2)) - (struct.set $struct2 0 - (local.tee $ref - (struct.new $struct2 - (i32.const 10) - ;; Side effects on the second field prevent us from moving the set's - ;; value past it to replace the first field above it. - (call $helper-i32 (i32.const 0)) - ) - ) - (call $helper-i32 (i32.const 1)) - ) - ) - - ;; CHECK: (func $side-effect-ok - ;; CHECK-NEXT: (local $ref (ref null $struct2)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct2 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effect-ok - (local $ref (ref null $struct2)) - (struct.set $struct2 0 - (local.tee $ref - (struct.new $struct2 - ;; Side effects on the first field do not interfere. - (call $helper-i32 (i32.const 0)) - (i32.const 10) - ) - ) - (call $helper-i32 (i32.const 1)) - ) - ) - - ;; CHECK: (func $optimize-subsequent - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $optimize-subsequent - (local $ref (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - ;; A set that comes right after can be optimized too. - (struct.set $struct 0 - (local.get $ref) - (i32.const 20) - ) - ) - - ;; CHECK: (func $optimize-subsequent-bad-local - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local $other (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $other) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-subsequent-bad-local - (local $ref (ref null $struct)) - (local $other (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - ;; As above, but the local.get uses a different local, so we have nothing - ;; to optimize. - (struct.set $struct 0 - (local.get $other) - (i32.const 20) - ) - ) - - ;; CHECK: (func $optimize-chain - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $optimize-chain - (local $ref (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (i32.const 20) - ) - ;; The value in the last item in the chain should apply. - (struct.set $struct 0 - (local.get $ref) - (i32.const 30) - ) - ) - - ;; CHECK: (func $pattern-breaker - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pattern-breaker - (local $ref (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - ;; Anything that we don't recognize breaks the pattern. - (nop) - (struct.set $struct 0 - (local.get $ref) - (i32.const 20) - ) - ) - - ;; CHECK: (func $ref-local-write - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref-local-write - (local $ref (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (block (result i32) - ;; A write to the ref local prevents us from optimizing. - (local.set $ref - (ref.null $struct) - ) - (i32.const 20) - ) - ) - ) - - ;; CHECK: (func $ref-local-write-tee - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref-local-write-tee - (local $ref (ref null $struct)) - (struct.set $struct 0 - (local.tee $ref - (struct.new $struct - (i32.const 10) - ) - ) - (block (result i32) - ;; As above, but now in a tee. - (local.set $ref - (ref.null $struct) - ) - (i32.const 20) - ) - ) - ) - - ;; CHECK: (func $other-local-write - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local $other (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $other - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $other-local-write - (local $ref (ref null $struct)) - (local $other (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (block (result i32) - ;; A write to another local is fine. - (local.set $other - (ref.null $struct) - ) - (i32.const 20) - ) - ) - ) - - ;; CHECK: (func $ref-local-read - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref-local-read - (local $ref (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (block (result i32) - ;; A read of the ref local prevents us from optimizing. - (drop - (local.get $ref) - ) - (i32.const 20) - ) - ) - ) - - ;; CHECK: (func $ref-local-read-tee - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref-local-read-tee - (local $ref (ref null $struct)) - (struct.set $struct 0 - (local.tee $ref - (struct.new $struct - (i32.const 10) - ) - ) - (block (result i32) - ;; As above, but now in a tee. - (drop - (local.get $ref) - ) - (i32.const 20) - ) - ) - ) - - ;; CHECK: (func $ref-other-read - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local $other (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $other) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $ref-other-read - (local $ref (ref null $struct)) - (local $other (ref null $struct)) - (local.set $ref - (struct.new $struct - (i32.const 10) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (block (result i32) - ;; A read of another local is fine. - (drop - (local.get $other) - ) - (i32.const 20) - ) - ) - ) - - ;; CHECK: (func $tee-and-subsequent - ;; CHECK-NEXT: (local $ref (ref null $struct3)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct3 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 50) - ;; CHECK-NEXT: (i32.const 60) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $tee-and-subsequent - (local $ref (ref null $struct3)) - ;; Test the common pattern of several subsequent sets, one of which is - ;; using a tee. - (struct.set $struct3 0 - (local.tee $ref - (struct.new $struct3 - (i32.const 10) - (i32.const 20) - (i32.const 30) - ) - ) - (i32.const 40) - ) - (struct.set $struct3 1 - (local.get $ref) - (i32.const 50) - ) - (struct.set $struct3 2 - (local.get $ref) - (i32.const 60) - ) - ) - - ;; CHECK: (func $side-effect-subsequent-ok - ;; CHECK-NEXT: (local $ref (ref null $struct2)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct2 - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper-i32 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $side-effect-subsequent-ok - (local $ref (ref null $struct2)) - (local.set $ref - (struct.new $struct2 - ;; The first field has side effects, but the second does not. - (call $helper-i32 (i32.const 0)) - (i32.const 10) - ) - ) - ;; Replace the second field with something with side effects. - (struct.set $struct2 1 - (local.get $ref) - (call $helper-i32 (i32.const 1)) - ) - ) - - ;; CHECK: (func $default - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $default - (local $ref (ref null $struct)) - (struct.set $struct 0 - (local.tee $ref - ;; Ignore a new_default for now. If the fields are defaultable then we - ;; could add them, in principle, but that might increase code size. - (struct.new_default $struct) - ) - (i32.const 20) - ) - ) - - ;; CHECK: (func $many-news - ;; CHECK-NEXT: (local $ref (ref null $struct3)) - ;; CHECK-NEXT: (local $ref2 (ref null $struct3)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct3 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 50) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (struct.set $struct3 2 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 60) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct3 - ;; CHECK-NEXT: (i32.const 400) - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: (i32.const 500) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct3 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $ref2 - ;; CHECK-NEXT: (struct.new $struct3 - ;; CHECK-NEXT: (i32.const 400) - ;; CHECK-NEXT: (i32.const 600) - ;; CHECK-NEXT: (i32.const 500) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $many-news - (local $ref (ref null $struct3)) - (local $ref2 (ref null $struct3)) - ;; Test that we optimize for multiple struct.news in the same function. - (struct.set $struct3 0 - (local.tee $ref - (struct.new $struct3 - (i32.const 10) - (i32.const 20) - (i32.const 30) - ) - ) - (i32.const 40) - ) - (struct.set $struct3 1 - (local.get $ref) - (i32.const 50) - ) - (nop) - (struct.set $struct3 2 - (local.get $ref) - (i32.const 60) - ) - (nop) - (struct.set $struct3 0 - (local.tee $ref - (struct.new $struct3 - (i32.const 100) - (i32.const 200) - (i32.const 300) - ) - ) - (i32.const 400) - ) - (struct.set $struct3 2 - (local.get $ref) - (i32.const 500) - ) - ;; Test inside an inner block. - (block $inner - (struct.set $struct3 0 - (local.tee $ref - (struct.new $struct3 - (i32.const 10) - (i32.const 20) - (i32.const 30) - ) - ) - (i32.const 40) - ) - ;; Use a different ref local here. - (struct.set $struct3 0 - (local.tee $ref2 - (struct.new $struct3 - (i32.const 100) - (i32.const 200) - (i32.const 300) - ) - ) - (i32.const 400) - ) - (struct.set $struct3 2 - (local.get $ref2) - (i32.const 500) - ) - (struct.set $struct3 1 - (local.get $ref2) - (i32.const 600) - ) - ) - ) - - ;; CHECK: (func $unreachable - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.tee $ref - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable - (local $ref (ref null $struct)) - ;; Do not optimize unreachable code, either in the new (first pair) or the - ;; set (second pair) - (local.set $ref - (struct.new $struct - (unreachable) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (i32.const 10) - ) - (nop) - (local.set $ref - (struct.new $struct - (i32.const 20) - ) - ) - (struct.set $struct 0 - (local.get $ref) - (unreachable) - ) - ) - - ;; CHECK: (func $helper-i32 (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - (func $helper-i32 (param $x i32) (result i32) - (i32.const 42) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-gc-iit.wast binaryen-99/test/lit/passes/optimize-instructions-gc-iit.wast --- binaryen-108/test/lit/passes/optimize-instructions-gc-iit.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-gc-iit.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,417 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: foreach %s %t wasm-opt --optimize-instructions --ignore-implicit-traps --enable-reference-types --enable-gc -S -o - \ -;; RUN: | filecheck %s -;; RUN: foreach %s %t wasm-opt --optimize-instructions --ignore-implicit-traps --enable-reference-types --enable-gc --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix NOMNL -;; Also test trapsNeverHappen (with nominal; no need for both type system modes). -;; RUN: foreach %s %t wasm-opt --optimize-instructions --traps-never-happen --enable-reference-types --enable-gc --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix NOMNL-TNH - -(module - ;; CHECK: (type $parent (struct (field i32))) - ;; NOMNL: (type $parent (struct_subtype (field i32) data)) - ;; NOMNL-TNH: (type $parent (struct_subtype (field i32) data)) - (type $parent (struct (field i32))) - ;; CHECK: (type $child (struct (field i32) (field f64))) - ;; NOMNL: (type $child (struct_subtype (field i32) (field f64) $parent)) - ;; NOMNL-TNH: (type $child (struct_subtype (field i32) (field f64) $parent)) - (type $child (struct_subtype (field i32) (field f64) $parent)) - ;; CHECK: (type $other (struct (field i64) (field f32))) - ;; NOMNL: (type $other (struct_subtype (field i64) (field f32) data)) - ;; NOMNL-TNH: (type $other (struct_subtype (field i64) (field f32) data)) - (type $other (struct (field i64) (field f32))) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $foo (type $none_=>_none) - ;; NOMNL-TNH-NEXT: (nop) - ;; NOMNL-TNH-NEXT: ) - (func $foo) - - - ;; CHECK: (func $ref-cast-iit (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) (param $parent-rtt (rtt $parent)) (param $child-rtt (rtt $child)) (param $other-rtt (rtt $other)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $parent)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: (local.get $child-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $other)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $other-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-iit (type $ref|$parent|_ref|$child|_ref|$other|_rtt_$parent_rtt_$child_rtt_$other_=>_none) (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) (param $parent-rtt (rtt $parent)) (param $child-rtt (rtt $child)) (param $other-rtt (rtt $other)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $parent)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $child)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $child) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: (local.get $child-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $other)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $child) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $other-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $ref-cast-iit (type $ref|$parent|_ref|$child|_ref|$other|_rtt_$parent_rtt_$child_rtt_$other_=>_none) (param $parent (ref $parent)) (param $child (ref $child)) (param $other (ref $other)) (param $parent-rtt (rtt $parent)) (param $child-rtt (rtt $child)) (param $other-rtt (rtt $other)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $parent)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $child)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (local.get $child) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (ref.cast - ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: (local.get $child-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $other)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $child) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (local.get $other-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (unreachable) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - (func $ref-cast-iit - (param $parent (ref $parent)) - (param $child (ref $child)) - (param $other (ref $other)) - - (param $parent-rtt (rtt $parent)) - (param $child-rtt (rtt $child)) - (param $other-rtt (rtt $other)) - - ;; a cast of parent to an rtt of parent: assuming no traps as we do, we can - ;; optimize this as the new type will be valid. - (drop - (ref.cast - (local.get $parent) - (local.get $parent-rtt) - ) - ) - ;; a cast of child to a supertype: again, we replace with a valid type. - (drop - (ref.cast - (local.get $child) - (local.get $parent-rtt) - ) - ) - ;; a cast of parent to a subtype: we cannot replace the original heap type - ;; $child with one that is not equal or more specific, like $parent, so we - ;; cannot optimize here. - (drop - (ref.cast - (local.get $parent) - (local.get $child-rtt) - ) - ) - ;; a cast of child to an unrelated type: it will trap anyhow - (drop - (ref.cast - (local.get $child) - (local.get $other-rtt) - ) - ) - ) - - ;; CHECK: (func $ref-cast-iit-bad (param $parent (ref $parent)) (param $parent-rtt (rtt $parent)) - ;; CHECK-NEXT: (local $2 (ref null $parent)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $parent)) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (block $block (result (ref $parent)) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block0 (result (rtt $parent)) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $parent) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (local.get $parent-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-iit-bad (type $ref|$parent|_rtt_$parent_=>_none) (param $parent (ref $parent)) (param $parent-rtt (rtt $parent)) - ;; NOMNL-NEXT: (local $2 (ref null $parent)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $parent)) - ;; NOMNL-NEXT: (local.set $2 - ;; NOMNL-NEXT: (block $block (result (ref $parent)) - ;; NOMNL-NEXT: (call $foo) - ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block $block0 (result (rtt $parent)) - ;; NOMNL-NEXT: (call $foo) - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $parent) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: (local.get $parent-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $ref-cast-iit-bad (type $ref|$parent|_rtt_$parent_=>_none) (param $parent (ref $parent)) (param $parent-rtt (rtt $parent)) - ;; NOMNL-TNH-NEXT: (local $2 (ref null $parent)) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block (result (ref $parent)) - ;; NOMNL-TNH-NEXT: (local.set $2 - ;; NOMNL-TNH-NEXT: (block $block (result (ref $parent)) - ;; NOMNL-TNH-NEXT: (call $foo) - ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (block $block0 (result (rtt $parent)) - ;; NOMNL-TNH-NEXT: (call $foo) - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (ref.as_non_null - ;; NOMNL-TNH-NEXT: (local.get $2) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (ref.cast - ;; NOMNL-TNH-NEXT: (local.get $parent) - ;; NOMNL-TNH-NEXT: (unreachable) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (ref.cast - ;; NOMNL-TNH-NEXT: (unreachable) - ;; NOMNL-TNH-NEXT: (local.get $parent-rtt) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - (func $ref-cast-iit-bad - (param $parent (ref $parent)) - (param $parent-rtt (rtt $parent)) - - ;; optimizing this cast away requires reordering. - (drop - (ref.cast - (block (result (ref $parent)) - (call $foo) - (local.get $parent) - ) - (block (result (rtt $parent)) - (call $foo) - (local.get $parent-rtt) - ) - ) - ) - - ;; ignore unreachability - (drop - (ref.cast - (local.get $parent) - (unreachable) - ) - ) - (drop - (ref.cast - (unreachable) - (local.get $parent-rtt) - ) - ) - ) - - ;; CHECK: (func $ref-eq-ref-cast (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-eq-ref-cast (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $ref-eq-ref-cast (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-TNH-NEXT: (drop - ;; NOMNL-TNH-NEXT: (i32.const 1) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - (func $ref-eq-ref-cast (param $x eqref) - ;; we can look through a ref.cast if we ignore traps - (drop - (ref.eq - (local.get $x) - (ref.cast - (local.get $x) - (rtt.canon $parent) - ) - ) - ) - ) - - ;; CHECK: (func $set-of-as-non-null (param $x anyref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $set-of-as-non-null (type $anyref_=>_none) (param $x anyref) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $set-of-as-non-null (type $anyref_=>_none) (param $x anyref) - ;; NOMNL-TNH-NEXT: (local.set $x - ;; NOMNL-TNH-NEXT: (local.get $x) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - (func $set-of-as-non-null (param $x anyref) - ;; As we ignore such traps, we can remove the ref.as here. - (local.set $x - (ref.as_non_null - (local.get $x) - ) - ) - ) -) - -(module - ;; CHECK: (type $B (struct (field (ref null $A)))) - - ;; CHECK: (type $A (struct )) - ;; NOMNL: (type $A (struct_subtype data)) - ;; NOMNL-TNH: (type $A (struct_subtype data)) - (type $A (struct_subtype data)) - ;; NOMNL: (type $B (struct_subtype (field (ref null $A)) $A)) - ;; NOMNL-TNH: (type $B (struct_subtype (field (ref null $A)) $A)) - (type $B (struct_subtype (field (ref null $A)) $A)) - ;; NOMNL: (type $C (struct_subtype (field (ref null $D)) $B)) - ;; NOMNL-TNH: (type $C (struct_subtype (field (ref null $D)) $B)) - (type $C (struct_subtype (field (ref null $D)) $B)) - ;; NOMNL: (type $D (struct_subtype $A)) - ;; NOMNL-TNH: (type $D (struct_subtype $A)) - (type $D (struct_subtype $A)) - - ;; CHECK: (func $test (param $C (ref $B)) (result anyref) - ;; CHECK-NEXT: (struct.get $B 0 - ;; CHECK-NEXT: (local.get $C) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $ref|$C|_=>_anyref) (param $C (ref $C)) (result anyref) - ;; NOMNL-NEXT: (struct.get $C 0 - ;; NOMNL-NEXT: (local.get $C) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-TNH: (func $test (type $ref|$C|_=>_anyref) (param $C (ref $C)) (result anyref) - ;; NOMNL-TNH-NEXT: (struct.get $C 0 - ;; NOMNL-TNH-NEXT: (local.get $C) - ;; NOMNL-TNH-NEXT: ) - ;; NOMNL-TNH-NEXT: ) - (func $test (param $C (ref $C)) (result anyref) - (struct.get $B 0 - (ref.cast_static $B ;; Try to cast a $C to its parent, $B. That always - ;; works, so the cast can be removed. - ;; Then once the cast is removed, the outer struct.get - ;; will have a reference with a different type, - ;; making it a (struct.get $C ..) instead of $B. - ;; But $B and $C have different types on field 0, and - ;; so the struct.get must be refinalized so the node - ;; has the expected type. - (local.get $C) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-gc-tnh-nn.wast binaryen-99/test/lit/passes/optimize-instructions-gc-tnh-nn.wast --- binaryen-108/test/lit/passes/optimize-instructions-gc-tnh-nn.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-gc-tnh-nn.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --traps-never-happen --enable-gc-nn-locals -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (func $set-of-as-non-null - ;; CHECK-NEXT: (local $x anyref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set-of-as-non-null - (local $x anyref) - ;; As we ignore such traps, we can in principle remove the ref.as here. - ;; However, as we allow non-nullable locals, we should not do that - if we - ;; did it it might prevent specializing the local type later. - (local.set $x - (ref.as_non_null - (local.get $x) - ) - ) - ;; The same for a tee. - (drop - (local.tee $x - (ref.as_non_null - (local.get $x) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-gc.wast binaryen-99/test/lit/passes/optimize-instructions-gc.wast --- binaryen-108/test/lit/passes/optimize-instructions-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,2850 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions --enable-reference-types --enable-gc -S -o - \ -;; RUN: | filecheck %s -;; RUN: wasm-opt %s --remove-unused-names --optimize-instructions --enable-reference-types --enable-gc --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix NOMNL - -(module - ;; CHECK: (type $struct (struct (field $i8 (mut i8)) (field $i16 (mut i16)) (field $i32 (mut i32)) (field $i64 (mut i64)))) - ;; NOMNL: (type $struct (struct_subtype (field $i8 (mut i8)) (field $i16 (mut i16)) (field $i32 (mut i32)) (field $i64 (mut i64)) data)) - (type $struct (struct - (field $i8 (mut i8)) - (field $i16 (mut i16)) - (field $i32 (mut i32)) - (field $i64 (mut i64)) - )) - - ;; CHECK: (type $A (struct (field i32))) - ;; NOMNL: (type $A (struct_subtype (field i32) data)) - (type $A (struct (field i32))) - - ;; CHECK: (type $B (struct (field i32) (field i32) (field f32))) - - ;; CHECK: (type $array (array (mut i8))) - ;; NOMNL: (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) - - ;; NOMNL: (type $array (array_subtype (mut i8) data)) - (type $array (array (mut i8))) - - (type $B (struct_subtype (field i32) (field i32) (field f32) $A)) - - ;; CHECK: (type $B-child (struct (field i32) (field i32) (field f32) (field i64))) - ;; NOMNL: (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B)) - (type $B-child (struct_subtype (field i32) (field i32) (field f32) (field i64) $B)) - - ;; CHECK: (type $empty (struct )) - ;; NOMNL: (type $empty (struct_subtype data)) - (type $empty (struct)) - - ;; CHECK: (type $C (struct (field i32) (field i32) (field f64))) - ;; NOMNL: (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) - (type $C (struct_subtype (field i32) (field i32) (field f64) $A)) - - ;; CHECK: (import "env" "get-i32" (func $get-i32 (result i32))) - ;; NOMNL: (import "env" "get-i32" (func $get-i32 (result i32))) - (import "env" "get-i32" (func $get-i32 (result i32))) - - ;; These functions test if an `if` with subtyped arms is correctly folded - ;; 1. if its `ifTrue` and `ifFalse` arms are identical (can fold) - ;; CHECK: (func $if-arms-subtype-fold (result anyref) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $if-arms-subtype-fold (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: ) - (func $if-arms-subtype-fold (result anyref) - (if (result anyref) - (i32.const 0) - (ref.null extern) - (ref.null extern) - ) - ) - ;; 2. if its `ifTrue` and `ifFalse` arms are not identical (cannot fold) - ;; CHECK: (func $if-arms-subtype-nofold (result anyref) - ;; CHECK-NEXT: (if (result anyref) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $if-arms-subtype-nofold (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (if (result anyref) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: (ref.null func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $if-arms-subtype-nofold (result anyref) - (if (result anyref) - (i32.const 0) - (ref.null extern) - (ref.null func) - ) - ) - - ;; Stored values automatically truncate unneeded bytes. - ;; CHECK: (func $store-trunc (param $x (ref null $struct)) - ;; CHECK-NEXT: (struct.set $struct $i8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct $i16 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 9029) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct $i8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $get-i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $store-trunc (type $ref?|$struct|_=>_none) (param $x (ref null $struct)) - ;; NOMNL-NEXT: (struct.set $struct $i8 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 35) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct $i16 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 9029) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct $i8 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (call $get-i32) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $store-trunc (param $x (ref null $struct)) - (struct.set $struct $i8 - (local.get $x) - (i32.const 0x123) ;; data over 0xff is unnecessary - ) - (struct.set $struct $i16 - (local.get $x) - (i32.const 0x12345) ;; data over 0xffff is unnecessary - ) - (struct.set $struct $i8 - (local.get $x) - (i32.and ;; truncating bits using an and is unnecessary - (call $get-i32) - (i32.const 0xff) - ) - ) - ) - - ;; Similar, but for arrays. - ;; CHECK: (func $store-trunc2 (param $x (ref null $array)) - ;; CHECK-NEXT: (array.set $array - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 35) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $store-trunc2 (type $ref?|$array|_=>_none) (param $x (ref null $array)) - ;; NOMNL-NEXT: (array.set $array - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: (i32.const 35) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $store-trunc2 (param $x (ref null $array)) - (array.set $array - (local.get $x) - (i32.const 0) - (i32.const 0x123) ;; data over 0xff is unnecessary - ) - ) - - ;; ref.is_null is not needed on a non-nullable value, and if something is - ;; a func we don't need that either etc. if we know the result - ;; CHECK: (func $unneeded_is (param $struct (ref $struct)) (param $func (ref func)) (param $data dataref) (param $i31 i31ref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_is (type $ref|$struct|_ref|func|_dataref_i31ref_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $data dataref) (param $i31 i31ref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_is - (param $struct (ref $struct)) - (param $func (ref func)) - (param $data (ref data)) - (param $i31 (ref i31)) - (drop - (ref.is_null (local.get $struct)) - ) - (drop - (ref.is_func (local.get $func)) - ) - (drop - (ref.is_data (local.get $data)) - ) - (drop - (ref.is_i31 (local.get $i31)) - ) - ) - - ;; similar to $unneeded_is, but the values are nullable. we can at least - ;; leave just the null check. - ;; CHECK: (func $unneeded_is_null (param $struct (ref null $struct)) (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_is_null (type $ref?|$struct|_funcref_ref?|data|_ref?|i31|_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.eqz - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.eqz - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.eqz - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_is_null - (param $struct (ref null $struct)) - (param $func (ref null func)) - (param $data (ref null data)) - (param $i31 (ref null i31)) - (drop - (ref.is_null (local.get $struct)) - ) - (drop - (ref.is_func (local.get $func)) - ) - (drop - (ref.is_data (local.get $data)) - ) - (drop - (ref.is_i31 (local.get $i31)) - ) - ) - - ;; similar to $unneeded_is, but the values are of mixed kind (is_func of - ;; data, etc.). regardless of nullability the result here is always 0. - ;; CHECK: (func $unneeded_is_bad_kinds (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_is_bad_kinds (type $funcref_ref?|data|_ref?|i31|_=>_none) (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_is_bad_kinds - (param $func (ref null func)) - (param $data (ref null data)) - (param $i31 (ref null i31)) - (drop - (ref.is_func (local.get $data)) - ) - (drop - (ref.is_data (local.get $i31)) - ) - (drop - (ref.is_i31 (local.get $func)) - ) - ;; also check non-nullable types as inputs - (drop - (ref.is_func (ref.as_non_null (local.get $data))) - ) - (drop - (ref.is_data (ref.as_non_null (local.get $i31))) - ) - (drop - (ref.is_i31 (ref.as_non_null (local.get $func))) - ) - ) - - ;; ref.as_non_null is not needed on a non-nullable value, and if something is - ;; a func we don't need that either etc., and can just return the value. - ;; CHECK: (func $unneeded_as (param $struct (ref $struct)) (param $func (ref func)) (param $data dataref) (param $i31 i31ref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_as (type $ref|$struct|_ref|func|_dataref_i31ref_=>_none) (param $struct (ref $struct)) (param $func (ref func)) (param $data dataref) (param $i31 i31ref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_as - (param $struct (ref $struct)) - (param $func (ref func)) - (param $data (ref data)) - (param $i31 (ref i31)) - (drop - (ref.as_non_null (local.get $struct)) - ) - (drop - (ref.as_func (local.get $func)) - ) - (drop - (ref.as_data (local.get $data)) - ) - (drop - (ref.as_i31 (local.get $i31)) - ) - ) - - ;; similar to $unneeded_as, but the values are nullable. we can turn the - ;; more specific things into ref.as_non_null. - ;; CHECK: (func $unneeded_as_null (param $struct (ref null $struct)) (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_as_null (type $ref?|$struct|_funcref_ref?|data|_ref?|i31|_=>_none) (param $struct (ref null $struct)) (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_as_null - (param $struct (ref null $struct)) - (param $func (ref null func)) - (param $data (ref null data)) - (param $i31 (ref null i31)) - (drop - (ref.as_non_null (local.get $struct)) - ) - (drop - (ref.as_func (local.get $func)) - ) - (drop - (ref.as_data (local.get $data)) - ) - (drop - (ref.as_i31 (local.get $i31)) - ) - ) - - ;; similar to $unneeded_as, but the values are of mixed kind (as_func of - ;; data, etc.), so we know we will trap - ;; CHECK: (func $unneeded_as_bad_kinds (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref func)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result dataref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i31ref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref func)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result dataref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $i31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i31ref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_as_bad_kinds (type $funcref_ref?|data|_ref?|i31|_=>_none) (param $func funcref) (param $data (ref null data)) (param $i31 (ref null i31)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref func)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result dataref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i31ref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref func)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $data) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result dataref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $i31) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i31ref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_as_bad_kinds - (param $func (ref null func)) - (param $data (ref null data)) - (param $i31 (ref null i31)) - (drop - (ref.as_func (local.get $data)) - ) - (drop - (ref.as_data (local.get $i31)) - ) - (drop - (ref.as_i31 (local.get $func)) - ) - ;; also check non-nullable types as inputs - (drop - (ref.as_func (ref.as_non_null (local.get $data))) - ) - (drop - (ref.as_data (ref.as_non_null (local.get $i31))) - ) - (drop - (ref.as_i31 (ref.as_non_null (local.get $func))) - ) - ) - - ;; CHECK: (func $unneeded_unreachability - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_func - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_func - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unneeded_unreachability (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.is_func - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_func - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $unneeded_unreachability - ;; unreachable instructions can simply be ignored - (drop - (ref.is_func (unreachable)) - ) - (drop - (ref.as_func (unreachable)) - ) - ) - - ;; CHECK: (func $redundant-non-null-casts (param $x (ref null $struct)) (param $y (ref null $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct $i8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (array.set $array - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.get_u $array - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (array.len $array - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $redundant-non-null-casts (type $ref?|$struct|_ref?|$array|_=>_none) (param $x (ref null $struct)) (param $y (ref null $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct $i8 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (array.set $array - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (i32.const 3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (array.get_u $array - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: (i32.const 4) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (array.len $array - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $redundant-non-null-casts (param $x (ref null $struct)) (param $y (ref null $array)) - (drop - (ref.as_non_null - (ref.as_non_null - (ref.as_non_null - (local.get $x) - ) - ) - ) - ) - (struct.set $struct 0 - (ref.as_non_null - (local.get $x) - ) - (i32.const 1) - ) - (drop - (struct.get_u $struct 0 - (ref.as_non_null - (local.get $x) - ) - ) - ) - (array.set $array - (ref.as_non_null - (local.get $y) - ) - (i32.const 2) - (i32.const 3) - ) - (drop - (array.get $array - (ref.as_non_null - (local.get $y) - ) - (i32.const 4) - ) - ) - (drop - (array.len $array - (ref.as_non_null - (local.get $y) - ) - ) - ) - ) - - ;; CHECK: (func $get-eqref (result eqref) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get-eqref (type $none_=>_eqref) (result eqref) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $get-eqref (result eqref) - (unreachable) - ) - - ;; CHECK: (func $ref-eq (param $x eqref) (param $y eqref) - ;; CHECK-NEXT: (local $lx eqref) - ;; CHECK-NEXT: (local $ly eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $lx - ;; CHECK-NEXT: (call $get-eqref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-eq (type $eqref_eqref_=>_none) (param $x eqref) (param $y eqref) - ;; NOMNL-NEXT: (local $lx eqref) - ;; NOMNL-NEXT: (local $ly eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $lx - ;; NOMNL-NEXT: (call $get-eqref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-eq (param $x eqref) (param $y eqref) - (local $lx eqref) - (local $ly eqref) - ;; identical parameters are equal - (drop - (ref.eq - (local.get $x) - (local.get $x) - ) - ) - ;; different ones might not be - (drop - (ref.eq - (local.get $x) - (local.get $y) - ) - ) - ;; identical locals are - (local.set $lx - (call $get-eqref) - ) - (drop - (ref.eq - (local.get $lx) - (local.get $lx) - ) - ) - ;; fallthroughs work ok (but we need --remove-unused-names so that we can - ;; trivially tell that there are no breaks) - (drop - (ref.eq - (block (result eqref) - (nop) - (local.get $x) - ) - (block (result eqref) - (nop) - (drop - (i32.const 10) - ) - (nop) - (local.get $x) - ) - ) - ) - ) - - ;; CHECK: (func $nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $nothing (type $none_=>_none) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $nothing) - - - ;; CHECK: (func $ref-eq-corner-cases (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (block (result eqref) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (result eqref) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-eq-corner-cases (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (block (result eqref) - ;; NOMNL-NEXT: (call $nothing) - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (block (result eqref) - ;; NOMNL-NEXT: (call $nothing) - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.new_default_with_rtt $struct - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-eq-corner-cases (param $x eqref) - ;; side effects prevent optimization - (drop - (ref.eq - (block (result eqref) - (call $nothing) - (local.get $x) - ) - (block (result eqref) - (call $nothing) - (local.get $x) - ) - ) - ) - ;; allocation prevents optimization - (drop - (ref.eq - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ) - ;; but irrelevant allocations do not prevent optimization - (drop - (ref.eq - (block (result eqref) - ;; an allocation that does not trouble us - (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - (local.get $x) - ) - (block (result eqref) - (drop - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ;; add a nop to make the two inputs to ref.eq not structurally equal, - ;; but in a way that does not matter (since only the value falling - ;; out does) - (nop) - (local.get $x) - ) - ) - ) - ) - - ;; CHECK: (func $ref-eq-ref-cast (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-eq-ref-cast (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-eq-ref-cast (param $x eqref) - ;; it is almost valid to look through a cast, except that it might trap so - ;; there is a side effect - (drop - (ref.eq - (local.get $x) - (ref.cast - (local.get $x) - (rtt.canon $struct) - ) - ) - ) - ) - - ;; CHECK: (func $flip-cast-of-as-non-null (param $x anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.as_func - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.as_data - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.as_i31 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $flip-cast-of-as-non-null (type $anyref_=>_none) (param $x anyref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.as_func - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.as_data - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.as_i31 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $flip-cast-of-as-non-null (param $x anyref) - (drop - (ref.cast - ;; this can be moved through the ref.cast outward. - (ref.as_non_null - (local.get $x) - ) - (rtt.canon $struct) - ) - ) - (drop - ;; an example of how this helps: the struct.get will trap on null anyhow - (struct.get_u $struct 0 - (ref.cast - ;; this can be moved through the ref.cast outward. - (ref.as_non_null - (local.get $x) - ) - (rtt.canon $struct) - ) - ) - ) - ;; other ref.as* operations are ignored for now - (drop - (ref.cast - (ref.as_func - (local.get $x) - ) - (rtt.canon $struct) - ) - ) - (drop - (ref.cast - (ref.as_data - (local.get $x) - ) - (rtt.canon $struct) - ) - ) - (drop - (ref.cast - (ref.as_i31 - (local.get $x) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $flip-tee-of-as-non-null (param $x anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $flip-tee-of-as-non-null (type $anyref_=>_none) (param $x anyref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.tee $x - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $flip-tee-of-as-non-null (param $x anyref) - (drop - (local.tee $x - ;; this can be moved through the tee outward. - (ref.as_non_null - (local.get $x) - ) - ) - ) - ) - - ;; CHECK: (func $flip-tee-of-as-non-null-non-nullable (param $x (ref any)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $flip-tee-of-as-non-null-non-nullable (type $ref|any|_=>_none) (param $x (ref any)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.tee $x - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $flip-tee-of-as-non-null-non-nullable (param $x (ref any)) - (drop - (local.tee $x - ;; this *cannnot* be moved through the tee outward, as the param is in - ;; fact non-nullable, and we depend on the ref.as_non_null in order to - ;; get a valid type to assign to it - (ref.as_non_null - (ref.null any) - ) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms (param $x i32) (param $y (ref null $struct)) (param $z (ref null $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (if (result (ref null $struct)) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ternary-identical-arms (type $i32_ref?|$struct|_ref?|$struct|_=>_none) (param $x i32) (param $y (ref null $struct)) (param $z (ref null $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (if (result (ref null $struct)) - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: (local.get $z) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ternary-identical-arms (param $x i32) (param $y (ref null $struct)) (param $z (ref null $struct)) - (drop - (if (result i32) - (local.get $x) - (ref.is_null (local.get $y)) - (ref.is_null (local.get $z)) - ) - ) - ) - ;; CHECK: (func $select-identical-arms-but-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $select-identical-arms-but-side-effect (type $ref?|$struct|_ref?|$struct|_i32_=>_none) (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (select - ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $z) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $select-identical-arms-but-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32) - (drop - (select - ;; the arms are equal but have side effects - (struct.get_u $struct 0 - (local.get $x) - ) - (struct.get_u $struct 0 - (local.get $y) - ) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-no-side-effect (param $x (ref $struct)) (param $y (ref $struct)) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (select (result (ref $struct)) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ternary-identical-arms-no-side-effect (type $ref|$struct|_ref|$struct|_i32_=>_none) (param $x (ref $struct)) (param $y (ref $struct)) (param $z i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (select (result (ref $struct)) - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: (local.get $z) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ternary-identical-arms-no-side-effect (param $x (ref $struct)) (param $y (ref $struct)) (param $z i32) - (drop - (select - ;; the arms are equal and as the params are non-null, there are no possible side effects - (struct.get_u $struct 0 - (local.get $x) - ) - (struct.get_u $struct 0 - (local.get $y) - ) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $if-identical-arms-with-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (if (result (ref null $struct)) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $if-identical-arms-with-side-effect (type $ref?|$struct|_ref?|$struct|_i32_=>_none) (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (if (result (ref null $struct)) - ;; NOMNL-NEXT: (local.get $z) - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $if-identical-arms-with-side-effect (param $x (ref null $struct)) (param $y (ref null $struct)) (param $z i32) - (drop - (if (result i32) - (local.get $z) - ;; the arms are equal and have side effects, but that is ok with an if - ;; which only executes one side anyhow - (struct.get_u $struct 0 - (local.get $x) - ) - (struct.get_u $struct 0 - (local.get $y) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-squared (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-squared (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-squared (param $x eqref) - ;; Identical ref.casts can be folded together. - (drop - (ref.cast - (ref.cast - (local.get $x) - (rtt.canon $struct) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $ref-cast-squared-fallthrough (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-squared-fallthrough (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.tee $x - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-squared-fallthrough (param $x eqref) - ;; A fallthrough in the middle does not prevent this optimization. - (drop - (ref.cast - (local.tee $x - (ref.cast - (local.get $x) - (rtt.canon $struct) - ) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $ref-cast-cubed (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-cubed (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-cubed (param $x eqref) - ;; Three and more also work. - (drop - (ref.cast - (ref.cast - (ref.cast - (local.get $x) - (rtt.canon $struct) - ) - (rtt.canon $struct) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $ref-cast-squared-different (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-squared-different (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-squared-different (param $x eqref) - ;; Different casts cannot be folded. - (drop - (ref.cast - (ref.cast - (local.get $x) - (rtt.canon $empty) - ) - (rtt.canon $struct) - ) - ) - ) - ;; CHECK: (func $ref-cast-squared-effects (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $get-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $get-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-squared-effects (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (call $get-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $get-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-squared-effects (param $x eqref) - ;; The rtts are equal but have side effects, preventing optimization. - (drop - (ref.cast - (ref.cast - (local.get $x) - (call $get-rtt) - ) - (call $get-rtt) - ) - ) - ) - - ;; Helper function for above. - ;; CHECK: (func $get-rtt (result (rtt $empty)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $get-rtt (type $none_=>_rtt_$empty) (result (rtt $empty)) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $get-rtt (result (rtt $empty)) - (unreachable) - ) - - ;; CHECK: (func $ref-eq-null (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-eq-null (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-eq-null (param $x eqref) - ;; Equality to null can be done with ref.is_null. - (drop - (ref.eq - (local.get $x) - (ref.null eq) - ) - ) - (drop - (ref.eq - (ref.null eq) - (local.get $x) - ) - ) - ;; Also check that we turn a comparison of two nulls into 1, using the rule - ;; for comparing the same thing to itself (i.e., that we run that rule first - ;; and not the check for one of them being null, which would require more - ;; work afterwards). - (drop - (ref.eq - (ref.null eq) - (ref.null eq) - ) - ) - ) - - ;; CHECK: (func $hoist-LUB-danger (param $x i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (struct.get $B 1 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $C 1 - ;; CHECK-NEXT: (ref.null $C) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $hoist-LUB-danger (type $i32_=>_i32) (param $x i32) (result i32) - ;; NOMNL-NEXT: (if (result i32) - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (struct.get $B 1 - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $C 1 - ;; NOMNL-NEXT: (ref.null $C) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $hoist-LUB-danger (param $x i32) (result i32) - ;; In nominal typing, if we hoist the struct.get out of the if, then the if - ;; will have a new type, $A, but $A does not have field "1" which would be an - ;; error. We disallow subtyping for this reason. - ;; - ;; We also disallow subtyping in structural typing, even though atm there - ;; might not be a concrete risk there: future instructions might introduce - ;; such things, and it reduces the complexity of having differences with - ;; nominal typing. - (if (result i32) - (local.get $x) - (struct.get $B 1 - (ref.null $B) - ) - (struct.get $C 1 - (ref.null $C) - ) - ) - ) - - ;; CHECK: (func $incompatible-cast-of-non-null (param $struct (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $incompatible-cast-of-non-null (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $incompatible-cast-of-non-null (param $struct (ref $struct)) - (drop - (ref.cast - (local.get $struct) - (rtt.canon $array) - ) - ) - ) - - ;; CHECK: (func $incompatible-cast-of-null - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (block (result (ref null $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $incompatible-cast-of-null (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (block (result (ref null $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.null $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $incompatible-cast-of-null - (drop - (ref.cast - (ref.null $struct) - (rtt.canon $array) - ) - ) - (drop - (ref.cast - ;; The fallthrough is null, but the node's child's type is non-nullable, - ;; so we must add a ref.as_non_null on the outside to keep the type - ;; identical. - (ref.as_non_null - (ref.null $struct) - ) - (rtt.canon $array) - ) - ) - ) - - ;; CHECK: (func $incompatible-cast-of-unknown (param $struct (ref null $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $incompatible-cast-of-unknown (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $incompatible-cast-of-unknown (param $struct (ref null $struct)) - (drop - (ref.cast - (local.get $struct) - (rtt.canon $array) - ) - ) - ) - - ;; CHECK: (func $incompatible-test (param $struct (ref null $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $array) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $incompatible-test (type $ref?|$struct|_=>_none) (param $struct (ref null $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $array) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $incompatible-test (param $struct (ref null $struct)) - (drop - ;; This test will definitely fail, so we can turn it into 0. - (ref.test - (local.get $struct) - (rtt.canon $array) - ) - ) - ) - - ;; CHECK: (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test - ;; CHECK-NEXT: (local.get $A) - ;; CHECK-NEXT: (rtt.canon $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test - ;; CHECK-NEXT: (local.get $B) - ;; CHECK-NEXT: (rtt.canon $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $subtype-compatible (type $ref?|$A|_ref?|$B|_=>_none) (param $A (ref null $A)) (param $B (ref null $B)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test - ;; NOMNL-NEXT: (local.get $A) - ;; NOMNL-NEXT: (rtt.canon $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test - ;; NOMNL-NEXT: (local.get $B) - ;; NOMNL-NEXT: (rtt.canon $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $subtype-compatible (param $A (ref null $A)) (param $B (ref null $B)) - (drop - ;; B is a subtype of A, so this can work. - (ref.test - (local.get $A) - (rtt.canon $B) - ) - ) - (drop - ;; The other direction works too. - (ref.test - (local.get $B) - (rtt.canon $A) - ) - ) - ) - ;; CHECK: (func $ref.test-unreachable (param $A (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (rtt.canon $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref.test-unreachable (type $ref?|$A|_=>_none) (param $A (ref null $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: (rtt.canon $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref.test-unreachable (param $A (ref null $A)) - (drop - ;; We should ignore unreachable ref.tests and not try to compare their - ;; HeapTypes. - (ref.test - (unreachable) - (rtt.canon $A) - ) - ) - ) - - ;; CHECK: (func $consecutive-opts-with-unreachable (param $func funcref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (block (result dataref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $consecutive-opts-with-unreachable (type $funcref_=>_none) (param $func funcref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (block (result dataref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $consecutive-opts-with-unreachable (param $func funcref) - (drop - (ref.cast - ;; Casting a funcref to data will definitely fail, so this will be - ;; replaced with an unreachable. But it should be enclosed in a block of - ;; the previous type, so that the outside ref.cast is not confused. This - ;; is a regression test for a bug where we replace this node with an - ;; unreachable one, but we left refinalize til the end of all the other - ;; opts - and that meant that we got to our parent, the ref.cast, with - ;; one unreachable child but before it itself was refinalized, so its - ;; type was *not* unreachable yet, which meant it saw inconsistent IR - ;; that then led to an assertion. - (ref.as_data - (local.get $func) - ) - (rtt.canon $struct) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-null - ;; CHECK-NEXT: (local $a (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $B)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $a - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-null (type $none_=>_none) - ;; NOMNL-NEXT: (local $a (ref null $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $B)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.tee $a - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null $A) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-null - (local $a (ref null $A)) - ;; Casting nulls results in a null. - (drop - (ref.cast_static $A - (ref.null $A) - ) - ) - (drop - (ref.cast_static $A - (ref.null $B) - ) - ) - (drop - (ref.cast_static $B - (ref.null $A) - ) - ) - ;; A fallthrough works too. - (drop - (ref.cast_static $A - (local.tee $a - (ref.null $A) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-impossible (param $func (ref func)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-impossible (type $ref|func|_=>_none) (param $func (ref func)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-impossible (param $func (ref func)) - ;; A func cannot be cast to a struct, so this will trap. - (drop - (ref.cast_static $struct - (local.get $func) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-general (param $a (ref null $A)) (param $b (ref null $B)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $a - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-general (type $ref?|$A|_ref?|$B|_=>_none) (param $a (ref null $A)) (param $b (ref null $B)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $a) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $b) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B - ;; NOMNL-NEXT: (local.get $a) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.tee $a - ;; NOMNL-NEXT: (local.get $a) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-general (param $a (ref null $A)) (param $b (ref null $B)) - ;; In the general case, a static cast of something simply succeeds if the - ;; type is a subtype. - (drop - (ref.cast_static $A - (local.get $a) - ) - ) - (drop - (ref.cast_static $A - (local.get $b) - ) - ) - ;; This is the only one that we cannot know for sure will succeed. - (drop - (ref.cast_static $B - (local.get $a) - ) - ) - ;; A fallthrough works too. - (drop - (ref.cast_static $A - (local.tee $a - (local.get $a) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-squared (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $A - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-squared (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $A - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-squared (param $x eqref) - ;; Identical ref.casts can be folded together. - (drop - (ref.cast_static $A - (ref.cast_static $A - (local.get $x) - ) - ) - ) - ;; When subtypes exist, we only need the stricter one. - (drop - (ref.cast_static $A - (ref.cast_static $B - (local.get $x) - ) - ) - ) - (drop - (ref.cast_static $B - (ref.cast_static $A - (local.get $x) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-many (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-many (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-many (param $x eqref) - ;; We should optimize a long sequence of static casts when we can. All six - ;; orderings of these casts should collapse into the strictest one. - (drop - (ref.cast_static $A - (ref.cast_static $B - (ref.cast_static $B-child - (local.get $x) - ) - ) - ) - ) - (drop - (ref.cast_static $A - (ref.cast_static $B-child - (ref.cast_static $B - (local.get $x) - ) - ) - ) - ) - (drop - (ref.cast_static $B - (ref.cast_static $A - (ref.cast_static $B-child - (local.get $x) - ) - ) - ) - ) - (drop - (ref.cast_static $B - (ref.cast_static $B-child - (ref.cast_static $A - (local.get $x) - ) - ) - ) - ) - (drop - (ref.cast_static $B-child - (ref.cast_static $A - (ref.cast_static $B - (local.get $x) - ) - ) - ) - ) - (drop - (ref.cast_static $B-child - (ref.cast_static $B - (ref.cast_static $A - (local.get $x) - ) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-very-many (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-very-many (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-very-many (param $x eqref) - ;; We should optimize an arbitrarily-long long sequence of static casts. - (drop - (ref.cast_static $A - (ref.cast_static $B - (ref.cast_static $B-child - (ref.cast_static $A - (ref.cast_static $A - (ref.cast_static $B-child - (ref.cast_static $B-child - (ref.cast_static $B - (ref.cast_static $B - (ref.cast_static $B - (ref.cast_static $B-child - (ref.cast_static $A - (local.get $x) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-fallthrough-remaining (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref null $B)) - ;; CHECK-NEXT: (call $ref-cast-static-fallthrough-remaining - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.cast_static $B - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-fallthrough-remaining (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref null $B)) - ;; NOMNL-NEXT: (call $ref-cast-static-fallthrough-remaining - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.cast_static $B - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-fallthrough-remaining (param $x eqref) - (drop - (ref.cast_static $A - (block (result (ref null $B)) - ;; Additional contents in between redundant casts must be preserved. - ;; That is, when we see that the casts are redundant, by seeing that - ;; the fallthrough value reaching the outer cast is already cast, we - ;; can avoid a duplicate cast, but we do still need to keep any code - ;; in the middle, as it may have side effects. - ;; - ;; In this first testcase, the outer cast is not needed as the inside - ;; is already a more specific type. - (call $ref-cast-static-fallthrough-remaining - (local.get $x) - ) - (ref.cast_static $B - (local.get $x) - ) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-fallthrough-remaining-child (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $B - ;; CHECK-NEXT: (block (result eqref) - ;; CHECK-NEXT: (call $ref-cast-static-fallthrough-remaining-child - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.cast_static $A - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-fallthrough-remaining-child (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $B - ;; NOMNL-NEXT: (block (result eqref) - ;; NOMNL-NEXT: (call $ref-cast-static-fallthrough-remaining-child - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.cast_static $A - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-fallthrough-remaining-child (param $x eqref) - (drop - ;; As above, but with $A and $B flipped. Now the inner cast is not needed. - ;; However, we do not remove it, as it may be necessary for validation, - ;; and we hope other opts help out here. - (ref.cast_static $B - (block (result (eqref)) - (call $ref-cast-static-fallthrough-remaining-child - (local.get $x) - ) - (ref.cast_static $A - (local.get $x) - ) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-fallthrough-remaining-impossible (param $x (ref eq)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref eq)) - ;; CHECK-NEXT: (call $ref-cast-static-fallthrough-remaining-impossible - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.cast_static $struct - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-fallthrough-remaining-impossible (type $ref|eq|_=>_none) (param $x (ref eq)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref eq)) - ;; NOMNL-NEXT: (call $ref-cast-static-fallthrough-remaining-impossible - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.cast_static $struct - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-fallthrough-remaining-impossible (param $x (ref eq)) - (drop - ;; As above, but with an impossible cast of an array to a struct. The - ;; block with the side effects and the inner cast must be kept around and - ;; dropped, and then we replace the outer cast with an unreachable. - (ref.cast_static $array - (block (result (ref eq)) - (call $ref-cast-static-fallthrough-remaining-impossible - (local.get $x) - ) - (ref.cast_static $struct - (local.get $x) - ) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-fallthrough-remaining-nonnull (param $x (ref eq)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $A - ;; CHECK-NEXT: (block (result (ref eq)) - ;; CHECK-NEXT: (call $ref-cast-static-fallthrough-remaining - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.cast_static $B - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-fallthrough-remaining-nonnull (type $ref|eq|_=>_none) (param $x (ref eq)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $A - ;; NOMNL-NEXT: (block (result (ref eq)) - ;; NOMNL-NEXT: (call $ref-cast-static-fallthrough-remaining - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.cast_static $B - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-fallthrough-remaining-nonnull (param $x (ref eq)) - ;; The input is non-nullable here, and the middle block is of a simpler - ;; type than either the parent or the child. This checks that we do not - ;; mis-optimize this case: In general the outer cast is not needed, but - ;; the middle block prevents us from seeing that (after other opts run, - ;; however, we would). - (drop - (ref.cast_static $A - (block (result (ref eq)) - (call $ref-cast-static-fallthrough-remaining - (local.get $x) - ) - (ref.cast_static $B - (local.get $x) - ) - ) - ) - ) - ) - - ;; CHECK: (func $ref-cast-static-squared-impossible (param $x eqref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast_static $struct - ;; CHECK-NEXT: (ref.cast_static $array - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.cast_static $array - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-cast-static-squared-impossible (type $eqref_=>_none) (param $x eqref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast_static $struct - ;; NOMNL-NEXT: (ref.cast_static $array - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result (ref $struct)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (ref.cast_static $array - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-cast-static-squared-impossible (param $x eqref) - ;; Impossible casts will trap unless the input is null. - (drop - (ref.cast_static $struct - (ref.cast_static $array - (local.get $x) - ) - ) - ) - (drop - (ref.cast_static $struct - (ref.cast_static $array - (ref.as_non_null (local.get $x)) - ) - ) - ) - ) - - ;; CHECK: (func $ref-test-static-same-type (param $nullable (ref null $A)) (param $non-nullable (ref $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test_static $A - ;; CHECK-NEXT: (local.get $nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $non-nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-test-static-same-type (type $ref?|$A|_ref|$A|_=>_none) (param $nullable (ref null $A)) (param $non-nullable (ref $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test_static $A - ;; NOMNL-NEXT: (local.get $nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $non-nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-test-static-same-type (param $nullable (ref null $A)) (param $non-nullable (ref $A)) - ;; A nullable value cannot be optimized here even though it is the same - ;; type. - (drop - (ref.test_static $A - (local.get $nullable) - ) - ) - ;; But if it is non-nullable, it must succeed. - (drop - (ref.test_static $A - (local.get $non-nullable) - ) - ) - ) - - ;; CHECK: (func $ref-test-static-subtype (param $nullable (ref null $B)) (param $non-nullable (ref $B)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test_static $A - ;; CHECK-NEXT: (local.get $nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $non-nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-test-static-subtype (type $ref?|$B|_ref|$B|_=>_none) (param $nullable (ref null $B)) (param $non-nullable (ref $B)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test_static $A - ;; NOMNL-NEXT: (local.get $nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $non-nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-test-static-subtype (param $nullable (ref null $B)) (param $non-nullable (ref $B)) - ;; As above, but the input is a subtype, so the same things happen. - (drop - (ref.test_static $A - (local.get $nullable) - ) - ) - (drop - (ref.test_static $A - (local.get $non-nullable) - ) - ) - ) - - ;; CHECK: (func $ref-test-static-supertype (param $nullable (ref null $A)) (param $non-nullable (ref $A)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test_static $B - ;; CHECK-NEXT: (local.get $nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.test_static $B - ;; CHECK-NEXT: (local.get $non-nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-test-static-supertype (type $ref?|$A|_ref|$A|_=>_none) (param $nullable (ref null $A)) (param $non-nullable (ref $A)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test_static $B - ;; NOMNL-NEXT: (local.get $nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.test_static $B - ;; NOMNL-NEXT: (local.get $non-nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-test-static-supertype (param $nullable (ref null $A)) (param $non-nullable (ref $A)) - ;; As above, but the input is a supertype. We can't know at compile time - ;; what to do here. - (drop - (ref.test_static $B - (local.get $nullable) - ) - ) - (drop - (ref.test_static $B - (local.get $non-nullable) - ) - ) - ) - - ;; CHECK: (func $ref-test-static-impossible (param $nullable (ref null $array)) (param $non-nullable (ref $array)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $non-nullable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-test-static-impossible (type $ref?|$array|_ref|$array|_=>_none) (param $nullable (ref null $array)) (param $non-nullable (ref $array)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block (result i32) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (local.get $non-nullable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-test-static-impossible (param $nullable (ref null $array)) (param $non-nullable (ref $array)) - ;; Testing an impossible cast will definitely fail. - (drop - (ref.test_static $struct - (local.get $nullable) - ) - ) - (drop - (ref.test_static $struct - (local.get $non-nullable) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-ignore-traps.wast binaryen-99/test/lit/passes/optimize-instructions-ignore-traps.wast --- binaryen-108/test/lit/passes/optimize-instructions-ignore-traps.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-ignore-traps.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,800 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --all-features --optimize-instructions --optimize-level=2 --ignore-implicit-traps -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (type $0 (func (param i32 i32) (result i32))) - (type $0 (func (param i32 i32) (result i32))) - ;; CHECK: (memory $0 0) - (memory $0 0) - ;; CHECK: (func $conditionals (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in6 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in6 - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 27000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $conditionals (type $0) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local.set $0 - (i32.const 0) - ) - (loop $while-in - (local.set $3 - (i32.const 0) - ) - (loop $while-in6 - (local.set $6 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (local.set $0 - (if (result i32) - (i32.or ;; this or is very expensive. we should compute one side, then see if we even need the other - (i32.eqz - (i32.rem_s - (i32.add - (i32.mul - (local.tee $7 ;; side effect, so we can't do this one - (i32.add - (local.get $0) - (i32.const 2) - ) - ) - (local.get $0) - ) - (i32.const 17) - ) - (i32.const 5) - ) - ) - (i32.eqz - (i32.rem_u - (i32.add - (i32.mul - (local.get $0) - (local.get $0) - ) - (i32.const 11) - ) - (i32.const 3) - ) - ) - ) - (local.get $7) - (local.get $6) - ) - ) - (br_if $while-in6 - (i32.lt_s - (local.tee $3 - (i32.add - (local.get $3) - (i32.const 1) - ) - ) - (local.get $4) - ) - ) - ) - (br_if $while-in - (i32.ne - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (i32.const 27000) - ) - ) - ) - (return - (local.get $5) - ) - ) - ;; CHECK: (func $side-effect (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in6 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in6 - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 27000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effect (type $0) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local.set $0 - (i32.const 0) - ) - (loop $while-in - (local.set $3 - (i32.const 0) - ) - (loop $while-in6 - (local.set $6 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (local.set $0 - (if (result i32) - (i32.or ;; this or is very expensive, but has a side effect on both sides - (i32.eqz - (i32.rem_s - (i32.add - (i32.mul - (local.tee $7 - (i32.add - (local.get $0) - (i32.const 0) - ) - ) - (local.get $0) - ) - (i32.const 17) - ) - (i32.const 5) - ) - ) - (i32.eqz - (i32.rem_u - (i32.add - (i32.mul - (local.get $0) - (local.get $0) - ) - (unreachable) - ) - (i32.const 3) - ) - ) - ) - (local.get $7) - (local.get $6) - ) - ) - (br_if $while-in6 - (i32.lt_s - (local.tee $3 - (i32.add - (local.get $3) - (i32.const 1) - ) - ) - (local.get $4) - ) - ) - ) - (br_if $while-in - (i32.ne - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (i32.const 27000) - ) - ) - ) - (return - (local.get $5) - ) - ) - ;; CHECK: (func $flip (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (local $2 i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (local $4 i32) - ;; CHECK-NEXT: (local $5 i32) - ;; CHECK-NEXT: (local $6 i32) - ;; CHECK-NEXT: (local $7 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in6 - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in6 - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $4) - ;; CHECK-NEXT: (local.tee $3 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 27000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $flip (type $0) (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local.set $0 - (i32.const 0) - ) - (loop $while-in - (local.set $3 - (i32.const 0) - ) - (loop $while-in6 - (local.set $6 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (local.set $0 - (if (result i32) - (i32.or ;; this or is very expensive, and the first side has no side effect - (i32.eqz - (i32.rem_s - (i32.add - (i32.mul - (i32.eqz - (i32.add - (local.get $0) - (i32.const 0) - ) - ) - (local.get $0) - ) - (i32.const 17) - ) - (i32.const 5) - ) - ) - (i32.eqz - (i32.rem_u - (i32.add - (i32.mul - (local.get $0) - (local.get $0) - ) - (i32.const 100) - ) - (i32.const 3) - ) - ) - ) - (local.get $7) - (local.get $6) - ) - ) - (br_if $while-in6 - (i32.lt_s - (local.tee $3 - (i32.add - (local.get $3) - (i32.const 1) - ) - ) - (local.get $4) - ) - ) - ) - (br_if $while-in - (i32.ne - (local.tee $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (i32.const 27000) - ) - ) - ) - (return - (local.get $5) - ) - ) - ;; CHECK: (func $invalidate-conditionalizeExpensiveOnBitwise (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $invalidate-conditionalizeExpensiveOnBitwise (param $0 i32) (param $1 i32) (result i32) - (if - (i32.eqz - (i32.and - (i32.lt_s - (i32.and - (i32.shr_s - (i32.shl - (i32.add - (local.get $1) ;; conflict with tee - (i32.const -1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 255) - ) - (i32.const 3) - ) - (i32.ne - (local.tee $1 - (i32.const 0) - ) - (i32.const 0) - ) - ) - ) - (return (local.get $0)) - ) - (return (local.get $1)) - ) - ;; CHECK: (func $invalidate-conditionalizeExpensiveOnBitwise-ok (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $invalidate-conditionalizeExpensiveOnBitwise-ok (param $0 i32) (param $1 i32) (result i32) - (if - (i32.eqz - (i32.and - (i32.lt_s - (i32.and - (i32.shr_s - (i32.shl - (i32.add - (local.get $0) ;; no conflict - (i32.const -1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 255) - ) - (i32.const 3) - ) - (i32.ne - (local.tee $1 - (i32.const 0) - ) - (i32.const 0) - ) - ) - ) - (return (local.get $0)) - ) - (return (local.get $1)) - ) - - ;; CHECK: (func $conditionalize-if-type-change (result f64) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (loop $label$1 (result f32) - ;; CHECK-NEXT: (block $label$2 (result f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $label$3 (result f32) - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (f32.gt - ;; CHECK-NEXT: (br_if $label$3 - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$2 - ;; CHECK-NEXT: (f32.const 71) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i64.const 58) - ;; CHECK-NEXT: (i64.const -982757) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const -nan:0xfffffffffffff) - ;; CHECK-NEXT: ) - (func $conditionalize-if-type-change (result f64) - (local $0 i32) - (drop - (loop $label$1 (result f32) - (block $label$2 (result f32) - (drop - (block $label$3 (result f32) - (br_if $label$1 - (i32.or ;; this turns into an if, but then the if might not be unreachable - (f32.gt - (br_if $label$3 - (f32.const 1) - (local.get $0) - ) - (br $label$2 - (f32.const 71) - ) - ) - (i64.eqz - (select - (i64.const 58) - (i64.const -982757) - (i64.eqz - (i64.const 0) - ) - ) - ) - ) - ) - ) - ) - (f32.const 1) - ) - ) - ) - (f64.const -nan:0xfffffffffffff) - ) - ;; CHECK: (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $sz) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $src) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) - (memory.copy ;; nop - (local.get $dst) - (local.get $dst) - (local.get $sz) - ) - - (memory.copy ;; nop - (local.get $dst) - (local.get $src) - (i32.const 0) - ) - ) - - ;; CHECK: (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $dst) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $val) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (memory.fill - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $sz) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-bulk-memory-fill (param $dst i32) (param $val i32) (param $sz i32) - (memory.fill ;; drops - (local.get $dst) - (i32.const 0) - (i32.const 0) - ) - - (memory.fill ;; drops - (local.get $dst) - (local.get $val) - (i32.const 0) - ) - - (memory.fill ;; skip - (i32.const 0) - (i32.const 0) - (local.get $sz) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-iit-eh.wast binaryen-99/test/lit/passes/optimize-instructions-iit-eh.wast --- binaryen-108/test/lit/passes/optimize-instructions-iit-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-iit-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --ignore-implicit-traps --optimize-instructions -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (type $struct.A (struct (field i32))) - (type $struct.A (struct i32)) - ;; CHECK: (global $g-struct.A (rtt $struct.A) (rtt.canon $struct.A)) - - ;; CHECK: (tag $e (param (ref null $struct.A))) - (tag $e (param (ref null $struct.A))) - (global $g-struct.A (rtt $struct.A) (rtt.canon $struct.A)) - - ;; CHECK: (func $ref-cast-statically-removed - ;; CHECK-NEXT: (local $0 (ref null $struct.A)) - ;; CHECK-NEXT: (local $1 (ref null $struct.A)) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop (ref null $struct.A)) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (block (result (ref null $struct.A)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $g-struct.A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref-cast-statically-removed - (try - (do) - (catch $e - (throw $e - ;; Because --ignore-implicit-traps is given, this ref.cast is assumed - ;; not to throw so this ref.cast can be statically removed. But that - ;; creates a block around this, making 'pop' nested into it, which is - ;; invalid. We fix this up at the end up OptimizeInstruction, - ;; assigning the 'pop' to a local at the start of this 'catch' body - ;; and later using 'local.get' to get it. - (ref.cast - (pop (ref null $struct.A)) - (global.get $g-struct.A) - ) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-multivalue.wast binaryen-99/test/lit/passes/optimize-instructions-multivalue.wast --- binaryen-108/test/lit/passes/optimize-instructions-multivalue.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-multivalue.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-multivalue -S -o - | filecheck %s - -(module - ;; CHECK: (func $if-identical-arms-tuple (param $x i32) (result i32) - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (if (result i32 i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-identical-arms-tuple (param $x i32) (result i32) - (if (result i32) - (local.get $x) - ;; The tuple.extract can be hoisted out. - (tuple.extract 0 - (tuple.make - (i32.const 0) - (i32.const 1) - ) - ) - (tuple.extract 0 - (tuple.make - (i32.const 2) - (i32.const 3) - ) - ) - ) - ) - ;; CHECK: (func $select-identical-arms-tuple (param $x i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-identical-arms-tuple (param $x i32) (result i32) - (select - ;; The tuple.extract cannot be hoisted out, as the spec disallows a - ;; select with multiple values in its arms. - (tuple.extract 0 - (tuple.make - (i32.const 0) - (i32.const 1) - ) - ) - (tuple.extract 0 - (tuple.make - (i32.const 2) - (i32.const 3) - ) - ) - (local.get $x) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-sign-ext.wast binaryen-99/test/lit/passes/optimize-instructions-sign-ext.wast --- binaryen-108/test/lit/passes/optimize-instructions-sign-ext.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-sign-ext.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-sign-ext -S -o - | filecheck %s - -(module - ;; CHECK: (func $duplicate-elimination (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.extend8_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.extend16_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $duplicate-elimination (param $x i32) - (drop (i32.extend8_s (i32.extend8_s (local.get $x)))) - (drop (i32.extend16_s (i32.extend16_s (local.get $x)))) - ) - - ;; i64(x) << 56 >> 56 ==> i64.extend8_s(x) - ;; i64(x) << 48 >> 48 ==> i64.extend16_s(x) - ;; i64(x) << 32 >> 32 ==> i64.extend32_s(x) - ;; i64.extend_i32_s(i32.wrap_i64(x)) ==> i64.extend32_s(x) - - ;; CHECK: (func $i64-sign-extentions (param $x i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend8_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend16_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend32_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shr_s - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend32_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $i64-sign-extentions (param $x i64) - (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 56)) (i64.const 56))) - (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 48)) (i64.const 48))) - (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 32)) (i64.const 32))) - (drop (i64.shr_s (i64.shl (local.get $x) (i64.const 16)) (i64.const 16))) ;; skip - (drop (i64.extend_i32_s (i32.wrap_i64 (local.get $x)))) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions-typed-function-references.wast binaryen-99/test/lit/passes/optimize-instructions-typed-function-references.wast --- binaryen-108/test/lit/passes/optimize-instructions-typed-function-references.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions-typed-function-references.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --enable-reference-types \ -;; RUN: --enable-typed-function-references -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32-i32 (func (param i32) (result i32))) - (type $i32-i32 (func (param i32) (result i32))) - ;; this function has a reference parameter. we analyze parameters, and should - ;; not be confused by a type that has no bit size, in particular. this test - ;; just verifies that we do not crash on that. - ;; CHECK: (func $call_from-param (param $f (ref null $i32-i32)) (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $call_from-param (param $f (ref null $i32-i32)) (result i32) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/passes/optimize-instructions.wast binaryen-99/test/lit/passes/optimize-instructions.wast --- binaryen-108/test/lit/passes/optimize-instructions.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/optimize-instructions.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,13874 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions -S -o - | filecheck %s - -(module - (memory 0) - ;; CHECK: (type $0 (func (param i32 i64))) - (type $0 (func (param i32 i64))) - ;; CHECK: (func $and-and (param $i1 i32) (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-and (param $i1 i32) (result i32) - (i32.and - (i32.and - (local.get $i1) - (i32.const 5) - ) - (i32.const 3) - ) - ) - ;; CHECK: (func $or-or (param $i1 i32) (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $or-or (param $i1 i32) (result i32) - (i32.or - (i32.or - (local.get $i1) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ;; CHECK: (func $xor-xor (param $i1 i32) (result i32) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $xor-xor (param $i1 i32) (result i32) - (i32.xor - (i32.xor - (local.get $i1) - (i32.const -2) - ) - (i32.const -5) - ) - ) - ;; CHECK: (func $mul-mul (param $i1 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: (i32.const -10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $mul-mul (param $i1 i32) (result i32) - (i32.mul - (i32.mul - (local.get $i1) - (i32.const -2) - ) - (i32.const 5) - ) - ) - ;; overflow also valid - ;; CHECK: (func $mul-mul-overflow (param $i1 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: (i32.const -133169153) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $mul-mul-overflow (param $i1 i32) (result i32) - (i32.mul - (i32.mul - (local.get $i1) - (i32.const 0xfffff) - ) - (i32.const 0x8000001) - ) - ) - ;; CHECK: (func $if-eqz-one-arm (param $i1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-eqz-one-arm (param $i1 i32) - (if - (i32.eqz - (local.get $i1) - ) - (drop - (i32.const 10) - ) - ) - ) - ;; CHECK: (func $if-eqz-two-arms (param $i1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-eqz-two-arms (param $i1 i32) - (if - (i32.eqz - (local.get $i1) - ) - (drop - (i32.const 11) - ) - (drop - (i32.const 12) - ) - ) - ) - ;; CHECK: (func $if-eqz-two-arms-i64 (param $i2 i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $i2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-eqz-two-arms-i64 (param $i2 i64) - (if - (i64.eqz - (local.get $i2) - ) - (drop - (i32.const 11) - ) - (drop - (i32.const 12) - ) - ) - ) - ;; CHECK: (func $eqz-gt_s (result i32) - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-gt_s (result i32) - (i32.eqz - (i32.gt_s - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-ge_s (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-ge_s (result i32) - (i32.eqz - (i32.ge_s - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-lt_s (result i32) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-lt_s (result i32) - (i32.eqz - (i32.lt_s - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-le_s (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-le_s (result i32) - (i32.eqz - (i32.le_s - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-gt_u (result i32) - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-gt_u (result i32) - (i32.eqz - (i32.gt_u - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-ge_u (result i32) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-ge_u (result i32) - (i32.eqz - (i32.ge_u - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-lt_u (result i32) - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-lt_u (result i32) - (i32.eqz - (i32.lt_u - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-le_u (result i32) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-le_u (result i32) - (i32.eqz - (i32.le_u - (i32.const 1) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-gt (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f32.gt - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-gt (result i32) - (i32.eqz - (f32.gt - (f32.const 1) - (f32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-ge (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f32.ge - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-ge (result i32) - (i32.eqz - (f32.ge - (f32.const 1) - (f32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-lt (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f32.lt - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-lt (result i32) - (i32.eqz - (f32.lt - (f32.const 1) - (f32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-le (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f32.le - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-le (result i32) - (i32.eqz - (f32.le - (f32.const 1) - (f32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-gt-f64 (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f64.gt - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-gt-f64 (result i32) - (i32.eqz - (f64.gt - (f64.const 1) - (f64.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-ge-f64 (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f64.ge - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-ge-f64 (result i32) - (i32.eqz - (f64.ge - (f64.const 1) - (f64.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-lt-f64 (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f64.lt - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-lt-f64 (result i32) - (i32.eqz - (f64.lt - (f64.const 1) - (f64.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-le-f64 (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (f64.le - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-le-f64 (result i32) - (i32.eqz - (f64.le - (f64.const 1) - (f64.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-eq (result i32) - ;; CHECK-NEXT: (f32.ne - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-eq (result i32) - (i32.eqz - (f32.eq - (f32.const 1) - (f32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-ne (result i32) - ;; CHECK-NEXT: (f32.eq - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-ne (result i32) - (i32.eqz - (f32.ne - (f32.const 1) - (f32.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-eq-f64 (result i32) - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-eq-f64 (result i32) - (i32.eqz - (f64.eq - (f64.const 1) - (f64.const 2) - ) - ) - ) - ;; CHECK: (func $eqz-ne-f64 (result i32) - ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eqz-ne-f64 (result i32) - (i32.eqz - (f64.ne - (f64.const 1) - (f64.const 2) - ) - ) - ) - - ;; we handle only 0 in the right position, as we assume a const is there, and - ;; don't care about whether both are consts here (precompute does that, so no - ;; need) - ;; CHECK: (func $eq-zero-rhs (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-zero-rhs (result i32) - (i32.eq - (i32.const 100) - (i32.const 0) - ) - ) - ;; CHECK: (func $eq-zero-lhs (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-zero-lhs (result i32) - (i32.eq - (i32.const 0) - (i32.const 100) - ) - ) - ;; CHECK: (func $eq-zero-zero (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-zero-zero (result i32) - (i32.eq - (i32.const 0) - (i32.const 0) - ) - ) - ;; CHECK: (func $eq-zero-rhs-i64 (result i32) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-zero-rhs-i64 (result i32) - (i64.eq - (i64.const 100) - (i64.const 0) - ) - ) - ;; CHECK: (func $eq-zero-lhs-i64 (result i32) - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-zero-lhs-i64 (result i32) - (i64.eq - (i64.const 0) - (i64.const 100) - ) - ) - ;; CHECK: (func $eq-zero-zero-i64 (result i32) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-zero-zero-i64 (result i32) - (i64.eq - (i64.const 0) - (i64.const 0) - ) - ) - ;; CHECK: (func $if-eqz-eqz - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-eqz-eqz - (if - (i32.eqz - (i32.eqz - (i32.const 123) - ) - ) - (nop) - ) - ) - ;; CHECK: (func $select-eqz (param $i1 i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 102) - ;; CHECK-NEXT: (i32.const 101) - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-eqz (param $i1 i32) (result i32) - (select - (i32.const 101) - (i32.const 102) - (i32.eqz - (local.get $i1) - ) - ) - ) - ;; CHECK: (func $select-eqz-noreorder (param $i1 i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $i1 - ;; CHECK-NEXT: (i32.const 103) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $i1 - ;; CHECK-NEXT: (i32.const 104) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $i1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-eqz-noreorder (param $i1 i32) (result i32) - (select - (local.tee $i1 - (i32.const 103) - ) ;; these conflict - (local.tee $i1 - (i32.const 104) - ) - (i32.eqz - (local.get $i1) - ) - ) - ) - ;; CHECK: (func $select-eqz-eqz (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $select-eqz-eqz (result i32) - (select - (i32.const 0) - (i32.const 1) - (i32.eqz - (i32.eqz - (i32.const 2) - ) - ) - ) - ) - ;; CHECK: (func $select-sign-32-lt (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-sign-32-lt (param $x i32) (result i32) - (select - (i32.const -1) - (i32.const 1) - (i32.lt_s - (local.get $x) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $select-sign-32-ge (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-sign-32-ge (param $x i32) (result i32) - (select - (i32.const 1) - (i32.const -1) - (i32.ge_s - (local.get $x) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $select-sign-64-lt (param $x i64) (result i64) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.shr_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-sign-64-lt (param $x i64) (result i64) - (select - (i64.const -1) - (i64.const 1) - (i64.lt_s - (local.get $x) - (i64.const 0) - ) - ) - ) - ;; CHECK: (func $select-sign-64-ge (param $x i64) (result i64) - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (i64.shr_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-sign-64-ge (param $x i64) (result i64) - (select - (i64.const 1) - (i64.const -1) - (i64.ge_s - (local.get $x) - (i64.const 0) - ) - ) - ) - ;; CHECK: (func $select-sign-lt-skip-1 (param $x i32) (result i64) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-sign-lt-skip-1 (param $x i32) (result i64) - (select - (i64.const -1) - (i64.const 1) - (i32.lt_s - (local.get $x) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $select-sign-lt-skip-2 (param $x i64) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-sign-lt-skip-2 (param $x i64) (result i32) - (select - (i32.const -1) - (i32.const 1) - (i64.lt_s - (local.get $x) - (i64.const 0) - ) - ) - ) - ;; CHECK: (func $select-or (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-or (param $x i32) (param $y i32) (result i32) - (select - (i32.const 1) - (i32.eq - (local.get $y) - (i32.const 1337) - ) - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $select-or-side-effects (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (call $select-or-side-effects - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (call $select-or-side-effects - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-or-side-effects (param $x i32) (param $y i32) (result i32) - ;; When there are side effects, the order of the operations must remain - ;; correct. - (select - (i32.const 1) - (i32.eq - (call $select-or-side-effects - (local.get $x) - (local.get $y) - ) - (i32.const 1337) - ) - (i32.and - (call $select-or-side-effects - (local.get $y) - (local.get $x) - ) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $select-or-no-bits (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-or-no-bits (param $x i32) (param $y i32) - ;; The following cannot be optimized into an "or" operation due to maxBits - ;; not being known to be 1. - (drop - (select - ;; Too many bits in ifTrue - (i32.const 2) - (i32.eq - (local.get $y) - (i32.const 1337) - ) - (i32.eq - (local.get $x) - (i32.const 42) - ) - ) - ) - (drop - (select - (i32.const 1) - ;; Too many bits in ifFalse - (local.get $y) - (i32.eq - (local.get $x) - (i32.const 42) - ) - ) - ) - (drop - (select - (i32.const 1) - (i32.eq - (local.get $y) - (i32.const 1337) - ) - ;; Too many bits in condition - (local.get $x) - ) - ) - ) - ;; CHECK: (func $select-or-no-type (param $x i32) (param $y i64) (result i64) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-or-no-type (param $x i32) (param $y i64) (result i64) - ;; An i64 result cannot be optimized into an "or" of the ifTrue and the - ;; condition due to their types being different. - (select - (i64.const 1) - (i64.and - (local.get $y) - (i64.const 1) - ) - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $select-or-no-const (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-or-no-const (param $x i32) (param $y i32) (result i32) - (select - ;; The wrong const (should be 1). - (i32.const 0) - (i32.eq - (local.get $y) - (i32.const 1337) - ) - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $select-and (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-and (param $x i32) (param $y i32) (result i32) - (select - (i32.eq - (local.get $y) - (i32.const 1337) - ) - (i32.const 0) - (i32.eq - (local.get $x) - (i32.const 42) - ) - ) - ) - ;; CHECK: (func $select-and-no-const (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-and-no-const (param $x i32) (param $y i32) (result i32) - (select - (i32.eq - (local.get $y) - (i32.const 1337) - ) - ;; The wrong constant (should be 0). - (i32.const 1) - (i32.eq - (local.get $x) - (i32.const 42) - ) - ) - ) - ;; CHECK: (func $load8_s-and-255 (result i32) - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load8_s-and-255 (result i32) - (i32.and (i32.load8_s (i32.const 0)) (i32.const 255)) - ) - ;; CHECK: (func $load8_u-and-255 (result i32) - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load8_u-and-255 (result i32) - (i32.and (i32.load8_u (i32.const 1)) (i32.const 255)) - ) - ;; CHECK: (func $load8_s-and-254 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 254) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load8_s-and-254 (result i32) - (i32.and (i32.load8_s (i32.const 2)) (i32.const 254)) - ) - ;; CHECK: (func $load8_u-and-1 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load8_u-and-1 (result i32) - (i32.and (i32.load8_u (i32.const 3)) (i32.const 1)) - ) - ;; CHECK: (func $load16_s-and-65535 (result i32) - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load16_s-and-65535 (result i32) - (i32.and (i32.load16_s (i32.const 4)) (i32.const 65535)) - ) - ;; CHECK: (func $load16_u-and-65535 (result i32) - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load16_u-and-65535 (result i32) - (i32.and (i32.load16_u (i32.const 5)) (i32.const 65535)) - ) - ;; CHECK: (func $load16_s-and-65534 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 65534) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load16_s-and-65534 (result i32) - (i32.and (i32.load16_s (i32.const 6)) (i32.const 65534)) - ) - ;; CHECK: (func $load16_u-and-1 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load16_u-and-1 (result i32) - (i32.and (i32.load16_u (i32.const 7)) (i32.const 1)) - ) - ;; CHECK: (func $store8-and-255 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-and-255 - (i32.store8 (i32.const 8) (i32.and (i32.const -1) (i32.const 255))) - ) - ;; CHECK: (func $store8-and-254 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (i32.const 254) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-and-254 - (i32.store8 (i32.const 9) (i32.and (i32.const -2) (i32.const 254))) - ) - ;; CHECK: (func $store16-and-65535 - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const -3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-and-65535 - (i32.store16 (i32.const 10) (i32.and (i32.const -3) (i32.const 65535))) - ) - ;; CHECK: (func $store16-and-65534 - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: (i32.const 65534) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-and-65534 - (i32.store16 (i32.const 11) (i32.and (i32.const -4) (i32.const 65534))) - ) - ;; CHECK: (func $store8-wrap - ;; CHECK-NEXT: (i64.store8 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-wrap - (i32.store8 (i32.const 11) (i32.wrap_i64 (i64.const 1))) - ) - ;; CHECK: (func $store16-wrap - ;; CHECK-NEXT: (i64.store16 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-wrap - (i32.store16 (i32.const 11) (i32.wrap_i64 (i64.const 2))) - ) - ;; CHECK: (func $store-wrap - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-wrap - (i32.store (i32.const 11) (i32.wrap_i64 (i64.const 3))) - ) - ;; CHECK: (func $store8-neg1 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-neg1 - (i32.store8 (i32.const 7) (i32.const -1)) ;; 255 - ) - ;; CHECK: (func $store8-255 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-255 - (i32.store8 (i32.const 8) (i32.const 255)) - ) - ;; CHECK: (func $store8-256 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-256 - (i32.store8 (i32.const 9) (i32.const 256)) ;; 0 - ) - ;; CHECK: (func $store16-neg1 - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-neg1 - (i32.store16 (i32.const 13) (i32.const -1)) ;; 65535 - ) - ;; CHECK: (func $store16-65535 - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-65535 - (i32.store16 (i32.const 10) (i32.const 65535)) - ) - ;; CHECK: (func $store16-65536 - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-65536 - (i32.store16 (i32.const 11) (i32.const 65536)) ;; 0 - ) - ;; CHECK: (func $store-65536 - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i32.const 65536) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-65536 - (i32.store (i32.const 14) (i32.const 65536)) - ) - ;; CHECK: (func $store8-255-i64 - ;; CHECK-NEXT: (i64.store8 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i64.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-255-i64 - (i64.store8 (i32.const 8) (i64.const 255)) - ) - ;; CHECK: (func $store8-256-i64 - ;; CHECK-NEXT: (i64.store8 - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store8-256-i64 - (i64.store8 (i32.const 9) (i64.const 256)) ;; 0 - ) - ;; CHECK: (func $store16-65535-i64 - ;; CHECK-NEXT: (i64.store16 - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i64.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-65535-i64 - (i64.store16 (i32.const 10) (i64.const 65535)) - ) - ;; CHECK: (func $store16-65536-i64 - ;; CHECK-NEXT: (i64.store16 - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store16-65536-i64 - (i64.store16 (i32.const 11) (i64.const 65536)) ;; 0 - ) - ;; CHECK: (func $store32-4294967295 - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: (i64.const 4294967295) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store32-4294967295 - (i64.store32 (i32.const 12) (i64.const 4294967295)) - ) - ;; CHECK: (func $store32-4294967296 - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store32-4294967296 - (i64.store32 (i32.const 13) (i64.const 4294967296)) ;; 0 - ) - ;; CHECK: (func $store-4294967296 - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: (i64.const 4294967296) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-4294967296 - (i64.store (i32.const 14) (i64.const 4294967296)) - ) - ;; CHECK: (func $and-neg1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-neg1 - (drop (i32.and (i32.const 100) (i32.const -1))) - (drop (i32.and (i32.const 100) (i32.const 1))) - ) - ;; CHECK: (func $and-pos1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 1000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 1000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 2000) - ;; CHECK-NEXT: (i32.const 3000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-pos1 - (drop (i32.and (i32.eqz (i32.const 1000)) (i32.const 1))) - (drop (i32.and (i32.const 1) (i32.eqz (i32.const 1000)))) - (drop (i32.and (i32.const 100) (i32.const 1))) - (drop (i32.and (i32.lt_s (i32.const 2000) (i32.const 3000)) (i32.const 1))) - ) - ;; CHECK: (func $canonicalize-unreachable - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-unreachable - (drop (i32.and (unreachable) (i32.const 1))) ;; ok to reorder - (drop (i32.and (i32.const 1) (unreachable))) - (drop (i32.div_s (unreachable) (i32.const 1))) ;; not ok - (drop (i32.div_s (i32.const 1) (unreachable))) - ) - ;; CHECK: (func $canonicalize-consts-vars (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-consts-vars (param $x i32) (param $y i32) - (drop (i32.and (i32.const 1) (i32.const 2))) - (drop (i32.and (local.get $x) (i32.const 3))) - (drop (i32.and (i32.const 4) (local.get $x))) - (drop (i32.and (local.get $x) (local.get $y))) - (drop (i32.and (local.get $y) (local.get $x))) - (drop (i32.and (local.get $y) (local.tee $x (i32.const -4)))) - ) - ;; CHECK: (func $canonicalize-block-var (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (i32.const -5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block0 (result i32) - ;; CHECK-NEXT: (i32.const -6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-block-var (param $x i32) - (drop (i32.and - (block (result i32) - (i32.const -5) - ) - (local.get $x) - )) - (drop (i32.and - (local.get $x) - (block (result i32) - (i32.const -6) - ) - )) - ) - ;; CHECK: (func $canonicalize-block-loop - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop-in (result i32) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block2 (result i32) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop-in1 (result i32) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block4 (result i32) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop-in3 (result i32) - ;; CHECK-NEXT: (call $and-pos1) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block6 (result i32) - ;; CHECK-NEXT: (call $and-pos1) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop-in5 (result i32) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (loop $loop-in7 (result i32) - ;; CHECK-NEXT: (call $and-pos1) - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block8 (result i32) - ;; CHECK-NEXT: (call $and-pos1) - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (block $block9 (result i32) - ;; CHECK-NEXT: (call $and-pos1) - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop-in10 (result i32) - ;; CHECK-NEXT: (call $and-pos1) - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-block-loop - (drop (i32.and - (block (result i32) - (i32.const 5) - ) - (loop (result i32) - (i32.const 6) - ) - )) - (drop (i32.and - (loop (result i32) - (i32.const 7) - ) - (block (result i32) - (i32.const 8) - ) - )) - (drop (i32.and - (loop (result i32) - (call $and-pos1) - (i32.const 9) - ) - (block (result i32) - (i32.const 10) - ) - )) - (drop (i32.and - (loop (result i32) - (i32.const 11) - ) - (block (result i32) - (call $and-pos1) - (i32.const 12) - ) - )) - (drop (i32.and - (loop (result i32) - (call $and-pos1) - (i32.const 13) - ) - (block (result i32) - (call $and-pos1) - (i32.const 14) - ) - )) - (drop (i32.and - (block (result i32) - (call $and-pos1) - (i32.const 14) - ) - (loop (result i32) - (call $and-pos1) - (i32.const 13) - ) - )) - ) - ;; CHECK: (func $canonicalize-gt_s-gt-u - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 21) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-gt_s-gt-u - (drop (i32.and - (i32.gt_s - (i32.const 16) - (i32.const 17) - ) - (i32.gt_u - (i32.const 18) - (i32.const 19) - ) - )) - (drop (i32.and - (i32.gt_u - (i32.const 20) - (i32.const 21) - ) - (i32.gt_s - (i32.const 22) - (i32.const 23) - ) - )) - ) - ;; CHECK: (func $canonicalize-cmp-near-zero (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-cmp-near-zero (param $x i32) - ;; i32(x) > -1 ==> x >= 0 - (drop (i32.gt_s - (local.get $x) - (i32.const -1) - )) - ;; i32(x) <= -1 ==> x < 0 - (drop (i32.le_s - (local.get $x) - (i32.const -1) - )) - ;; -1 < i32(x) ==> x >= 0 - (drop (i32.lt_s - (i32.const -1) - (local.get $x) - )) - ;; -1 >= i32(x) ==> x < 0 - (drop (i32.ge_s - (i32.const -1) - (local.get $x) - )) - ;; i32(x) < 1 ==> x <= 0 - (drop (i32.lt_s - (local.get $x) - (i32.const 1) - )) - ;; (signed)x >= 1 ==> x > 0 - (drop (i32.ge_s - (local.get $x) - (i32.const 1) - )) - ;; u32(x) < 1 ==> x == 0 - (drop (i32.lt_u - (local.get $x) - (i32.const 1) - )) - ;; u32(x) >= 1 ==> x != 0 - (drop (i32.ge_u - (local.get $x) - (i32.const 1) - )) - ) - ;; CHECK: (func $canonicalize-cmp-const (param $x i32) (param $fx f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.gt - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f64.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.le - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f64.const inf) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.ge - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f64.const nan:0x8000000000000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.ge - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-cmp-const (param $x i32) (param $fx f64) - (drop (i32.gt_s - (i32.const 1) - (local.get $x) - )) - (drop (i32.gt_u - (i32.const 0) - (local.get $x) - )) - (drop (i32.ne - (i32.const -1) - (local.get $x) - )) - (drop (f64.ne - (f64.const -1) - (local.get $fx) - )) - (drop (f64.lt - (f64.const -2) - (local.get $fx) - )) - (drop (f64.ge - (f64.const inf) - (local.get $fx) - )) - (drop (f64.le - (f64.const nan) - (local.get $fx) - )) - ;; skip - (drop (f64.ge - (f64.const 1) - (f64.const 2) - )) - ) - ;; CHECK: (func $canonicalize-nested-vars (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-nested-vars (param $x i32) (param $y i32) - (drop (i32.add (i32.ctz (local.get $x)) (i32.ctz (local.get $y)))) - (drop (i32.add (i32.ctz (local.get $y)) (i32.ctz (local.get $x)))) - ) - ;; CHECK: (func $canonicalize-ctz-eqz (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.ctz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $canonicalize-ctz-eqz (param $x i32) (param $y i32) - (drop (i32.add (i32.ctz (local.get $x)) (i32.eqz (local.get $y)))) - (drop (i32.add (i32.eqz (local.get $x)) (i32.ctz (local.get $y)))) - ) - ;; CHECK: (func $ne0 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $ne0 (result i32) - (if (i32.ne (call $ne0) (i32.const 0)) - (nop) - ) - (if (i32.ne (i32.const 0) (call $ne0)) - (nop) - ) - ;; through an or - (if - (i32.or - (i32.ne (i32.const 0) (call $ne0)) - (i32.ne (i32.const 0) (call $ne0)) - ) - (nop) - ) - ;; but not an and - (if - (i32.and - (i32.ne (i32.const 0) (call $ne0)) - (i32.ne (i32.const 0) (call $ne0)) - ) - (nop) - ) - (i32.const 1) - ) - ;; CHECK: (func $recurse-bool - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (call $ne1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $recurse-bool - (if - (if (result i32) - (i32.const 1) - (i32.ne (call $ne0) (i32.const 0)) - (i32.ne (call $ne1) (i32.const 0)) - ) - (nop) - ) - (if - (block (result i32) - (nop) - (i32.ne (call $ne0) (i32.const 0)) - ) - (nop) - ) - ) - ;; CHECK: (func $ne1 (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $ne1 (result i32) - (unreachable) - ) - ;; CHECK: (func $store-off-2-add-consts (param $0 i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-off-2-add-consts (param $0 i32) - (i32.store offset=2 - (i32.add - (i32.const 1) - (i32.const 3) - ) - (local.get $0) - ) - (i32.store offset=2 - (i32.add - (i32.const 3) - (i32.const 1) - ) - (local.get $0) - ) - ) - ;; CHECK: (func $store-off-2-add-var-const (param $0 i32) - ;; CHECK-NEXT: (i32.store offset=2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-off-2-add-var-const (param $0 i32) - (i32.store offset=2 - (i32.add - (local.get $0) - (i32.const 5) - ) - (local.get $0) - ) - (i32.store offset=2 - (i32.add - (i32.const 7) - (local.get $0) - ) - (local.get $0) - ) - ) - ;; CHECK: (func $store-off-2-add-var-negative-const (param $0 i32) - ;; CHECK-NEXT: (i32.store offset=2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-off-2-add-var-negative-const (param $0 i32) - (i32.store offset=2 - (i32.add - (i32.const -11) ;; do not fold this! - (local.get $0) - ) - (local.get $0) - ) - (i32.store offset=2 - (i32.add - (local.get $0) - (i32.const -13) ;; do not fold this! - ) - (local.get $0) - ) - ) - ;; CHECK: (func $store-off-2-negative-const (param $0 i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=2 - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-off-2-negative-const (param $0 i32) - (i32.store offset=2 - (i32.add - (i32.const -15) - (i32.const 17) - ) - (local.get $0) - ) - (i32.store offset=2 - (i32.add - (i32.const -21) - (i32.const 19) - ) - (local.get $0) - ) - ) - ;; CHECK: (func $store-off-2-const (param $0 i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store offset=2 - ;; CHECK-NEXT: (i32.const -25) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-off-2-const (param $0 i32) - (i32.store offset=2 - (i32.const 23) - (local.get $0) - ) - (i32.store offset=2 - (i32.const -25) - (local.get $0) - ) - ) - ;; CHECK: (func $load-off-2 (param $0 i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load offset=2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load offset=2 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $load-off-2 (param $0 i32) (result i32) - (drop - (i32.load offset=2 - (i32.add - (i32.const 2) - (i32.const 4) - ) - ) - ) - (drop - (i32.load offset=2 - (i32.add - (i32.const 4) - (i32.const 2) - ) - ) - ) - (drop - (i32.load offset=2 - (i32.add - (local.get $0) - (i32.const 6) - ) - ) - ) - (drop - (i32.load offset=2 - (i32.const 8) - ) - ) - (i32.load offset=2 - (i32.add - (i32.const 10) - (local.get $0) - ) - ) - ) - ;; eq of sign-ext to const, can be a zext - ;; CHECK: (func $eq-sext-24-zero (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-24-zero (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $eq-sext-16-zero (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-16-zero (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 16) - ) - (i32.const 16) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $eq-sext-5-zero (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 134217727) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-5-zero (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 5) ;; weird size, but still valid - ) - (i32.const 5) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $eq-sext-24-const (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-24-const (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 100) ;; non-zero - ) - ) - ;; CHECK: (func $eq-sext-24-big-positive-const (param $0 i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $eq-sext-24-big-positive-const (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 32767) ;; non-zero and bigger than the mask, with sign bit - ) - ) - ;; CHECK: (func $eq-sext-24-negative-const (param $0 i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $eq-sext-24-negative-const (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const -149) ;; non-zero and bigger than the mask, without sign bit - ) - ) - ;; eq of two sign-ext, can both be a zext - ;; CHECK: (func $eq-sext-sext-24 (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-sext-24 (param $0 i32) (param $1 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ;; CHECK: (func $eq-sext-sext-16 (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 65535) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-sext-16 (param $0 i32) (param $1 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 16) - ) - (i32.const 16) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ) - ;; corner cases we should not opt - ;; CHECK: (func $eq-sext-smaller-shr (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-smaller-shr (param $0 i32) (result i32) - (i32.eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 23) ;; different shift, smaller - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $eq-sext-unsigned-shr (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eq-sext-unsigned-shr (param $0 i32) (result i32) - (i32.eq - (i32.shr_u ;; unsigned - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $lt_s-sext-zero (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $lt_s-sext-zero (param $0 i32) (result i32) - (i32.lt_s ;; non-eq - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $if-sext-unreachable (param $0 i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: (i32.const 222) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-sext-unreachable (param $0 i32) (result i32) - (if (result i32) - (i32.shr_s - (i32.shl - (unreachable) ;; ignore an unreachable value - (i32.const 16) - ) - (i32.const 16) - ) - (i32.const 111) - (i32.const 222) - ) - ) - ;; CHECK: (func $sext-24-100 (result i32) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - (func $sext-24-100 (result i32) - (i32.shr_s - (i32.shl - (i32.const 100) ;; small! - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-127 (result i32) - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - (func $sext-24-127 (result i32) - (i32.shr_s - (i32.shl - (i32.const 127) ;; just small enough - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-128 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-128 (result i32) - (i32.shr_s - (i32.shl - (i32.const 128) ;; just too big - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-var (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-var (param $0 i32) (result i32) - (i32.shr_s - (i32.shl - (local.get $0) ;; who knows... - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-unreachable (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-unreachable (result i32) - (i32.shr_s - (i32.shl - (unreachable) ;; ignore - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-div (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-div (result i32) - (i32.shr_s - (i32.shl - (i32.div_s ;; this could be optimizable in theory, but currently we don't look into adds etc. - (i32.const 1) - (i32.const 2) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-and-127-128 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-and-127-128 (result i32) - (i32.shr_s - (i32.shl - (i32.and ;; takes the min, here it is ok - (i32.const 127) - (i32.const 128) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-and-128-129 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: (i32.const 129) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-and-128-129 (result i32) - (i32.shr_s - (i32.shl - (i32.and ;; takes the min, here it is not - (i32.const 128) - (i32.const 129) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-xor-127-126 (result i32) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: (i32.const 126) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-xor-127-126 (result i32) - (i32.shr_s - (i32.shl - (i32.xor ;; takes the max, here it is ok - (i32.const 127) - (i32.const 126) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-xor-127-128 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-xor-127-128 (result i32) - (i32.shr_s - (i32.shl - (i32.xor ;; takes the max, here it is not - (i32.const 127) - (i32.const 128) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-or-127-126 (result i32) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: (i32.const 126) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-or-127-126 (result i32) - (i32.shr_s - (i32.shl - (i32.or ;; takes the max, here it is ok - (i32.const 127) - (i32.const 126) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-or-127-128 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-or-127-128 (result i32) - (i32.shr_s - (i32.shl - (i32.or ;; takes the max, here it is not - (i32.const 127) - (i32.const 128) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-32-2 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-32-2 (result i32) - (i32.shr_s - (i32.shl - (i32.shl ;; adds, here it is too much - (i32.const 32) - (i32.const 2) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-32-1 (result i32) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-32-1 (result i32) - (i32.shr_s - (i32.shl - (i32.shl ;; adds, here it is ok - (i32.const 32) - (i32.const 1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-32-35 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-32-35 (result i32) - (i32.shr_s - (i32.shl - (i32.shl ;; adds, here it is too much and "overflows" - (i32.const 32) - (i32.const 35) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-256-1 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-256-1 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u ;; subtracts, here it is still too much - (i32.const 256) - (i32.const 1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-256-2 (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-256-2 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u ;; subtracts, here it is ok - (i32.const 256) - (i32.const 2) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-128-35 (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-128-35 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u ;; subtracts, here it "overflows" - (i32.const 128) - (i32.const 35) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_s-256-1 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_s-256-1 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_s ;; subtracts, here it is still too much - (i32.const 256) - (i32.const 1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_s-256-2 (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_s-256-2 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_s ;; subtracts, here it is ok - (i32.const 256) - (i32.const 2) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_s-128-35 (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_s-128-35 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_s ;; subtracts, here it "overflows" - (i32.const 128) - (i32.const 35) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_s-neg1-32 (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_s-neg1-32 (result i32) - (i32.shr_s - (i32.shl - (i32.shr_s ;; subtracts, here there is a sign bit, so it stays 32 bits no matter how much we shift - (i32.const -1) - (i32.const 32) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_s-and-masked-sign (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_s-and-masked-sign (result i32) - (i32.shr_s - (i32.shl - (i32.shr_s ;; subtracts, here we mask out that sign bit - (i32.and - (i32.const -1) - (i32.const 2147483647) - ) - (i32.const 31) ;; adjusted after we fixed shift computation to just look at lower 5 bits - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-ne (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $sext-24-ne (result i32) - (i32.shr_s - (i32.shl - (i32.ne ;; 1 bit - (i32.const -1) - (i32.const -1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-le (result i32) - ;; CHECK-NEXT: (f32.le - ;; CHECK-NEXT: (f32.const -1) - ;; CHECK-NEXT: (f32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-le (result i32) - (i32.shr_s - (i32.shl - (f32.le - (f32.const -1) - (f32.const -1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-clz (result i32) - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-clz (result i32) - (i32.shr_s - (i32.shl - (i32.clz ;; assumed 5 bits - (i32.const 0) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-clz (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-clz (result i32) - (i32.shr_s - (i32.shl - (i32.shl - (i32.clz ;; assumed 5 bits - (i32.const 0) - ) - (i32.const 2) ;; + 2, so 7 - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-clz-too-big (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 27) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-clz-too-big (result i32) - (i32.shr_s - (i32.shl - (i32.shl - (i32.clz ;; assumed 5 bits - (i32.const 0) - ) - (i32.const 3) ;; + 3, so 8, too much - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-wrap-clz (result i32) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.clz - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-wrap-clz (result i32) - (i32.shr_s - (i32.shl - (i32.wrap_i64 ;; preserves 6 - (i64.clz ;; assumed 6 bits - (i64.const 0) - ) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-wrap-clz (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.clz - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-wrap-clz (result i32) - (i32.shr_s - (i32.shl - (i32.shl - (i32.wrap_i64 ;; preserves 6 - (i64.clz ;; assumed 6 bits - (i64.const 0) - ) - ) - (i32.const 1) ;; + 1, so 7 - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shl-wrap-clz-too-big (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.clz - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shl-wrap-clz-too-big (result i32) - (i32.shr_s - (i32.shl - (i32.shl - (i32.wrap_i64 ;; preserves 6 - (i64.clz ;; assumed 6 bits - (i64.const 0) - ) - ) - (i32.const 2) ;; + 2, so 8, too much - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-eqz (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-eqz (result i32) - (i32.shr_s - (i32.shl - (i32.eqz ;; 1 bit - (i32.const -1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-wrap-too-big (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-wrap-too-big (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u - (i32.wrap_i64 ;; down to 32 - (i64.const -1) ;; 64 - ) - (i32.const 24) ;; 32 - 24 = 8 - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-wrap (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-wrap (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u - (i32.wrap_i64 ;; down to 32 - (i64.const -1) ;; 64 - ) - (i32.const 25) ;; 32 - 25 = 7, ok - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-wrap-extend-too-big (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-wrap-extend-too-big (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u - (i32.wrap_i64 ;; stay 32 - (i64.extend_i32_s - (i32.const -1) - ) - ) - (i32.const 24) ;; 32 - 24 = 8 - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-shr_u-wrap-extend (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-shr_u-wrap-extend (result i32) - (i32.shr_s - (i32.shl - (i32.shr_u - (i32.wrap_i64 ;; stay 32 - (i64.extend_i32_s - (i32.const -1) - ) - ) - (i32.const 25) ;; 32 - 25 = 7, ok - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $sext-24-xor (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sext-24-xor (param $0 i32) (result i32) ;; fuzz testcase - (i32.shr_s - (i32.shl - (i32.xor ;; should be 32 bits - (i32.le_u ;; 1 bit - (local.get $0) - (i32.const 2) - ) - (local.get $0) ;; unknown, so 32 bits - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ;; CHECK: (func $linear-sums (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 18) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 26) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 22) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 66) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 34) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $linear-sums (param $0 i32) (param $1 i32) - (drop - (i32.add - (i32.add - (local.get $1) - (i32.const 16) - ) - (i32.shl - (i32.add - (local.get $0) - (i32.const -1) ;; -16, so cancels out! - ) - (i32.const 4) - ) - ) - ) - (drop - (i32.add - (i32.add - (local.get $1) - (i32.const 20) - ) - (i32.shl - (i32.add - (local.get $0) - (i32.const -1) ;; -8, so sum is +12 - ) - (i32.const 3) - ) - ) - ) - (drop - (i32.add ;; simple sum - (i32.const 1) - (i32.const 3) - ) - ) - (drop - (i32.add ;; nested sum - (i32.add - (i32.const 1) - (i32.const 3) - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.add - (i32.const 1) - (i32.const 3) - ) - (i32.sub ;; internal sub - (i32.const 5) - (i32.const 3) - ) - ) - ) - (drop - (i32.sub ;; external sub - (i32.add - (i32.const 1) - (i32.const 3) - ) - (i32.add - (i32.const 5) - (i32.const 3) - ) - ) - ) - (drop - (i32.sub ;; external sub - (i32.add - (i32.const 1) - (i32.const 3) - ) - (i32.sub ;; and also internal sub - (i32.const 5) - (i32.const 3) - ) - ) - ) - (drop - (i32.add - (i32.add - (i32.const 1) - (i32.const 3) - ) - (i32.sub ;; negating sub - (i32.const 0) - (i32.const 3) - ) - ) - ) - (drop - (i32.add - (i32.sub - (i32.const 0) - (i32.sub ;; two negating subs - (i32.const 0) - (i32.add - (i32.const 3) - (i32.const 20) - ) - ) - ) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (drop - (i32.add - (i32.add - (i32.const 0) - (i32.sub ;; one negating sub - (i32.const 0) - (i32.add - (i32.const 3) - (i32.const 20) - ) - ) - ) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (drop - (i32.add - (i32.shl ;; shifted value - (i32.const 1) - (i32.const 3) - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.shl ;; shifted value - (i32.const 1) - (local.get $0) ;; but not by const - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.shl ;; shifted nested value - (i32.sub - (local.get $1) - (i32.const 10) - ) - (i32.const 3) - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.mul ;; multiplied - (i32.const 10) - (i32.const 3) - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.mul ;; multiplied by nonconstant - can't recurse - (i32.const 10) - (local.get $0) - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.mul ;; nested mul - (i32.add - (i32.const 10) - (local.get $0) - ) - (i32.const 2) - ) - (i32.add - (i32.const 5) - (i32.const 9) - ) - ) - ) - (drop - (i32.add - (i32.add - (local.get $0) - (i32.const 10) ;; cancelled out with the below - ) - (i32.sub - (i32.const -5) - (i32.const 5) - ) - ) - ) - ) - ;; CHECK: (func $almost-sign-ext (param $0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 50) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $almost-sign-ext (param $0 i32) - (drop - (i32.shr_s - (i32.shl - (i32.const 100) ;; too big, there is a sign bit, due to the extra shift - (i32.const 25) - ) - (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift, in theory - ) - ) - (drop - (i32.shr_s - (i32.shl - (i32.const 50) ;; small enough, no sign bit - (i32.const 25) - ) - (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift - ) - ) - ) - ;; CHECK: (func $squaring (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 203) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 19) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $squaring (param $0 i32) (param $1 i32) - (drop - (i32.and - (i32.and - (local.get $0) - (i32.const 11) - ) - (i32.const 200) - ) - ) - (drop - (i32.and - (i32.and - (local.get $0) - (i32.const 11) - ) - (local.get $0) ;; non-const, cannot optimize this! - ) - ) - (drop - (i32.and - (i32.and - (i32.const 11) ;; flipped order - (local.get $0) - ) - (i32.const 200) - ) - ) - (drop - (i32.or - (i32.or - (local.get $0) - (i32.const 11) - ) - (i32.const 200) - ) - ) - (drop - (i32.shl - (i32.shl - (local.get $0) - (i32.const 11) - ) - (i32.const 200) - ) - ) - (drop - (i32.shr_s - (i32.shr_s - (local.get $0) - (i32.const 11) - ) - (i32.const 200) - ) - ) - (drop - (i32.shr_u - (i32.shr_u - (local.get $0) - (i32.const 11) - ) - (i32.const 200) - ) - ) - (drop - (i32.shr_u - (i32.shr_s ;; but do not optimize a mixture or different shifts! - (local.get $0) - (i32.const 11) - ) - (i32.const 200) - ) - ) - ) - ;; CHECK: (func $sign-ext-ne (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 111) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-ext-ne (param $0 i32) (param $1 i32) - ;; ne of sign-ext to const, can be a zext - (drop - (i32.ne - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 65000) - ) - ) - (drop - (i32.ne - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 64872) ;; no sign bit - ) - ) - (drop - (i32.ne - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const -149) ;; no sign bit, not all ones - ) - ) - (drop - (i32.ne - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 111) - ) - ) - (drop - (i32.ne - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ) - ;; CHECK: (func $sign-ext-eqz (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-ext-eqz (param $0 i32) (param $1 i32) - (drop - (i32.eqz - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ) - ;; CHECK: (func $sign-ext-boolean (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-ext-boolean (param $0 i32) (param $1 i32) - (drop - (if (result i32) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 100) - (i32.const 200) - ) - ) - ) - ;; CHECK: (func $add-sub-zero (param $0 i32) (param $1 i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $add-sub-zero (param $0 i32) (param $1 i64) - (drop - (i32.add - (local.get $0) - (i32.const 0) - ) - ) - (drop - (i32.sub - (local.get $0) - (i32.const 0) - ) - ) - (drop - (i64.add - (local.get $1) - (i64.const 0) - ) - ) - (drop - (i64.sub - (local.get $1) - (i64.const 0) - ) - ) - ) - ;; CHECK: (func $store-signext (param $0 i32) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store16 - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $store-signext (param $0 i32) - (i32.store8 - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) ;; exact size we store, sign-ext of 8 bits - ) - (i32.const 24) - ) - ) - (i32.store8 - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 25) ;; 7 bits. so the ext can alter a bit we store, do not optimize - ) - (i32.const 25) - ) - ) - (i32.store8 - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 23) ;; 9 bits, this is good to optimize - ) - (i32.const 23) - ) - ) - (i32.store16 - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 16) ;; exact size we store, sign-ext of 16 bits - ) - (i32.const 16) - ) - ) - (i32.store16 - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 17) ;; 15 bits. so the ext can alter a bit we store, do not optimize - ) - (i32.const 17) - ) - ) - (i32.store16 - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 14) ;; 17 bits, this is good to optimize - ) - (i32.const 14) - ) - ) - (i32.store - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 16) ;; 4 bytes stored, do nothing - ) - (i32.const 16) - ) - ) - (i32.store - (i32.const 8) - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 8) ;; 4 bytes stored, do nothing - ) - (i32.const 8) - ) - ) - ) - ;; CHECK: (func $sign-ext-tee (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-ext-tee (param $0 i32) (param $1 i32) - (drop - (i32.shr_s - (i32.shl - (local.tee $0 - (i32.const 128) ;; too big - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.tee $0 - (i32.const 127) ;; just right - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ;; CHECK: (func $sign-ext-load (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i32.const 256) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-ext-load (param $0 i32) (param $1 i32) - (drop - (i32.shr_s - (i32.shl - (i32.load8_s ;; one byte, so perfect - (i32.const 256) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (i32.shr_u - (i32.load8_s ;; one byte, but sexted to 32 - (i32.const 256) - ) - (i32.const 1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (i32.shr_u - (i32.load8_u ;; one byte, but reduced to 7 - (i32.const 256) - ) - (i32.const 1) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (i32.load16_s ;; two, so perfect - (i32.const 256) - ) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ;; through tees, we cannot alter the load sign - (drop - (i32.shr_s - (i32.shl - (local.tee $1 - (i32.load8_s - (i32.const 1) - ) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.tee $1 - (i32.load8_u - (i32.const 1) - ) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.and - (local.tee $1 - (i32.load8_s - (i32.const 1) - ) - ) - (i32.const 255) - ) - ) - (drop - (i32.and - (local.tee $1 - (i32.load8_u - (i32.const 1) - ) - ) - (i32.const 255) - ) - ) - ) - ;; CHECK: (func $mask-bits (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 254) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1279) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1290) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $mask-bits (param $0 i32) (param $1 i32) - (drop - (i32.and - (local.tee $0 - (i32.const 127) ;; 7 bits - ) - (i32.const 255) ;; mask 8, so we don't need this - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) ;; 8 bits - ) - (i32.const 255) ;; mask 8, so we don't need this - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) - ) - (i32.const 254) ;; improper mask, small - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) - ) - (i32.const 1279) ;; improper mask, large - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) - ) - (i32.const 1290) ;; improper mask, large - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) - ) - (i32.const 4095) ;; proper mask, huge - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) - ) - (i32.const 511) ;; proper mask, large - ) - ) - (drop - (i32.and - (local.tee $0 - (i32.const 128) - ) - (i32.const 127) ;; proper mask, just too small - ) - ) - ) - ;; CHECK: (func $local-info-zero-ext (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $z i32) - ;; CHECK-NEXT: (local $w i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 212) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 500) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 212) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 212) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 220) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (i32.const 212) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (i32.const 1000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-info-zero-ext (param $0 i32) (param $1 i32) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $x - (i32.const 212) ;; mask is unneeded, we are small - ) - (drop - (i32.and - (local.get $x) - (i32.const 255) - ) - ) - (local.set $y - (i32.const 500) ;; mask is needed, we are too big - ) - (drop - (i32.and - (local.get $y) - (i32.const 255) - ) - ) - (local.set $0 - (i32.const 212) ;; mask is unneeded, but we are a param, not a var, so no - ) - (drop - (i32.and - (local.get $0) - (i32.const 255) - ) - ) - (local.set $z - (i32.const 212) ;; mask is unneeded, we are small - ) - (local.set $z - (i32.const 220) ;; mask is still unneeded even with 2 uses - ) - (drop - (i32.and - (local.get $z) - (i32.const 255) - ) - ) - (local.set $w - (i32.const 212) ;; mask is unneeded, we are small - ) - (local.set $w - (i32.const 1000) ;; mask is needed, one use is too big - ) - (drop - (i32.and - (local.get $w) - (i32.const 255) - ) - ) - ) - ;; CHECK: (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $z i32) - ;; CHECK-NEXT: (local $w i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.const 128) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (i32.const 150) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $x - (i32.const 127) ;; mask is unneeded, we are small - ) - (drop - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $y - (i32.const 128) ;; mask is needed, we are too big - ) - (drop - (i32.shr_s - (i32.shl - (local.get $y) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $0 - (i32.const 127) ;; mask is unneeded, but we are a param, not a var, so no - ) - (drop - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $z - (i32.const 127) ;; mask is unneeded, we are small - ) - (local.set $z - (i32.const 100) ;; mask is still unneeded even with 2 uses - ) - (drop - (i32.shr_s - (i32.shl - (local.get $z) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $w - (i32.const 127) ;; mask is unneeded, we are small - ) - (local.set $w - (i32.const 150) ;; mask is needed, one use is too big - ) - (drop - (i32.shr_s - (i32.shl - (local.get $w) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ;; CHECK: (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $z i32) - ;; CHECK-NEXT: (local $w i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $w - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $x - (i32.shr_s - (i32.shl - (local.get $0) ;; already sign-exted here, so no need later - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $y - (i32.shr_s - (i32.shl - (local.get $0) ;; already sign-exted here, but wrong bit size - (i32.const 16) - ) - (i32.const 16) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.get $y) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $0 - (i32.shr_s - (i32.shl - (local.get $0) ;; already sign-exted here, so no need later, but we are a param - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.get $0) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $z - (i32.shr_s - (i32.shl - (local.get $0) ;; already sign-exted here, so no need later - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $z - (i32.shr_s - (i32.shl - (local.get $1) ;; already sign-exted here, so no need later - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.get $z) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $w - (i32.shr_s - (i32.shl - (local.get $0) ;; already sign-exted here, so no need later - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $w - (i32.shr_s - (i32.shl - (local.get $0) ;; not quite a sign-ext - (i32.const 23) - ) - (i32.const 24) - ) - ) - (drop - (i32.shr_s - (i32.shl - (local.get $w) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (drop ;; odd corner case - (i32.shr_s - (i32.shl - (local.get $0) ;; param, so we should know nothing - (i32.const 24) - ) - (i32.const 23) ;; different shift, smaller - ) - ) - ) - ;; CHECK: (func $signed-loads-fill-the-bits (param $$e i32) (result i32) - ;; CHECK-NEXT: (local $$0 i32) - ;; CHECK-NEXT: (local $$conv i32) - ;; CHECK-NEXT: (local.set $$0 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $$conv - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $$0) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $$e) - ;; CHECK-NEXT: (local.get $$conv) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $signed-loads-fill-the-bits (param $$e i32) (result i32) - (local $$0 i32) - (local $$conv i32) - (local.set $$0 - (i32.load8_s ;; one byte, but 32 bits due to sign-extend - (i32.const 1024) - ) - ) - (local.set $$conv - (i32.and - (local.get $$0) - (i32.const 255) ;; so we need this zexting! - ) - ) - (return - (i32.eq - (local.get $$conv) - (local.get $$e) - ) - ) - ) - ;; CHECK: (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (local $z i32) - ;; CHECK-NEXT: (local $w i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (i32.const 1024) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32) - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $x - (i32.load8_s (i32.const 1024)) ;; 8 bits, sign extended, no need to do it again - ) - (drop - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $y - (i32.load8_u (i32.const 1024)) ;; 8 bits, zext, so bad - ) - (drop - (i32.shr_s - (i32.shl - (local.get $y) - (i32.const 24) - ) - (i32.const 24) - ) - ) - (local.set $z - (i32.load16_s (i32.const 1024)) ;; 16 bits sign-extended, wrong size - ) - (drop - (i32.shr_s - (i32.shl - (local.get $z) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ;; CHECK: (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32) - (drop - (i32.eq - (i32.load8_s - (local.get $0) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.load8_s - (local.get $0) ;; flip order, we should canonicalize - ) - ) - ) - (drop - (i32.eq - (i32.load8_u ;; unsigned, bad - (local.get $0) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - (drop - (i32.eq - (i32.load8_s - (local.get $0) - ) - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 16) ;; wrong size - ) - (i32.const 16) - ) - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.load8_u ;; unsigned, bad - (local.get $0) - ) - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 16) ;; wrong size - ) - (i32.const 16) - ) - (i32.load8_s - (local.get $0) - ) - ) - ) - ) - ;; CHECK: (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (call $unsign-diff-sizes - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (call $unsign-diff-sizes - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2006) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) - (i32.ne - (i32.shr_s - (i32.shl - (call $unsign-diff-sizes - (i32.const -1) - (i32.const 5) - ) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.shr_s - (i32.shl - (call $unsign-diff-sizes - (i32.const 1) - (i32.const 2006) - ) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ) - ;; CHECK: (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (call $unsign-same-sizes - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (call $unsign-same-sizes - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2006) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) - (i32.ne - (i32.shr_s - (i32.shl - (call $unsign-same-sizes - (i32.const -1) - (i32.const 5) - ) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.shr_s - (i32.shl - (call $unsign-same-sizes - (i32.const 1) - (i32.const 2006) - ) - (i32.const 24) - ) - (i32.const 24) - ) - ) - ) - ;; CHECK: (func $fuzz-almost-sign-ext - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 2278) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_u - ;; CHECK-NEXT: (i32.const 2278) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 17) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fuzz-almost-sign-ext - (drop - (i32.shr_s - (i32.shl - (i32.load16_u - (i32.const 2278) - ) - (i32.const 17) - ) - (i32.const 16) - ) - ) - (drop - (i32.shr_s - (i32.shl - (i32.shl - (i32.load16_u - (i32.const 2278) - ) - (i32.const 1) - ) - (i32.const 16) - ) - (i32.const 16) - ) - ) - ) - ;; CHECK: (func $fuzz-comp-impossible (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 252) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fuzz-comp-impossible (param $x i32) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 16) - ) - (i32.const 16) - ) - (i32.const 65535) ;; impossible to be equal, the effective sign bit is set, but not the higher bits, which the sign-ext will set on the non-const value - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 255) - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 127) ;; safe - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 128) ;; unsafe again - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 4223) ;; more big bits, so sign bit though - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const 4224) ;; more big bits - ) - ) - (drop - (i32.eq - (i32.shr_s - (i32.shl - (local.get $x) - (i32.const 24) - ) - (i32.const 24) - ) - (i32.const -4) ;; safe even with more big bits, as they are all 1s - ) - ) - ) - ;; CHECK: (func $if-parallel (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-parallel (param $0 i32) (param $1 i32) - (drop - (if (result i32) - (local.get $0) - (i32.add (local.get $1) (i32.const 1)) - (i32.add (local.get $1) (i32.const 1)) - ) - ) - (drop - (if (result i32) - (local.tee $0 (local.get $1)) ;; side effects! - (i32.add (local.get $1) (i32.const 1)) - (i32.add (local.get $1) (i32.const 1)) - ) - ) - (drop - (if (result i32) - (local.get $0) - (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if - (i32.add (local.get $1) (unreachable)) - ) - ) - (drop - (if (result i32) - (local.tee $0 (local.get $1)) ;; side effects! - (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if - (i32.add (local.get $1) (unreachable)) - ) - ) - (drop - (if (result i32) - (unreachable) ;; !!! - (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if - (i32.add (local.get $1) (unreachable)) - ) - ) - ) - ;; CHECK: (func $select-parallel (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-parallel (param $0 i32) (param $1 i32) - (drop - (select - (i32.add (local.get $1) (i32.const 1)) - (i32.add (local.get $1) (i32.const 1)) - (local.get $0) - ) - ) - (drop - (select - (local.tee $0 (local.get $1)) ;; side effects! - (local.tee $0 (local.get $1)) ;; side effects! - (local.get $0) - ) - ) - (drop - (select - (i32.add (local.get $1) (i32.const 1)) - (i32.add (local.get $1) (i32.const 1)) - (local.tee $0 (local.get $1)) ;; side effects! (but no interference with values) - ) - ) - (drop - (select - (local.tee $0 (local.get $1)) ;; side effects! interference! - (local.tee $0 (local.get $1)) ;; side effects! interference! - (local.tee $0 (local.get $1)) ;; side effects! interference! - ) - ) - (drop - (select - (local.tee $0 (local.get $1)) ;; side effects! - (local.tee $0 (local.get $1)) ;; side effects! - (unreachable) ;; side effects! (but no interference with values) - ) - ) - ) - ;; CHECK: (func $zero-shifts-is-not-sign-ext - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load16_s align=1 - ;; CHECK-NEXT: (i32.const 790656516) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -5431187) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.load16_s align=1 - ;; CHECK-NEXT: (i32.const 790656516) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -5431187) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-shifts-is-not-sign-ext - (drop - (i32.eq - (i32.const -5431187) - (i32.add - (i32.const 0) - (i32.shr_s - (i32.shl - (i32.load16_s align=1 - (i32.const 790656516) - ) - (i32.const 0) - ) - (i32.const 0) - ) - ) - ) - ) - (drop - (i32.eq - (i32.const -5431187) - (i32.add - (i32.const 0) - (i32.shr_s - (i32.shl - (i32.load16_s align=1 - (i32.const 790656516) - ) - (i32.const 1) - ) - (i32.const 0) - ) - ) - ) - ) - ) - ;; CHECK: (func $zero-ops (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.load16_s align=1 - ;; CHECK-NEXT: (i32.const 790656516) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-ops (result i32) - (return - (i32.eq - (i32.const -1337) - (i32.shr_u - (i32.add - (i32.const 0) - (i32.shr_s - (i32.shl - (i32.load16_s align=1 - (i32.const 790656516) - ) - (i32.const 0) - ) - (i32.const 0) - ) - ) - (i32.const 0) - ) - ) - ) - ) - ;; CHECK: (func $zero-ops-64 (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (i64.load16_s align=1 - ;; CHECK-NEXT: (i32.const 790656516) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const -1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-ops-64 (result i32) - (return - (i64.eq - (i64.const -1337) - (i64.shr_u - (i64.add - (i64.const 0) - (i64.shr_s - (i64.shl - (i64.load16_s align=1 - (i32.const 790656516) - ) - (i64.const 0) - ) - (i64.const 0) - ) - ) - (i64.const 0) - ) - ) - ) - ) - ;; CHECK: (func $zero-ops-64-special (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.popcnt - ;; CHECK-NEXT: (i64.const 7377) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $zero-ops-64-special (result i32) - (return - (i32.wrap_i64 - (i64.popcnt - (i64.sub - (i64.shl - (i64.const 4294783828) - (i64.const 17179869183) - ) - (i64.const -7377) - ) - ) - ) - ) - ) - ;; CHECK: (func $sign-ext-1-and-ne (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $sign-ext-1-and-ne) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $sign-ext-1-and-ne (result i32) - (select - (i32.ne - (i32.const 1333788672) - (i32.shr_s - (i32.shl - (call $sign-ext-1-and-ne) - (i32.const 1) - ) - (i32.const 1) - ) - ) - (i32.const 2) - (i32.const 1) - ) - ) - ;; CHECK: (func $neg-shifts-and-255 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const -99) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $neg-shifts-and-255 (result i32) - (i32.and - (i32.shr_u - (i32.const -99) - (i32.const -32) ;; this shift does nothing - ) - (i32.const 255) - ) - ) - ;; CHECK: (func $neg-shifts-and-255-b (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const -2349025) - ;; CHECK-NEXT: (i32.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $neg-shifts-and-255-b (result i32) - (i32.and - (i32.shl - (i32.const -2349025) - (i32.const -32) ;; this shift does nothing - ) - (i32.const 255) - ) - ) - ;; CHECK: (func $shifts-square-overflow (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $shifts-square-overflow (param $x i32) (result i32) - (i32.shr_u - (i32.shr_u - (local.get $x) - (i32.const 65535) ;; 31 bits effectively - ) - (i32.const 32767) ;; also 31 bits, so two shifts that force the value into nothing for sure - ) - ) - ;; CHECK: (func $shifts-square-no-overflow-small (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $shifts-square-no-overflow-small (param $x i32) (result i32) - (i32.shr_u - (i32.shr_u - (local.get $x) - (i32.const 1031) ;; 7 bits effectively - ) - (i32.const 4098) ;; 2 bits effectively - ) - ) - ;; CHECK: (func $shifts-square-overflow-64 (param $x i64) (result i64) - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $shifts-square-overflow-64 (param $x i64) (result i64) - (i64.shr_u - (i64.shr_u - (local.get $x) - (i64.const 65535) ;; 63 bits effectively - ) - (i64.const 64767) ;; also 63 bits, so two shifts that force the value into nothing for sure - ) - ) - ;; CHECK: (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64) - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64) - (i64.shr_u - (i64.shr_u - (local.get $x) - (i64.const 1031) ;; 7 bits effectively - ) - (i64.const 4098) ;; 2 bits effectively - ) - ) - ;; CHECK: (func $shifts-square-unreachable (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 1031) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4098) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $shifts-square-unreachable (param $x i32) (result i32) - (i32.shr_u - (i32.shr_u - (unreachable) - (i32.const 1031) ;; 7 bits effectively - ) - (i32.const 4098) ;; 2 bits effectively - ) - ) - ;; CHECK: (func $mix-shifts (result i32) - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 23) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $mix-shifts (result i32) - (i32.shr_s - (i32.shl - (i32.const 23) - (i32.const -61) - ) - (i32.const 168) - ) - ) - ;; CHECK: (func $actually-no-shifts (result i32) - ;; CHECK-NEXT: (i32.const 33) - ;; CHECK-NEXT: ) - (func $actually-no-shifts (result i32) - (i32.add - (i32.shl - (i32.const 23) - (i32.const 32) ;; really 0 - ) - (i32.const 10) - ) - ) - ;; CHECK: (func $less-shifts-than-it-seems (param $x i32) (result i32) - ;; CHECK-NEXT: (i32.const 4800) - ;; CHECK-NEXT: ) - (func $less-shifts-than-it-seems (param $x i32) (result i32) - (i32.add - (i32.shl - (i32.const 200) - (i32.const 36) ;; really 4 - ) - (i32.shl - (i32.const 100) - (i32.const 4) - ) - ) - ) - ;; CHECK: (func $and-popcount32 (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.popcnt - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-popcount32 (result i32) - (i32.and - (i32.popcnt - (i32.const -1) - ) - (i32.const 31) - ) - ) - ;; CHECK: (func $and-popcount32-big (result i32) - ;; CHECK-NEXT: (i32.popcnt - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-popcount32-big (result i32) - (i32.and - (i32.popcnt - (i32.const -1) - ) - (i32.const 63) - ) - ) - ;; CHECK: (func $and-popcount64 (result i64) - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (i64.popcnt - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-popcount64 (result i64) ;; these are TODOs - (i64.and - (i64.popcnt - (i64.const -1) - ) - (i64.const 63) - ) - ) - ;; CHECK: (func $and-popcount64-big (result i64) - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (i64.popcnt - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 127) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-popcount64-big (result i64) - (i64.and - (i64.popcnt - (i64.const -1) - ) - (i64.const 127) - ) - ) - ;; CHECK: (func $and-popcount64-bigger (result i64) - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (i64.popcnt - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 255) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $and-popcount64-bigger (result i64) - (i64.and - (i64.popcnt - (i64.const -1) - ) - (i64.const 255) - ) - ) - ;; CHECK: (func $optimizeAddedConstants-filters-through-nonzero (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const -536870912) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31744) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimizeAddedConstants-filters-through-nonzero (result i32) - (i32.sub - (i32.add - (i32.shl - (i32.const -536870912) - (i32.wrap_i64 - (i64.const 0) - ) - ) - (i32.const -32768) - ) - (i32.const -1024) - ) - ) - ;; CHECK: (func $optimizeAddedConstants-filters-through-nonzero-b (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const -536870912) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31744) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimizeAddedConstants-filters-through-nonzero-b (result i32) - (i32.sub - (i32.add - (i32.shl - (i32.const -536870912) - (i32.wrap_i64 - (i64.const -1) - ) - ) - (i32.const -32768) - ) - (i32.const -1024) - ) - ) - ;; CHECK: (func $return-proper-value-from-shift-left-by-zero (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (loop $label$0 (result i32) - ;; CHECK-NEXT: (block $label$1 - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -62) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $return-proper-value-from-shift-left-by-zero (result i32) - (if (result i32) - (i32.sub - (i32.add - (loop $label$0 (result i32) - (block $label$1 - (br_if $label$1 - (i32.shl - (i32.load - (i32.const 0) - ) - (i32.const -31904) ;; really 0 shifts - ) - ) - ) - (i32.const -62) - ) - (i32.const 38) - ) - (i32.const -2) - ) - (i32.const 1) - (i32.const 0) - ) - ) - ;; CHECK: (func $de-morgan-2 (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $de-morgan-2 (param $x i32) (param $y i32) - (drop - (i32.and (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) - ) - (drop - (i32.or (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) - ) - (drop - (i32.xor (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) - ) - (drop - (i32.and (i32.eqz (local.get $x)) (local.get $y)) - ) - (drop - (i32.and (local.get $x) (i32.eqz (local.get $y))) - ) - (drop - (i32.and (i32.eqz (local.get $x)) (i32.wrap_i64 (i64.const 2))) - ) - (drop - (i32.and (i32.wrap_i64 (i64.const 1)) (i32.eqz (local.get $y))) - ) - ) - ;; CHECK: (func $subzero1 (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subzero1 (param $0 i32) (result i32) - (i32.add - (i32.sub - (i32.const 1) - (i32.clz - (local.get $0) - ) - ) - (i32.const 31) - ) - ) - ;; CHECK: (func $subzero2 (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subzero2 (param $0 i32) (result i32) - (i32.add - (i32.const 31) - (i32.sub - (i32.const 1) - (i32.clz - (local.get $0) - ) - ) - ) - ) - ;; CHECK: (func $subzero3 (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subzero3 (param $0 i32) (param $1 i32) (result i32) - (i32.add - (i32.sub - (i32.const 0) - (i32.clz - (local.get $0) - ) - ) - (local.get $1) - ) - ) - ;; CHECK: (func $subzero4 (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.clz - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $subzero4 (param $0 i32) (param $1 i32) (result i32) - (i32.add - (local.get $0) - (i32.sub - (i32.const 0) - (i32.clz - (local.get $1) - ) - ) - ) - ) - ;; CHECK: (func $remove-signs-for-mul-i32 (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $remove-signs-for-mul-i32 (param $0 i32) (param $1 i32) (result i32) - (i32.mul - (i32.sub - (i32.const 0) - (local.get $0) - ) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - ;; CHECK: (func $remove-signs-for-mul-i64 (param $0 i64) (param $1 i64) (result i64) - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $remove-signs-for-mul-i64 (param $0 i64) (param $1 i64) (result i64) - (i64.mul - (i64.sub - (i64.const 0) - (local.get $0) - ) - (i64.sub - (i64.const 0) - (local.get $1) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-i32-lhs (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-i32-lhs (param $0 i32) (param $1 i32) (result i32) - (i32.mul - (i32.sub - (i32.const 0) - (local.get $0) - ) - (local.get $1) - ) - ) - ;; CHECK: (func $propagate-sign-for-i32-rhs (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-i32-rhs (param $0 i32) (param $1 i32) (result i32) - (i32.mul - (local.get $0) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-i64-lhs (param $0 i64) (param $1 i64) (result i64) - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-i64-lhs (param $0 i64) (param $1 i64) (result i64) - (i64.mul - (i64.sub - (i64.const 0) - (local.get $0) - ) - (local.get $1) - ) - ) - ;; CHECK: (func $propagate-sign-for-i64-rhs (param $0 i64) (param $1 i64) (result i64) - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-i64-rhs (param $0 i64) (param $1 i64) (result i64) - (i64.mul - (local.get $0) - (i64.sub - (i64.const 0) - (local.get $1) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-i32-rhs-side (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (call $subzero4 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-i32-rhs-side (param $0 i32) (param $1 i32) (result i32) - (i32.mul - (call $subzero4 - (local.get $0) - (local.get $1) - ) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-mul-i32-lhs-const (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-mul-i32-lhs-const (param $0 i32) (result i32) - (i32.mul - (i32.const 3) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-mul-i32-lhs-const-pot (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-mul-i32-lhs-const-pot (param $0 i32) (result i32) - (i32.mul - (i32.const 2) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-mul-i32-rhs-const (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-mul-i32-rhs-const (param $0 i32) (result i32) - (i32.mul - (i32.sub - (i32.const 0) - (local.get $0) - ) - (i32.const -5) - ) - ) - ;; CHECK: (func $propagate-sign-for-i32-both-sign-consts (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-i32-both-sign-consts (param $0 i32) (result i32) - (i32.mul - (i32.const -5) - (i32.sub - (i32.const 0) - (i32.const 2) - ) - ) - ) - ;; CHECK: (func $propagate-sign-for-mul-i32-smin (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-mul-i32-smin (param $0 i32) (result i32) - (i32.mul - (i32.sub - (i32.const 0) - (local.get $0) - ) - (i32.const 0x80000000) - ) - ) - ;; CHECK: (func $propagate-sign-for-mul-i32-skip-2 (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-sign-for-mul-i32-skip-2 (param $0 i32) (result i32) - (i32.mul - (local.get $0) - (i32.sub - (i32.const 0) - (i32.const 3) - ) - ) - ) - ;; CHECK: (func $mul-32-power-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-32-power-2 - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $mul-32-power-2 (param $x i32) (result i32) - (drop - (call $mul-32-power-2 - (i32.mul - (local.get $x) - (i32.const 4) - ) - ) - ) - (drop - (call $mul-32-power-2 - (i32.mul - (local.get $x) - (i32.const 5) - ) - ) - ) - (drop - (call $mul-32-power-2 - (i32.mul - (local.get $x) - (i32.const 1) - ) - ) - ) - (drop - (call $mul-32-power-2 - (i32.mul - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (call $mul-32-power-2 - (i32.mul - (call $mul-32-power-2 (i32.const 123)) ;; side effects - (i32.const 0) - ) - ) - ) - (drop - (call $mul-32-power-2 - (i32.mul - (local.get $x) - (i32.const 0xffffffff) - ) - ) - ) - (drop - (call $mul-32-power-2 - (i32.mul - (local.get $x) - (i32.const 0x80000000) - ) - ) - ) - (unreachable) - ) - ;; CHECK: (func $mul-64-power-2 (param $x i64) (result i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.mul - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $mul-64-power-2 - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $mul-64-power-2 (param $x i64) (result i64) - (drop - (call $mul-64-power-2 - (i64.mul - (local.get $x) - (i64.const 4) - ) - ) - ) - (drop - (call $mul-64-power-2 - (i64.mul - (local.get $x) - (i64.const 5) - ) - ) - ) - (drop - (call $mul-64-power-2 - (i64.mul - (local.get $x) - (i64.const 1) - ) - ) - ) - (drop - (call $mul-64-power-2 - (i64.mul - (local.get $x) - (i64.const 0) - ) - ) - ) - (drop - (call $mul-64-power-2 - (i64.mul - (call $mul-64-power-2 (i64.const 123)) ;; side effects - (i64.const 0) - ) - ) - ) - (drop - (call $mul-64-power-2 - (i64.mul - (local.get $x) - (i64.const 0xffffffffffffffff) - ) - ) - ) - (drop - (call $mul-64-power-2 - (i64.mul - (local.get $x) - (i64.const 0x8000000000000000) - ) - ) - ) - (unreachable) - ) - ;; CHECK: (func $div-32-power-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.const 123) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $div-32-power-2 - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $div-32-power-2 (param $x i32) (result i32) - (drop - (call $div-32-power-2 - (i32.div_u - (local.get $x) - (i32.const 4) - ) - ) - ) - (drop - (call $div-32-power-2 - (i32.div_u - (local.get $x) - (i32.const 5) - ) - ) - ) - (drop - (call $div-32-power-2 - (i32.div_u - (local.get $x) - (i32.const 1) - ) - ) - ) - (drop - (call $div-32-power-2 - (i32.div_u - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (call $div-32-power-2 - (i32.div_u - (call $div-32-power-2 (i32.const 123)) ;; side effects - (i32.const 0) - ) - ) - ) - (drop - (call $div-32-power-2 - (i32.div_u - (local.get $x) - (i32.const 0xffffffff) - ) - ) - ) - (drop - (call $div-32-power-2 - (i32.div_u - (local.get $x) - (i32.const 0x80000000) - ) - ) - ) - (unreachable) - ) - ;; CHECK: (func $urem-32-power-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $urem-32-power-2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $urem-32-power-2 (param $x i32) (result i32) - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 4) - ) - ) - ) - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 5) - ) - ) - ) - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 1) - ) - ) - ) - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 0xffffffff) - ) - ) - ) - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 0x80000000) - ) - ) - ) - ;; (unsigned)x % 1 - (drop - (call $urem-32-power-2 - (i32.rem_u - (local.get $x) - (i32.const 1) - ) - ) - ) - (unreachable) - ) - ;; CHECK: (func $fdiv-32-power-2 (param $x f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 0.5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const -0.5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 2.3283064365386963e-10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 5.421010862427522e-20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 8507059173023461586584365e13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 1.1754943508222875e-38) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const -8507059173023461586584365e13) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const -1.1754943508222875e-38) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 5.877471754111438e-39) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 5.877471754111438e-39) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const nan:0x400000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const inf) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f32.const -inf) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fdiv-32-power-2 (param $x f32) - (drop (f32.div - (local.get $x) - (f32.const 2) - )) - (drop (f32.div - (local.get $x) - (f32.const -2) - )) - (drop (f32.div - (local.get $x) - (f32.const 4294967296) - )) - (drop (f32.div - (local.get $x) - (f32.const 18446744073709551616) - )) - (drop (f32.div - (local.get $x) - (f32.const 0x1p-126) - )) - (drop (f32.div - (local.get $x) - (f32.const 0x1p+126) - )) - (drop (f32.div - (local.get $x) - (f32.const -0x1p-126) - )) - (drop (f32.div - (local.get $x) - (f32.const -0x1p+126) - )) - (drop (f32.div - (local.get $x) - (f32.const 0x1p-127) ;; skip - )) - (drop (f32.div - (local.get $x) - (f32.const 0x1p-127) ;; skip - )) - (drop (f32.div - (local.get $x) - (f32.const 0) ;; skip - )) - (drop (f32.div - (local.get $x) - (f32.const nan) ;; skip - )) - (drop (f32.div - (local.get $x) - (f32.const inf) ;; skip - )) - (drop (f32.div - (local.get $x) - (f32.const -inf) ;; skip - )) - ) - ;; CHECK: (func $fdiv-64-power-2 (param $x f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 0.5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const -0.5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 2.3283064365386963e-10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 5.421010862427522e-20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 4494232837155789769323262e283) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 2.2250738585072014e-308) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const -4494232837155789769323262e283) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const -2.2250738585072014e-308) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 1.1125369292536007e-308) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 8988465674311579538646525e283) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const nan:0x8000000000000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const inf) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const -inf) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $fdiv-64-power-2 (param $x f64) - (drop (f64.div - (local.get $x) - (f64.const 2) - )) - (drop (f64.div - (local.get $x) - (f64.const -2) - )) - (drop (f64.div - (local.get $x) - (f64.const 4294967296) - )) - (drop (f64.div - (local.get $x) - (f64.const 18446744073709551616) - )) - (drop (f64.div - (local.get $x) - (f64.const 0x1p-1022) - )) - (drop (f64.div - (local.get $x) - (f64.const 0x1p+1022) - )) - (drop (f64.div - (local.get $x) - (f64.const -0x1p-1022) - )) - (drop (f64.div - (local.get $x) - (f64.const -0x1p+1022) - )) - (drop (f64.div - (local.get $x) - (f64.const 0x1p-1023) ;; skip - )) - (drop (f64.div - (local.get $x) - (f64.const 0x1p+1023) ;; skip - )) - (drop (f64.div - (local.get $x) - (f64.const 0) ;; skip - )) - (drop (f64.div - (local.get $x) - (f64.const nan) ;; skip - )) - (drop (f64.div - (local.get $x) - (f64.const inf) ;; skip - )) - (drop (f64.div - (local.get $x) - (f64.const -inf) ;; skip - )) - ) - ;; CHECK: (func $srem-by-const (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.rem_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -9223372036854775808) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $srem-by-const (param $x i32) (param $y i64) - ;; (signed)x % 1 - (drop (i32.rem_s - (local.get $x) - (i32.const 1) - )) - (drop (i64.rem_s - (local.get $y) - (i64.const 1) - )) - ;; (signed)x % 0x80000000 -> x & 0x7FFFFFFF - (drop (i32.rem_s - (local.get $x) - (i32.const 0x80000000) - )) - ;; (signed)x % 0x8000000000000000 -> x & 0x7FFFFFFFFFFFFFFF - (drop (i64.rem_s - (local.get $y) - (i64.const 0x8000000000000000) - )) - ) - ;; CHECK: (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 9223372036854775807) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 9223372036854775807) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.rem_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) - ;; eqz((signed)x % 4) - (drop (i32.eqz - (i32.rem_s - (local.get $x) - (i32.const 4) - ) - )) - (drop (i64.eqz - (i64.rem_s - (local.get $y) - (i64.const 4) - ) - )) - ;; eqz((signed)x % -4) - (drop (i32.eqz - (i32.rem_s - (local.get $x) - (i32.const -4) - ) - )) - (drop (i64.eqz - (i64.rem_s - (local.get $y) - (i64.const -4) - ) - )) - ;; (signed)x % 4 == 0 - (drop (i32.eq - (i32.rem_s - (local.get $x) - (i32.const 4) - ) - (i32.const 0) - )) - (drop (i64.eq - (i64.rem_s - (local.get $y) - (i64.const 2) - ) - (i64.const 0) - )) - ;; (signed)x % -4 == 0 - (drop (i32.eq - (i32.rem_s - (local.get $x) - (i32.const -4) - ) - (i32.const 0) - )) - (drop (i64.eq - (i64.rem_s - (local.get $y) - (i64.const -4) - ) - (i64.const 0) - )) - ;; (signed)x % 2 != 0 - (drop (i32.ne - (i32.rem_s - (local.get $x) - (i32.const 2) - ) - (i32.const 0) - )) - (drop (i64.ne - (i64.rem_s - (local.get $y) - (i64.const 2) - ) - (i64.const 0) - )) - ;; (signed)x % -1 == 0 -> 0 == 0 - (drop (i32.eq - (i32.rem_s - (local.get $x) - (i32.const -1) - ) - (i32.const 0) - )) - ;; (signed)x % 0x80000000 == 0 - (drop (i32.eq - (i32.rem_s - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 0) - )) - ;; (signed)x % 0x80000000 != 0 - (drop (i32.ne - (i32.rem_s - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 0) - )) - ;; (signed)x % 0x8000000000000000 == 0 - (drop (i64.eq - (i64.rem_s - (local.get $y) - (i64.const 0x8000000000000000) - ) - (i64.const 0) - )) - ;; (signed)x % 0x8000000000000000 != 0 - (drop (i64.ne - (i64.rem_s - (local.get $y) - (i64.const 0x8000000000000000) - ) - (i64.const 0) - )) - ;; - (drop (i32.eq - (i32.rem_s - (local.get $x) - (i32.const 3) ;; skip - ) - (i32.const 0) - )) - (drop (i64.eq - (i64.rem_s - (local.get $y) - (i64.const 3) ;; skip - ) - (i64.const 0) - )) - ) - ;; CHECK: (func $orZero (param $0 i32) (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $orZero (param $0 i32) (result i32) - (i32.or - (local.get $0) - (i32.const 0) - ) - ) - ;; CHECK: (func $andZero (param $0 i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (call $andZero - ;; CHECK-NEXT: (i32.const 1234) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $andZero (param $0 i32) (result i32) - (drop - (i32.and - (local.get $0) - (i32.const 0) - ) - ) - (drop - (i32.and - (call $andZero (i32.const 1234)) ;; side effects - (i32.const 0) - ) - ) - (unreachable) - ) - ;; CHECK: (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $y32) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $y64) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $y32) - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $y64) - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $y32) - ;; CHECK-NEXT: (f32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $y64) - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $y32) - ;; CHECK-NEXT: (f32.const 1.2000000476837158) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (f32.const -0) - ;; CHECK-NEXT: (local.get $y32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (f64.const -0) - ;; CHECK-NEXT: (local.get $y64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $x64) - ;; CHECK-NEXT: (i64.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64) - (drop - (i32.or - (i32.const 0) - (local.get $x32) - ) - ) - (drop - (i32.shl - (local.get $x32) - (i32.const 0) - ) - ) - (drop - (i32.shr_u - (local.get $x32) - (i32.const 0) - ) - ) - (drop - (i32.shr_s - (local.get $x32) - (i32.const 0) - ) - ) - (drop - (i64.or - (i64.const 0) - (local.get $x64) - ) - ) - (drop - (i64.shl - (local.get $x64) - (i64.const 0) - ) - ) - (drop - (i64.shr_u - (local.get $x64) - (i64.const 0) - ) - ) - (drop - (i64.shr_s - (local.get $x64) - (i64.const 0) - ) - ) - (drop - (i32.mul - (local.get $x32) - (i32.const 0) - ) - ) - (drop - (i64.mul - (local.get $x64) - (i64.const 0) - ) - ) - (drop - (f32.mul - (local.get $y32) - (f32.const 0) - ) - ) - (drop - (f64.mul - (local.get $y64) - (f64.const 0) - ) - ) - (drop - (i32.mul - (local.get $x32) - (i32.const 1) - ) - ) - (drop - (i64.mul - (local.get $x64) - (i64.const 1) - ) - ) - (drop - (f32.mul - (local.get $y32) - (f32.const 1) - ) - ) - (drop - (f64.mul - (local.get $y64) - (f64.const 1) - ) - ) - (drop - (i32.and - (local.get $x32) - (i32.const 0) - ) - ) - (drop - (i64.and - (local.get $x64) - (i64.const 0) - ) - ) - (drop - (i32.and - (unreachable) - (i32.const 0) - ) - ) - (drop - (i64.and - (unreachable) - (i64.const 0) - ) - ) - (drop - (i32.div_s - (local.get $x32) - (i32.const 1) - ) - ) - (drop - (i32.div_u - (local.get $x32) - (i32.const 1) - ) - ) - (drop - (i64.div_s - (local.get $x64) - (i64.const 1) - ) - ) - (drop - (i64.div_u - (local.get $x64) - (i64.const 1) - ) - ) - (drop - (f32.div - (local.get $y32) - (f32.const 1) - ) - ) - (drop - (f64.div - (local.get $y64) - (f64.const 1) - ) - ) - (drop - (f32.div - (local.get $y32) - (f32.const 1.2) - ) - ) - (drop - (i32.mul - (local.get $x32) - (i32.const -1) - ) - ) - (drop - (i64.mul - (local.get $x64) - (i64.const -1) - ) - ) - (drop - (f32.mul - (local.get $y32) - (f32.const -1) - ) - ) - (drop - (f64.mul - (local.get $y64) - (f64.const -1) - ) - ) - (drop - (i32.eq - (i32.add - (local.get $x32) - (i32.const 10) - ) - (i32.const 20) - ) - ) - (drop - (i32.le_u - (i32.add - (local.get $x32) - (i32.const 10) - ) - (i32.const 20) - ) - ) - (drop - (i32.eq - (i32.sub - (local.get $x32) - (i32.const 10) - ) - (i32.const 20) - ) - ) - (drop - (i64.eq - (i64.add - (local.get $x64) - (i64.const 10) - ) - (i64.const 20) - ) - ) - (drop - (i32.eq - (i32.const 20) - (i32.add - (local.get $x32) - (i32.const 10) - ) - ) - ) - (drop - (i32.eq - (i32.add - (local.get $x32) - (i32.const 10) - ) - (i32.add - (local.get $x32) - (i32.const 20) - ) - ) - ) - (drop - (i32.eq - (i32.sub - (local.get $x32) - (i32.const 10) - ) - (i32.const 20) - ) - ) - (drop - (i32.eq - (i32.add - (local.get $x32) - (i32.const 10) - ) - (i32.sub - (local.get $x32) - (i32.const 20) - ) - ) - ) - (drop - (i32.eq - (i32.sub - (local.get $x32) - (i32.const 10) - ) - (i32.add - (local.get $x32) - (i32.const 20) - ) - ) - ) - (drop - (i32.eq - (i32.sub - (local.get $x32) - (i32.const 10) - ) - (i32.sub - (local.get $x32) - (i32.const 20) - ) - ) - ) - (drop - (i64.le_s - (i64.sub - (local.get $x64) - (i64.const 288230376151711744) - ) - (i64.const 9223372036854775807) - ) - ) - ) - ;; CHECK: (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -134217728) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -8192) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1048576) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -134217728) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -17179869184) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -2199023255552) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -281474976710656) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -36028797018963968) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -4611686018427387904) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.add - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (f32.const 64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32) - (drop (i32.add (local.get $x) (i32.const 0x40))) - (drop (i32.sub (local.get $x) (i32.const 0x40))) - (drop (i32.add (local.get $x) (i32.const 0x2000))) - (drop (i32.add (local.get $x) (i32.const 0x100000))) - (drop (i32.add (local.get $x) (i32.const 0x8000000))) - - (drop (i64.add (local.get $y) (i64.const 0x40))) - (drop (i64.sub (local.get $y) (i64.const 0x40))) - (drop (i64.add (local.get $y) (i64.const 0x2000))) - (drop (i64.add (local.get $y) (i64.const 0x100000))) - (drop (i64.add (local.get $y) (i64.const 0x8000000))) - - (drop (i64.add (local.get $y) (i64.const 0x400000000))) - (drop (i64.add (local.get $y) (i64.const 0x20000000000))) - (drop (i64.add (local.get $y) (i64.const 0x1000000000000))) - (drop (i64.add (local.get $y) (i64.const 0x80000000000000))) - (drop (i64.add (local.get $y) (i64.const 0x4000000000000000))) - - (drop (f32.add (local.get $z) (f32.const 0x40))) - ) - ;; CHECK: (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32) - (drop - (i32.shl - (i32.const 0) - (local.get $x) - ) - ) - (drop - (i32.shr_u - (i32.const 0) - (local.get $x) - ) - ) - (drop - (i32.shr_s - (i32.const 0) - (local.get $x) - ) - ) - (drop - (i64.shl - (i64.const 0) - (local.get $y) - ) - ) - (drop - (i32.shl - (i32.const 0) - (unreachable) - ) - ) - ) - ;; CHECK: (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $xx) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32) - (drop - (i32.sub - (local.get $x) - (local.get $x) - ) - ) - (drop - (i64.sub - (local.get $y) - (local.get $y) - ) - ) - (drop - (f64.sub - (local.get $z) - (local.get $z) - ) - ) - (drop - (i32.sub - (local.get $x) - (local.get $xx) - ) - ) - (drop - (i32.sub - (unreachable) - (unreachable) - ) - ) - (drop - (i32.add - (local.get $x) - (local.get $x) - ) - ) - ;; more ops - (drop - (i32.xor - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.ne - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.lt_s - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.lt_u - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.gt_s - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.gt_u - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.and - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.or - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.eq - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.le_s - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.le_u - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.ge_s - (local.get $x) - (local.get $x) - ) - ) - (drop - (i32.ge_u - (local.get $x) - (local.get $x) - ) - ) - (drop - (i64.xor - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.ne - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.lt_s - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.lt_u - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.gt_s - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.gt_u - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.and - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.or - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.eq - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.le_s - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.le_u - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.ge_s - (local.get $y) - (local.get $y) - ) - ) - (drop - (i64.ge_u - (local.get $y) - (local.get $y) - ) - ) - ) - ;; CHECK: (func $all_ones (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $all_ones (param $x i32) (param $y i64) - (drop - (i32.and - (local.get $x) - (i32.const -1) - ) - ) - (drop - (i32.or - (local.get $x) - (i32.const -1) - ) - ) - (drop - (i32.or - (local.tee $x - (i32.const 1337) - ) - (i32.const -1) - ) - ) - (drop - (i64.and - (local.get $y) - (i64.const -1) - ) - ) - (drop - (i64.or - (local.get $y) - (i64.const -1) - ) - ) - ) - ;; CHECK: (func $xor (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $xor (param $x i32) (param $y i64) - (drop - (i32.xor - (local.get $x) - (i32.const 0) - ) - ) - ) - ;; CHECK: (func $select-on-const (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-on-const (param $x i32) (param $y i64) - (drop - (select - (i32.const 2) - (local.get $x) - (i32.const 0) - ) - ) - (drop - (select - (i32.const 3) - (local.get $x) - (i32.const 1) - ) - ) - (drop - (select - (i32.const 4) - (local.tee $x - (i32.const 5) - ) - (i32.const 0) - ) - ) - (drop - (select - (local.tee $x - (i32.const 6) - ) - (i32.const 7) - (i32.const 0) - ) - ) - (drop - (select - (i32.const 4) - (local.tee $x - (i32.const 5) - ) - (i32.const 1) - ) - ) - (drop - (select - (local.tee $x - (i32.const 6) - ) - (i32.const 7) - (i32.const 1) - ) - ) - (drop - (select - (i32.const 1) - (i32.const 0) - (local.get $x) - ) - ) - (drop - (select - (i32.const 0) - (i32.const 1) - (local.get $x) - ) - ) - (drop - (select - (i32.const 0) - (i32.const 1) - (i32.lt_s - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (select - (i32.const 1) - (i32.const 0) - (i32.lt_s - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (select - (i32.const 0) - (i32.const 1) - (i32.ge_s - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (select - (i32.const 1) - (i32.const 0) - (i32.gt_s - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (select - (i32.const 0) - (i32.const 1) - (i32.gt_s - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (select - (i32.const 1) - (i32.const 0) - (i32.ge_s - (local.get $x) - (i32.const 0) - ) - ) - ) - (drop - (select - (i64.const 1) - (i64.const 0) - (local.get $x) - ) - ) - (drop - (select - (i64.const 0) - (i64.const 1) - (local.get $x) - ) - ) - (drop - (select - (i64.const 1) - (i64.const 0) - (i64.eqz - (local.get $y) - ) - ) - ) - (drop - (select - (i64.const 0) - (i64.const 1) - (i64.eqz - (local.get $y) - ) - ) - ) - (drop - (select - (i64.const 0) - (i64.const 1) - (i64.lt_s - (local.get $y) - (i64.const 0) - ) - ) - ) - (drop - (select - (i64.const 1) - (i64.const 0) - (i64.lt_s - (local.get $y) - (i64.const 0) - ) - ) - ) - (drop - (select - (i64.const 0) - (i64.const 1) - (i64.ge_s - (local.get $y) - (i64.const 0) - ) - ) - ) - (drop - (select - (i64.const 1) - (i64.const 0) - (i64.ge_s - (local.get $y) - (i64.const 0) - ) - ) - ) - ;; optimize boolean - (drop - (select - (local.get $x) - (i32.const 0) - (i32.eqz - (i32.const 0) - ) - ) - ) - (drop - (select - (local.get $x) - (i32.const 2) - (i32.eqz - (i32.const 2) - ) - ) - ) - (drop - (select - (local.get $x) - (i32.const 2) - (i32.eqz - (i32.eqz - (local.get $x) - ) - ) - ) - ) - (drop - (select - (local.get $y) - (i64.const 0) - (i64.eqz - (i64.const 0) - ) - ) - ) - (drop - (select - (local.get $y) - (i64.const 2) - (i64.eqz - (i64.const 2) - ) - ) - ) - ) - ;; CHECK: (func $optimize-boolean (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-boolean (param $x i32) (param $y i64) - ;; bool(-x) -> bool(x) - (drop - (select - (i32.const 1) - (i32.const 2) - (i32.sub - (i32.const 0) - (local.get $x) - ) - ) - ) - ;; i32(bool(expr)) == 1 -> bool(expr) - (drop (i32.eq - (i32.and - (local.get $x) - (i32.const 1) - ) - (i32.const 1) - )) - ;; i32(bool(expr)) != 1 -> !bool(expr) - (drop (i32.ne - (i32.and - (local.get $x) - (i32.const 1) - ) - (i32.const 1) - )) - ;; i32(bool(expr)) ^ 1 -> !bool(expr) - (drop (i32.xor - (i32.and - (local.get $x) - (i32.const 1) - ) - (i32.const 1) - )) - ;; i64(bool(expr)) ^ 1 -> extend(!bool(expr)) - (drop (i64.xor - (i64.and - (local.get $y) - (i64.const 1) - ) - (i64.const 1) - )) - ;; i64(bool(expr)) != 0 -> i32(bool(expr)) - (drop (i64.ne - (i64.shr_u - (local.get $y) - (i64.const 63) - ) - (i64.const 0) - )) - ;; eqz((i32(bool(expr)) != 0) != 0) - (drop (i32.eqz - (i32.ne - (i32.ne - (i32.shr_u - (local.get $x) - (i32.const 31) - ) - (i32.const 0) - ) - (i32.const 0) - ) - )) - ;; i32.eqz(wrap(i64(x))) - (drop (i32.eqz - (i32.wrap_i64 - (i64.shr_u - (local.get $y) - (i64.const 63) - ) - ) - )) - ;; eqz((i64(bool(expr)) != 0) != 0) - (drop (i32.eqz - (i32.ne - (i64.ne - (i64.shr_u - (local.get $y) - (i64.const 63) - ) - (i64.const 0) - ) - (i32.const 0) - ) - )) - ;; eqz((i64(bool(expr)) != 0) != 0) - (drop (i32.eqz - (i32.ne - (i64.ne - (local.get $y) - (i64.const 0) - ) - (i32.const 0) - ) - )) - ;; i32.eqz(wrap(i64(x))) -> skip - (drop (i32.eqz - (i32.wrap_i64 - (local.get $y) - ) - )) - ;; i64(bool(expr)) == 1 -> i32(bool(expr)) - (drop (i64.eq - (i64.and - (local.get $y) - (i64.const 1) - ) - (i64.const 1) - )) - ;; i64(bool(expr)) != 1 -> !i64(bool(expr)) - (drop (i64.ne - (i64.and - (local.get $y) - (i64.const 1) - ) - (i64.const 1) - )) - ;; i32(bool(expr)) & 1 -> bool(expr) - (drop (i32.and - (i32.and - (local.get $x) - (i32.const 1) - ) - (i32.const 1) - )) - ;; i32(bool(expr)) | 1 -> 1 - (drop (i32.or - (i32.and - (local.get $x) - (i32.const 1) - ) - (i32.const 1) - )) - ;; i64(bool(expr)) & 1 -> i64(bool(expr)) - (drop (i64.and - (i64.and - (local.get $y) - (i64.const 1) - ) - (i64.const 1) - )) - ;; i64(bool(expr)) | 1 -> 1 - (drop (i64.or - (i64.and - (local.get $y) - (i64.const 1) - ) - (i64.const 1) - )) - ;; i32(bool(expr)) != 0 -> i32(bool(expr)) - (drop (i32.ne - (i32.and - (local.get $x) - (i32.const 1) - ) - (i32.const 0) - )) - ;; i32(bool(expr)) != 0 -> i32(bool(expr)) - (drop (i32.ne - (i64.ne - (local.get $y) - (i64.const 0) - ) - (i32.const 0) - )) - ;; (i32(expr) != 0) != 0 -> (expr != 0) - (drop (i32.ne - (i32.ne - (local.get $x) - (i32.const 0) - ) - (i32.const 0) - )) - ;; (signed)x % 4 ? 1 : 0 - (drop (if (result i32) - (i32.rem_s - (local.get $x) - (i32.const 4) - ) - (i32.const 1) - (i32.const 0) - )) - ;; (signed)x % min_s ? 1 : 0 - (drop (if (result i32) - (i32.rem_s - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 1) - (i32.const 0) - )) - ) - ;; CHECK: (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rotl - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.rotl - ;; CHECK-NEXT: (i64.const -2) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64) - ;; ~(1 << x) -> rotl(-2, x) - (drop (i32.xor - (i32.shl - (i32.const 1) - (local.get $x) - ) - (i32.const -1) - )) - (drop (i64.xor - (i64.shl - (i64.const 1) - (local.get $z) - ) - (i64.const -1) - )) - ) - ;; CHECK: (func $getFallthrough - ;; CHECK-NEXT: (local $x0 i32) - ;; CHECK-NEXT: (local $x1 i32) - ;; CHECK-NEXT: (local $x2 i32) - ;; CHECK-NEXT: (local $x3 i32) - ;; CHECK-NEXT: (local $x4 i32) - ;; CHECK-NEXT: (local $x5 i32) - ;; CHECK-NEXT: (local $x6 i32) - ;; CHECK-NEXT: (local $x7 i32) - ;; CHECK-NEXT: (local.set $x0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x1 - ;; CHECK-NEXT: (local.tee $x2 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x3 - ;; CHECK-NEXT: (loop $loop-in (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x4 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x4) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x5 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x6 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $out (result i32) - ;; CHECK-NEXT: (local.set $x7 - ;; CHECK-NEXT: (br_if $out - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $getFallthrough ;; unit tests for Properties::getFallthrough - (local $x0 i32) - (local $x1 i32) - (local $x2 i32) - (local $x3 i32) - (local $x4 i32) - (local $x5 i32) - (local $x6 i32) - (local $x7 i32) - ;; the trivial case - (local.set $x0 (i32.const 1)) - (drop (i32.and (local.get $x0) (i32.const 7))) - ;; tees - (local.set $x1 (local.tee $x2 (i32.const 1))) - (drop (i32.and (local.get $x1) (i32.const 7))) - ;; loop - (local.set $x3 (loop (result i32) (i32.const 1))) - (drop (i32.and (local.get $x3) (i32.const 7))) - ;; if - two sides, can't - (local.set $x4 (if (result i32) (i32.const 1) (i32.const 2) (i32.const 3))) - (drop (i32.and (local.get $x4) (i32.const 7))) - ;; if - one side, can - (local.set $x5 (if (result i32) (i32.const 1) (unreachable) (i32.const 3))) - (drop (i32.and (local.get $x5) (i32.const 7))) - ;; if - one side, can - (local.set $x6 (if (result i32) (i32.const 1) (i32.const 3) (unreachable))) - (drop (i32.and (local.get $x6) (i32.const 7))) - ;; br_if with value - (drop - (block $out (result i32) - (local.set $x7 (br_if $out (i32.const 1) (i32.const 1))) - (drop (i32.and (local.get $x7) (i32.const 7))) - (unreachable) - ) - ) - ) - ;; CHECK: (func $tee-with-unreachable-value (result f64) - ;; CHECK-NEXT: (local $var$0 i32) - ;; CHECK-NEXT: (block $label$1 (result f64) - ;; CHECK-NEXT: (local.tee $var$0 - ;; CHECK-NEXT: (br_if $label$1 - ;; CHECK-NEXT: (f64.const 1) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $tee-with-unreachable-value (result f64) - (local $var$0 i32) - (block $label$1 (result f64) - (local.tee $var$0 - (br_if $label$1 ;; the f64 does not actually flow through this, it's unreachable (and the type is wrong - but unchecked) - (f64.const 1) - (unreachable) - ) - ) - ) - ) - ;; CHECK: (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) - (i32.add - (i32.add - (i32.sub - (i32.const 0) ;; this zero looks like we could remove it by subtracting the get of $temp from the parent, but that would reorder it *after* the tee :( - (local.get $temp) - ) - (local.tee $temp ;; cannot move this tee before the get - (i32.const 1) - ) - ) - (i32.const 2) - ) - ) - ;; CHECK: (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) - (i32.add - (i32.add - (local.tee $temp ;; in this order, the tee already comes first, so all is good for the optimization - (i32.const 1) - ) - (i32.sub - (i32.const 0) - (local.get $temp) - ) - ) - (i32.const 2) - ) - ) - ;; CHECK: (func $const-float-zero (param $fx f32) (param $fy f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.add - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f32.const -0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const -0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.add - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.add - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (f32.const -nan:0x34546d) - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $const-float-zero (param $fx f32) (param $fy f64) - ;; x - 0.0 ==> x - (drop (f32.sub - (local.get $fx) - (f32.const 0) - )) - (drop (f64.sub - (local.get $fy) - (f64.const 0) - )) - ;; x + (-0.0) ==> x - (drop (f32.add - (local.get $fx) - (f32.const -0) - )) - (drop (f64.add - (local.get $fy) - (f64.const -0) - )) - ;; x - (-0.0) ==> x + 0.0 - (drop (f32.sub - (local.get $fx) - (f32.const -0) ;; skip - )) - (drop (f64.sub - (local.get $fy) - (f64.const -0) ;; skip - )) - ;; 0.0 - x ==> 0.0 - x - (drop (f32.sub - (f32.const 0) - (local.get $fx) ;; skip - )) - (drop (f64.sub - (f64.const 0) - (local.get $fy) ;; skip - )) - ;; x + 0.0 ==> x + 0.0 - (drop (f32.add - (local.get $fx) ;; skip - (f32.const 0) - )) - (drop (f64.add - (local.get $fy) ;; skip - (f64.const 0) - )) - (drop (f32.sub - (f32.const -nan:0x34546d) ;; skip - (f32.const 0) - )) - ) - ;; CHECK: (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (f32.const -0) - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (f64.const -0) - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) - (drop (i32.sub - (local.get $x) - (i32.const -1) - )) - (drop (i64.sub - (local.get $y) - (i64.const -1) - )) - ;; (unsigned)x > -1 ==> 0 - (drop (i32.gt_u - (local.get $x) - (i32.const -1) - )) - (drop (i64.gt_u - (local.get $y) - (i64.const -1) - )) - (drop (i32.gt_s - (local.get $x) - (i32.const -1) - )) - (drop (i64.gt_s - (local.get $y) - (i64.const -1) - )) - (drop (i64.extend_i32_s - (i64.gt_u - (i64.const 0) - (i64.const -1) - ) - )) - ;; (unsigned)x <= -1 ==> 1 - (drop (i32.le_u - (local.get $x) - (i32.const -1) - )) - (drop (i64.le_u - (local.get $y) - (i64.const -1) - )) - (drop (i32.le_s - (local.get $x) - (i32.const -1) - )) - (drop (i64.le_s - (local.get $y) - (i64.const -1) - )) - ;; (unsigned)x >= -1 ==> x == -1 - (drop (i32.ge_u - (local.get $x) - (i32.const -1) - )) - (drop (i64.ge_u - (local.get $y) - (i64.const -1) - )) - ;; (unsigned)x < -1 ==> x != -1 - (drop (i32.lt_u - (local.get $x) - (i32.const -1) - )) - (drop (i64.lt_u - (local.get $y) - (i64.const -1) - )) - ;; x * -1 - (drop (i32.mul - (local.get $x) - (i32.const -1) - )) - (drop (i64.mul - (local.get $y) - (i64.const -1) - )) - (drop (f32.mul ;; skip - (local.get $fx) - (f32.const -1) - )) - (drop (f64.mul ;; skip - (local.get $fy) - (f64.const -1) - )) - ;; (unsigned)x / -1 - (drop (i32.div_u - (local.get $x) - (i32.const -1) - )) - (drop (i64.div_u - (local.get $y) - (i64.const -1) - )) - ) - ;; CHECK: (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -9223372036854775808) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.div_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 63) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 9223372036854775807) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -9223372036854775808) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const -9223372036854775808) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 9223372036854775807) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (f32.const -0) - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const 2.1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $fx) - ;; CHECK-NEXT: (f32.const -inf) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: (f64.const -nan:0x8000000000000) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (f64.const -5) - ;; CHECK-NEXT: (local.get $fy) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) - ;; signed divs - ;; i32(x) / -2147483648 -> x == -2147483648 - (drop (i32.div_s - (local.get $x) - (i32.const -2147483648) - )) - ;; i64(x) / -9223372036854775808 -> x == -9223372036854775808 - (drop (i64.div_s - (local.get $y) - (i64.const -9223372036854775808) - )) - ;; skip - (drop (i64.div_s - (local.get $y) - (i64.const -2147483648) - )) - - ;; unsigned divs - ;; u32(x) / -2 => x >= -2 - (drop (i32.div_u - (local.get $x) - (i32.const -2) - )) - ;; u32(x) / -1 => x == -1 - (drop (i32.div_u - (local.get $x) - (i32.const -1) - )) - ;; u32(x) / (i32.min + 1) - (drop (i32.div_u - (local.get $x) - (i32.const -2147483647) - )) - ;; u32(x) / i32.min => x >>> 31 - (drop (i32.div_u - (local.get $x) - (i32.const -2147483648) - )) - ;; u64(x) / -1 => u64(x == -1) - (drop (i64.div_u - (local.get $y) - (i64.const -1) - )) - ;; u64(x) / i64.min => x >>> 63 - (drop (i64.div_u - (local.get $y) - (i64.const -9223372036854775808) - )) - - ;; (unsigned)x >= 0 => i32(1) - (drop (i32.ge_u - (local.get $x) - (i32.const 0) - )) - (drop (i64.ge_u - (local.get $y) - (i64.const 0) - )) - - ;; (unsigned)x < 0 => i32(0) - (drop (i32.lt_u - (local.get $x) - (i32.const 0) - )) - (drop (i64.lt_u - (local.get $y) - (i64.const 0) - )) - - ;; (unsigned)x > 0 => x != 0 - (drop (i32.gt_u - (local.get $x) - (i32.const 0) - )) - (drop (i64.gt_u - (local.get $y) - (i64.const 0) - )) - - ;; (unsigned)x <= 0 => x == 0 - (drop (i32.le_u - (local.get $x) - (i32.const 0) - )) - (drop (i64.le_u - (local.get $y) - (i64.const 0) - )) - - ;; i32(x) <= 0x7fffffff => i32(1) - (drop (i32.le_s - (local.get $x) - (i32.const 0x7fffffff) - )) - ;; i64(x) <= 0x7fffffffffffffff => i32(1) - (drop (i64.le_s - (local.get $y) - (i64.const 0x7fffffffffffffff) - )) - - ;; i32(x) >= 0x80000000 => i32(1) - (drop (i32.ge_s - (local.get $x) - (i32.const 0x80000000) - )) - ;; i64(x) >= 0x8000000000000000 => i32(1) - (drop (i64.ge_s - (local.get $y) - (i64.const 0x8000000000000000) - )) - - ;; i32(x) < 0x80000000 => 0 - (drop (i32.lt_s - (local.get $x) - (i32.const 0x80000000) - )) - ;; i64(x) < 0x8000000000000000 => 0 - (drop (i64.lt_s - (local.get $y) - (i64.const 0x8000000000000000) - )) - - ;; i32(x) > 0x7fffffff => 0 - (drop (i32.gt_s - (local.get $x) - (i32.const 0x7fffffff) - )) - ;; i64(x) > 0x7fffffffffffffff => 0 - (drop (i64.gt_s - (local.get $y) - (i64.const 0x7fffffffffffffff) - )) - - ;; i32(x) < 0x7fffffff => x != 0x7fffffff - (drop (i32.lt_s - (local.get $x) - (i32.const 0x7fffffff) - )) - ;; i64(x) < 0x7fffffffffffffff => x != 0x7fffffffffffffff - (drop (i64.lt_s - (local.get $y) - (i64.const 0x7fffffffffffffff) - )) - - ;; i32(x) > 0x80000000 => x != 0x80000000 - (drop (i32.gt_s - (local.get $x) - (i32.const 0x80000000) - )) - ;; i64(x) > 0x8000000000000000 => x != 0x8000000000000000 - (drop (i64.gt_s - (local.get $y) - (i64.const 0x8000000000000000) - )) - - ;; i32(x) <= 0x80000000 => x == 0x80000000 - (drop (i32.le_s - (local.get $x) - (i32.const 0x80000000) - )) - ;; i64(x) <= 0x8000000000000000 => x == 0x8000000000000000 - (drop (i64.le_s - (local.get $y) - (i64.const 0x8000000000000000) - )) - - ;; i32(x) >= 0x7fffffff => x == 0x7fffffff - (drop (i32.ge_s - (local.get $x) - (i32.const 0x7fffffff) - )) - ;; i64(x) >= 0x7fffffffffffffff => x == 0x7fffffffffffffff - (drop (i64.ge_s - (local.get $y) - (i64.const 0x7fffffffffffffff) - )) - - ;; -x * 1 => x * -1 - (drop (f32.mul - (f32.neg - (local.get $fx) - ) - (f32.const 1) - )) - ;; -x * -2.1 => x * 2.1 - (drop (f64.mul - (f64.neg - (local.get $fy) - ) - (f64.const -2.1) - )) - ;; 2 * -x => x * -2 - (drop (f64.mul - (f64.const 2) - (f64.neg - (local.get $fy) - ) - )) - ;; -x / inf => x / -inf - (drop (f32.div - (f32.neg - (local.get $fx) - ) - (f32.const inf) - )) - ;; -x / -0.0 => x / 0.0 - (drop (f64.div - (f64.neg - (local.get $fy) - ) - (f64.const -0.0) - )) - ;; -x / nan => x / -nan - (drop (f64.div - (f64.neg - (local.get $fy) - ) - (f64.const nan) - )) - ;; 5.0 / -x => -5 / x - (drop (f64.div - (f64.const 5) - (f64.neg - (local.get $fy) - ) - )) - ) - ;; CHECK: (func $lhs-is-neg-one (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $lhs-is-neg-one (param $x i32) (param $y i64) - ;; -1 >> x ==> -1 - (drop (i32.shr_s - (i32.const -1) - (local.get $x) - )) - (drop (i64.shr_s - (i64.const -1) - (local.get $y) - )) - ;; rotl(-1, x) ==> -1 - (drop (i32.rotl - (i32.const -1) - (local.get $x) - )) - (drop (i64.rotl - (i64.const -1) - (local.get $y) - )) - ;; rotr(-1, x) ==> -1 - (drop (i32.rotr - (i32.const -1) - (local.get $x) - )) - (drop (i64.rotr - (i64.const -1) - (local.get $y) - )) - ;; skip - (drop (i32.shr_s - (i32.const -1) - (call $ne0) ;; side effect - )) - ;; skip - (drop (i32.shr_u - (i32.const -1) - (local.get $x) - )) - ) - ;; CHECK: (func $lhs-is-const (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (i64.const -2) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $lhs-is-const (param $x i32) (param $y i64) - ;; 0 - (x - 1) - (drop (i32.sub - (i32.const 0) - (i32.sub - (local.get $x) - (i32.const 1) - ) - )) - (drop (i64.sub - (i64.const 0) - (i64.sub - (local.get $y) - (i64.const 1) - ) - )) - ;; -1 - (x + 1) - (drop (i32.sub - (i32.const -1) - (i32.add - (local.get $x) - (i32.const 1) - ) - )) - (drop (i64.sub - (i64.const -1) - (i64.add - (local.get $y) - (i64.const 1) - ) - )) - ;; 1 - (2 - x) - (drop (i32.sub - (i32.const 1) - (i32.sub - (i32.const 2) - (local.get $x) - ) - )) - (drop (i64.sub - (i64.const 1) - (i64.sub - (i64.const 2) - (local.get $y) - ) - )) - ;; 0 - (0x80000000 - x) - (drop (i32.sub - (i32.const 0) - (i32.sub - (i32.const 0x80000000) - (local.get $x) - ) - )) - ) - ;; CHECK: (func $pre-combine-or (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pre-combine-or (param $x i32) (param $y i32) - (drop (i32.or - (i32.gt_s - (local.get $x) - (local.get $y) - ) - (i32.eq - (local.get $y) ;; ordering should not stop us - (local.get $x) - ) - )) - (drop (i32.or - (i32.eq ;; ordering should not stop us - (local.get $y) - (local.get $x) - ) - (i32.gt_s - (local.get $x) - (local.get $y) - ) - )) - (drop (i32.or - (i32.gt_s - (local.get $x) - (local.get $y) - ) - (i32.eq - (local.get $x) - (i32.const 1) ;; not equal - ) - )) - (drop (i32.or - (i32.gt_s - (local.get $x) - (i32.const 1) ;; not equal - ) - (i32.eq - (local.get $x) - (local.get $y) - ) - )) - (drop (i32.or - (i32.gt_s - (call $ne0) ;; side effects - (local.get $y) - ) - (i32.eq - (call $ne0) - (local.get $y) - ) - )) - (drop (i32.or - (i32.gt_s - (local.get $y) - (call $ne0) ;; side effects - ) - (i32.eq - (local.get $y) - (call $ne0) - ) - )) - ) - ;; CHECK: (func $combine-or (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $combine-or (param $x i32) (param $y i32) - (drop (i32.or - (i32.gt_s - (local.get $x) - (local.get $y) - ) - (i32.eq - (local.get $x) - (local.get $y) - ) - )) - ;; TODO: more stuff here - ) - ;; CHECK: (func $select-into-arms (param $x i32) (param $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-into-arms (param $x i32) (param $y i32) - (if - (select - (i32.eqz (i32.eqz (local.get $x))) - (i32.eqz (i32.eqz (local.get $y))) - (local.get $y) - ) - (unreachable) - ) - ) - ;; CHECK: (func $select-with-same-arm-and-cond-32 (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-with-same-arm-and-cond-32 (param $x i32) - ;; i32(x) ? i32(x) : 0 ==> x - (drop (select - (local.get $x) - (i32.const 0) - (local.get $x) - )) - ;; i32(x) ? 0 : i32(x) ==> {x, 0} - (drop (select - (i32.const 0) - (local.get $x) - (local.get $x) - )) - ;; i32(x) == 0 ? i32(x) : 0 ==> {x, 0} - (drop (select - (local.get $x) - (i32.const 0) - (i32.eqz (local.get $x)) - )) - ) - - ;; CHECK: (func $select-with-same-arm-and-cond-64 (param $x i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-with-same-arm-and-cond-64 (param $x i64) - ;; i64(x) != 0 ? i64(x) : 0 ==> x - (drop (select - (local.get $x) - (i64.const 0) - (i64.ne - (local.get $x) - (i64.const 0) - ) - )) - ;; i64(x) == 0 ? 0 : i64(x) ==> x - (drop (select - (i64.const 0) - (local.get $x) - (i64.eqz - (local.get $x) - ) - )) - ;; i64(x) != 0 ? 0 : i64(x) ==> 0 - (drop (select - (i64.const 0) - (local.get $x) - (i64.ne - (local.get $x) - (i64.const 0) - ) - )) - ;; i64(x) == 0 ? i64(x) : 0 ==> {x, 0} - (drop (select - (local.get $x) - (i64.const 0) - (i64.eqz - (local.get $x) - ) - )) - (drop (select - (local.get $x) - (i64.const 0) - (i64.eq - (local.get $x) - (i64.const 0) - ) - )) - ) - - ;; CHECK: (func $select-with-same-arm-and-cond-skips (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-with-same-arm-and-cond-skips (param $x i32) (param $y i64) - ;; skip not equals - (drop (select - (local.get $x) - (i32.const 0) - (i32.wrap_i64 (local.get $y)) - )) - (drop (select - (i32.const 0) - (i32.sub (i32.const 0) (local.get $x)) - (local.get $x) - )) - - ;; skip not zero - (drop (select - (local.get $x) - (i32.const -1) - (local.get $x) - )) - (drop (select - (i32.const -1) - (local.get $x) - (local.get $x) - )) - (drop (select - (i64.const -1) - (local.get $y) - (i64.ne - (local.get $y) - (i64.const 0) - ) - )) - (drop (select - (i64.const 0) - (local.get $y) - (i64.ne - (local.get $y) - (i64.const 1) - ) - )) - ) - - ;; CHECK: (func $select-with-same-arm-and-cond-skips-side-effects (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (call $select-sign-64-lt - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (call $select-sign-64-lt - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (call $select-sign-64-lt - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (call $select-sign-64-lt - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $select-with-same-arm-and-cond-skips-side-effects (param $x i32) (param $y i64) - ;; skip with side effects - (drop (select - (i32.div_u (i32.const 10) (local.get $x)) - (i32.const 0) - (i32.div_u (i32.const 10) (local.get $x)) - )) - (drop (select - (i32.const 0) - (call $ne0) - (call $ne0) - )) - (drop (select - (call $select-sign-64-lt (local.get $y)) - (i64.const 0) - (i64.eqz - (call $select-sign-64-lt (local.get $y)) - ) - )) - (drop (select - (i64.const 0) - (call $select-sign-64-lt (local.get $y)) - (i64.eqz - (call $select-sign-64-lt (local.get $y)) - ) - )) - ) - ;; CHECK: (func $optimize-boolean-context (param $x i32) (param $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-boolean-context (param $x i32) (param $y i32) - ;; 0 - x ==> x - (if - (i32.sub - (i32.const 0) - (local.get $x) - ) - (unreachable) - ) - (drop (select - (local.get $x) - (local.get $y) - (i32.sub - (i32.const 0) - (local.get $x) - ) - )) - ) - - ;; CHECK: (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0 - (drop (i32.and - (i32.eq (local.get $x) (i32.const 0)) - (i32.eq (local.get $y) (i32.const 0)) - )) - ;; (i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0 - (drop (i32.and - (i64.eq (local.get $a) (i64.const 0)) - (i64.eq (local.get $b) (i64.const 0)) - )) - ) - ;; CHECK: (func $optimize-combined-by-or-noequal-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-or-noequal-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) != 0) | (i32(y) != 0) ==> i32(x | y) != 0 - (drop (i32.or - (i32.ne (local.get $x) (i32.const 0)) - (i32.ne (local.get $y) (i32.const 0)) - )) - ;; (i64(x) != 0) | (i64(y) != 0) ==> i64(x | y) != 0 - (drop (i32.or - (i64.ne (local.get $a) (i64.const 0)) - (i64.ne (local.get $b) (i64.const 0)) - )) - ) - ;; CHECK: (func $optimize-combined-by-or-gt-or-eq-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-or-gt-or-eq-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) >= 0) | (i32(y) >= 0) ==> i32(x & y) >= 0 - (drop (i32.or - (i32.ge_s (local.get $x) (i32.const 0)) - (i32.ge_s (local.get $y) (i32.const 0)) - )) - ;; (i64(x) >= 0) | (i64(y) >= 0) ==> i64(x & y) >= 0 - (drop (i32.or - (i64.ge_s (local.get $a) (i64.const 0)) - (i64.ge_s (local.get $b) (i64.const 0)) - )) - - ;; skips - ;; (i32(x) >= 0) | (i64(y) >= 0) ==> skip - (drop (i32.or - (i32.ge_s (local.get $x) (i32.const 0)) - (i64.ge_s (local.get $a) (i64.const 0)) - )) - ) - ;; CHECK: (func $optimize-combined-by-or-ne-to-minus-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-or-ne-to-minus-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) != -1) | (i32(y) != -1) ==> i32(x & y) != -1 - (drop (i32.or - (i32.ne (local.get $x) (i32.const -1)) - (i32.ne (local.get $y) (i32.const -1)) - )) - ;; (i64(x) != -1) | (i64(y) == -1) ==> i64(x & y) != -1 - (drop (i32.or - (i64.ne (local.get $a) (i64.const -1)) - (i64.ne (local.get $b) (i64.const -1)) - )) - - ;; skips - ;; (i32(x) != -1) | (i64(y) != -1) ==> skip - (drop (i32.or - (i32.ne (local.get $x) (i32.const -1)) - (i64.ne (local.get $a) (i64.const -1)) - )) - ) - ;; CHECK: (func $optimize-combined-by-or-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-or-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) < 0) | (i32(y) < 0) ==> i32(x | y) < 0 - (drop (i32.or - (i32.lt_s (local.get $x) (i32.const 0)) - (i32.lt_s (local.get $y) (i32.const 0)) - )) - ;; (i64(x) < 0) | (i64(y) < 0) ==> i64(x | y) < 0 - (drop (i32.or - (i64.lt_s (local.get $a) (i64.const 0)) - (i64.lt_s (local.get $b) (i64.const 0)) - )) - - ;; skips - ;; (i32(x) < 0) | (i64(a) < 0) ==> skip - (drop (i32.or - (i32.lt_s (local.get $x) (i32.const 0)) - (i64.lt_s (local.get $a) (i64.const 0)) - )) - ;; (i32(x) <= 0) | (i32(y) < 0) ==> skip - (drop (i32.or - (i32.le_s (local.get $x) (i32.const 0)) - (i32.lt_s (local.get $y) (i32.const 0)) - )) - ;; (i32(x) < 1) | (i32(y) < 0) ==> skip - (drop (i32.or - (i32.lt_s (local.get $x) (i32.const 1)) - (i32.lt_s (local.get $y) (i32.const 0)) - )) - ) - ;; CHECK: (func $optimize-combined-by-and-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.lt_s - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-and-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) < 0) & (i32(y) < 0) ==> i32(x & y) < 0 - (drop (i32.and - (i32.lt_s (local.get $x) (i32.const 0)) - (i32.lt_s (local.get $y) (i32.const 0)) - )) - ;; (i64(x) < 0) & (i64(y) < 0) ==> i64(x & y) < 0 - (drop (i32.and - (i64.lt_s (local.get $a) (i64.const 0)) - (i64.lt_s (local.get $b) (i64.const 0)) - )) - ) - ;; CHECK: (func $optimize-combined-by-and-greatequal-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (i64.or - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.ge_s - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-and-greatequal-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) >= 0) & (i32(y) >= 0) ==> i32(x | y) >= 0 - (drop (i32.and - (i32.ge_s (local.get $x) (i32.const 0)) - (i32.ge_s (local.get $y) (i32.const 0)) - )) - ;; (i64(x) >= 0) & (i64(y) >= 0) ==> i64(x | y) >= 0 - (drop (i32.and - (i64.ge_s (local.get $a) (i64.const 0)) - (i64.ge_s (local.get $b) (i64.const 0)) - )) - - ;; skips - ;; (i32(x) >= 0) & (i64(y) >= 0) ==> skip - (drop (i32.and - (i32.ge_s (local.get $x) (i32.const 0)) - (i64.ge_s (local.get $a) (i64.const 0)) - )) - ) - ;; CHECK: (func $optimize-combined-by-and-equal-neg-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (local.get $b) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $a) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-combined-by-and-equal-neg-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) - ;; (i32(x) == -1) & (i32(y) == -1) ==> i32(x & y) == -1 - (drop (i32.and - (i32.eq (local.get $x) (i32.const -1)) - (i32.eq (local.get $y) (i32.const -1)) - )) - ;; (i64(x) == -1) & (i64(y) == -1) ==> i64(x & y) == -1 - (drop (i32.and - (i64.eq (local.get $a) (i64.const -1)) - (i64.eq (local.get $b) (i64.const -1)) - )) - - ;; skips - ;; (i32(x) == -1) & (i64(y) == -1) ==> skip - (drop (i32.and - (i32.eq (local.get $x) (i32.const -1)) - (i64.eq (local.get $a) (i64.const -1)) - )) - ) - ;; CHECK: (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: (local.get $Y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: (local.get $Y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.ne - ;; CHECK-NEXT: (local.get $X) - ;; CHECK-NEXT: (local.get $Y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block $block23 (result i32) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64) - ;; eqz(x + 0x7FFFFFFF) -> x == -2147483647 - (drop (i32.eqz - (i32.add - (local.get $x) - (i32.const 0x7FFFFFFF) - ) - )) - ;; eqz(x + 0x80000000) -> x == -2147483648 - (drop (i32.eqz - (i32.add - (local.get $x) - (i32.const 0x80000000) - ) - )) - ;; eqz(x + 0x80000001) -> x == 2147483647 - (drop (i32.eqz - (i32.add - (local.get $x) - (i32.const 0x80000001) - ) - )) - ;; eqz(x - y) - (drop (i32.eqz - (i32.sub - (local.get $x) - (local.get $y) - ) - )) - (drop (i64.eqz - (i64.sub - (local.get $X) - (local.get $Y) - ) - )) - ;; x - y == 0 - (drop (i32.eq - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - (drop (i64.eq - (i64.sub - (local.get $X) - (local.get $Y) - ) - (i64.const 0) - )) - ;; x - y != 0 - (drop (i32.ne - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - (drop (i64.ne - (i64.sub - (local.get $X) - (local.get $Y) - ) - (i64.const 0) - )) - ;; i32(x - y) > 0 -> x > y - (drop (i32.gt_s - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; i32(x - y) >= 0 -> x >= y - (drop (i32.ge_s - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; u32(x - y) > 0 -> x != y - (drop (i32.gt_u - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; u32(x - y) >= 0 -> 1 - (drop (i32.ge_u - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; u64(x - y) >= 0 -> i32(1) - (drop (i64.ge_u - (i64.sub - (local.get $X) - (local.get $Y) - ) - (i64.const 0) - )) - ;; i32(x - y) < 0 -> x < y - (drop (i32.lt_s - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; i32(x - y) <= 0 -> x <= y - (drop (i32.le_s - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; u32(x - y) < 0 -> 0 - (drop (i32.lt_u - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; u64(x - y) < 0 -> i32(0) - (drop (i64.lt_u - (i64.sub - (local.get $X) - (local.get $Y) - ) - (i64.const 0) - )) - ;; u32(x - y) <= 0 -> x == y - (drop (i32.le_u - (i32.sub - (local.get $x) - (local.get $y) - ) - (i32.const 0) - )) - ;; i32(x - 0x80000000) == 0 -> x == 0x80000000 - (drop (i32.eq - (i32.sub - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 0) - )) - ;; i32(x - 0x80000000) != 0 -> x == 0x80000000 - (drop (i32.ne - (i32.sub - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 0) - )) - ;; i32(x - { 0x80000000 }) < 0 -> skip - (drop (i32.lt_s - (i32.sub - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 0) - )) - ;; i32(x - { 0x80000000 }) >= 0 -> skip - (drop (i32.ge_s - (i32.sub - (local.get $x) - (i32.const 0x80000000) - ) - (i32.const 0) - )) - ;; i32(x - { 0x80000000 }) > 0 -> skip - (drop (i32.gt_s - (i32.sub - (local.get $x) - (block (result i32) - (i32.const 0x80000000) - ) - ) - (i32.const 0) - )) - ;; i32(x - { 0x80000000 }) <= 0 -> skip - (drop (i32.gt_s - (i32.sub - (local.get $x) - (block (result i32) - (i32.const 0x80000000) - ) - ) - (i32.const 0) - )) - ) - ;; CHECK: (func $unsigned-context (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -2147483648) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 9223372036854775807) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.div_s - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 9223372036854775807) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unsigned-context (param $x i32) (param $y i64) - (drop (i32.div_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const 3) - )) - (drop (i32.div_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const -3) ;; skip - )) - (drop (i32.div_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const 0x80000000) ;; skip - )) - (drop (i64.div_s - (i64.and - (local.get $y) - (i64.const 0x7fffffffffffffff) - ) - (i64.const 2) - )) - (drop (i64.div_s - (i64.and - (local.get $y) - (i64.const 0x7fffffffffffffff) - ) - (i64.const -1) ;; skip - )) - (drop (i32.rem_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const 3) - )) - (drop (i32.shr_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const 7) - )) - (drop (i32.ge_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const 7) - )) - (drop (i32.ge_s - (i32.and - (local.get $x) - (i32.const 0x7fffffff) - ) - (i32.const -7) ;; skip - )) - ) - ;; CHECK: (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (call $tee-with-unreachable-value) - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (f64.const -2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32) - (drop (f64.mul - (local.get $0) - (f64.const 2) - )) - (drop (f32.mul - (local.get $1) - (f32.const 2) - )) - - (drop (f64.mul - (call $tee-with-unreachable-value) ;; side effect - (f64.const 2) - )) - (drop (f64.mul - (f64.neg (local.get $0)) ;; complex expression - (f64.const 2) - )) - ) - ;; CHECK: (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.ceil - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.floor - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.trunc - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.nearest - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.nearest - ;; CHECK-NEXT: (f64.trunc - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.trunc - ;; CHECK-NEXT: (f64.nearest - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $ne0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (i32.rem_s - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (i32.xor - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) - ;; unary - (drop (f64.abs (f64.abs (local.get $w)))) - (drop (f64.ceil (f64.ceil (local.get $w)))) - (drop (f64.floor (f64.floor (local.get $w)))) - (drop (f64.trunc (f64.trunc (local.get $w)))) - (drop (f64.nearest (f64.nearest (local.get $w)))) - - (drop (f64.nearest (f64.trunc (local.get $w)))) ;; skip - (drop (f64.trunc (f64.nearest (local.get $w)))) ;; skip - - (drop (f64.neg (f64.neg (local.get $w)))) - (drop (f64.neg (f64.neg (f64.neg (local.get $w))))) - (drop (f64.neg (f64.neg (f64.neg (f64.neg (local.get $w)))))) - - (drop (i32.eqz (i32.eqz (local.get $x)))) ;; skip - (drop (i32.eqz (i32.eqz (i32.eqz (local.get $x))))) - (drop (i32.eqz (i32.eqz (i64.eqz (i64.const 1))))) - (drop (i32.eqz (i32.eqz (i32.ne (local.get $x) (i32.const 2))))) - - (drop (i32.eqz - (i32.eqz - (i32.and - (local.get $x) - (i32.const 1) - ) - ) - )) - - ;; binary - ;; ((signed)x % y) % y - (drop (i32.rem_s - (i32.rem_s - (local.get $x) - (local.get $y) - ) - (local.get $y) - )) - ;; ((unsigned)x % y) % y - (drop (i32.rem_u - (i32.rem_u - (local.get $x) - (local.get $y) - ) - (local.get $y) - )) - ;; 0 - (0 - y) - (drop (i32.sub - (i32.const 0) - (i32.sub - (i32.const 0) - (local.get $y) - ) - )) - ;; x - (x - y) - (drop (i32.sub - (local.get $x) - (i32.sub - (local.get $x) - (local.get $y) - ) - )) - ;; y - (x - y) - skip - (drop (i32.sub - (local.get $y) - (i32.sub - (local.get $x) - (local.get $y) - ) - )) - ;; x ^ (x ^ y) - (drop (i32.xor - (local.get $x) - (i32.xor - (local.get $x) - (local.get $y) - ) - )) - ;; x ^ (y ^ x) - (drop (i32.xor - (local.get $x) - (i32.xor - (local.get $y) - (local.get $x) - ) - )) - ;; (x ^ y) ^ x - (drop (i32.xor - (i32.xor - (local.get $x) - (local.get $y) - ) - (local.get $x) - )) - ;; (y ^ x) ^ x - (drop (i32.xor - (i32.xor - (local.get $y) - (local.get $x) - ) - (local.get $x) - )) - ;; x ^ (x ^ x) - (drop (i32.xor - (local.get $x) - (i32.xor - (local.get $x) - (local.get $x) - ) - )) - ;; x & (x & y) - (drop (i32.and - (local.get $x) - (i32.and - (local.get $x) - (local.get $y) - ) - )) - ;; x & (y & x) - (drop (i32.and - (local.get $x) - (i32.and - (local.get $y) - (local.get $x) - ) - )) - ;; (x & y) & x - (drop (i32.and - (i32.and - (local.get $x) - (local.get $y) - ) - (local.get $x) - )) - ;; (y & x) & x - (drop (i32.and - (i32.and - (local.get $y) - (local.get $x) - ) - (local.get $x) - )) - ;; x | (x | y) - (drop (i32.or - (local.get $x) - (i32.or - (local.get $x) - (local.get $y) - ) - )) - ;; x | (y | x) - (drop (i32.or - (local.get $x) - (i32.or - (local.get $y) - (local.get $x) - ) - )) - ;; (x | y) | x - (drop (i32.or - (i32.or - (local.get $x) - (local.get $y) - ) - (local.get $x) - )) - ;; (y | x) | x - (drop (i32.or - (i32.or - (local.get $y) - (local.get $x) - ) - (local.get $x) - )) - ;; (y | x) | z - skip - (drop (i32.or - (i32.or - (local.get $y) - (local.get $x) - ) - (local.get $z) - )) - ;; (z | x) | y - skip - (drop (i32.or - (i32.or - (local.get $z) - (local.get $x) - ) - (local.get $y) - )) - ;; (SE() | x) | x - (drop (i32.or - (i32.or - (call $ne0) ;; side effect - (local.get $x) - ) - (local.get $x) - )) - ;; (x | SE()) | SE() - skip - (drop (i32.or - (i32.or - (local.get $x) - (call $ne0) ;; side effect - ) - (call $ne0) ;; side effect - )) - ;; x | (SE() | x) - (drop (i32.or - (local.get $x) - (i32.or - (local.get $x) - (call $ne0) ;; side effect - ) - )) - ;; SE() | (x | SE()) - skip - (drop (i32.or - (call $ne0) ;; side effect - (i32.or - (call $ne0) ;; side effect - (local.get $x) - ) - )) - ;; (y % x) % y - skip - (drop (i32.rem_s - (i32.rem_s - (local.get $y) - (local.get $x) - ) - (local.get $y) - )) - ;; y % (x % y) - skip - (drop (i32.rem_u - (local.get $y) - (i32.rem_u - (local.get $x) - (local.get $y) - ) - )) - ;; x | (y | x) where x and y cannot be reordered - skip - (drop - (i32.or - (local.get $x) - (i32.or - (local.tee $x - (i32.const 1) - ) - (local.get $x) - ) - ) - ) - (drop - (i32.or - (i32.or - (local.get $x) - (local.tee $x - (i32.const 1) - ) - ) - (local.get $x) - ) - ) - ;; x ^ (y ^ x) where x and y cannot be reordered - skip - (drop - (i32.xor - (local.get $x) - (i32.xor - (local.tee $x - (i32.const 1) - ) - (local.get $x) - ) - ) - ) - (drop - (i32.xor - (i32.xor - (local.get $x) - (local.tee $x - (i32.const 1) - ) - ) - (local.get $x) - ) - ) - ) - - ;; i32.wrap_i64(i64.extend_i32_s(x)) ==> x - ;; i32.wrap_i64(i64.extend_i32_u(x)) ==> x - - ;; CHECK: (func $sign-and-zero-extention-elimination-1 (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-and-zero-extention-elimination-1 (param $x i32) - (drop (i32.wrap_i64 (i64.extend_i32_s (local.get $x)))) - (drop (i32.wrap_i64 (i64.extend_i32_u (local.get $x)))) - ) - ;; i64.extend_i32_u(i32.wrap_i64(x)) => x, where maxBits(x) <= 32 - ;; i64.extend_i32_s(i32.wrap_i64(x)) => x, where maxBits(x) <= 31 - - ;; CHECK: (func $sign-and-zero-extention-elimination-2 (param $x i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 4294967295) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 2147483647) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_s - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 4294967295) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sign-and-zero-extention-elimination-2 (param $x i64) - (drop (i64.extend_i32_u (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x00000000FFFFFFFF))))) - (drop (i64.extend_i32_s (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x000000007FFFFFFF))))) - - (drop (i64.extend_i32_u (i32.wrap_i64 (local.get $x)))) ;; skip - (drop (i64.extend_i32_s (i32.wrap_i64 (local.get $x)))) ;; skip - (drop (i64.extend_i32_s (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x00000000FFFFFFFF))))) ;; skip - ) - ;; CHECK: (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shr_s - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shl - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: (i64.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.shr_u - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (i64.and - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: (i64.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64) - ;; i32 - (drop (i32.shl - (local.get $x) - (i32.const 32) - )) - (drop (i32.shr_s - (local.get $x) - (i32.const 32) - )) - (drop (i32.shr_u - (local.get $x) - (i32.const 64) - )) - (drop (i32.rotl - (local.get $x) - (i32.const 64) - )) - (drop (i32.rotr - (local.get $x) - (i32.const 64) - )) - ;; i64 - (drop (i64.shl - (local.get $z) - (i64.const 64) - )) - (drop (i64.shr_s - (local.get $z) - (i64.const 64) - )) - (drop (i64.shr_u - (local.get $z) - (i64.const 128) - )) - (drop (i64.rotl - (local.get $z) - (i64.const 128) - )) - (drop (i64.rotr - (local.get $z) - (i64.const 128) - )) - - ;; i32 - (drop (i32.shl - (local.get $x) - (i32.and - (local.get $y) - (i32.const 31) - ) - )) - (drop (i32.shl - (local.get $x) - (i32.and - (local.get $y) - (i32.const 63) - ) - )) - (drop (i32.shr_s - (local.get $x) - (i32.and - (local.get $y) - (i32.const 31) - ) - )) - (drop (i32.shr_u - (local.get $x) - (i32.and - (local.get $y) - (i32.const 31) - ) - )) - ;; i64 - (drop (i64.shl - (local.get $z) - (i64.and - (local.get $w) - (i64.const 63) - ) - )) - (drop (i64.shl - (local.get $z) - (i64.and - (local.get $w) - (i64.const 127) - ) - )) - (drop (i64.shr_s - (local.get $z) - (i64.and - (local.get $w) - (i64.const 63) - ) - )) - (drop (i64.shr_u - (local.get $z) - (i64.and - (local.get $w) - (i64.const 63) - ) - )) - ;; i32(x) >> (y & 32) -> x - (drop (i32.shr_u - (local.get $x) - (i32.and - (local.get $y) - (i32.const 32) - ) - )) - ;; i64(x) >> (y & 64) -> x - (drop (i64.shr_u - (local.get $z) - (i64.and - (local.get $w) - (i64.const 128) - ) - )) - - ;; skip - (drop (i64.shl - (local.get $z) - (i64.and - (local.get $w) - (i64.const 32) - ) - )) - ;; skip - (drop (i64.shr_u - (local.get $z) - (i64.and - (local.get $w) - (i64.const 31) - ) - )) - ) - ;; CHECK: (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $y1) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.sub - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $y1) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.mul - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.div - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: (local.get $y0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.div - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: (local.get $x0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32) - ;; abs(x) * abs(x) ==> x * x - (drop (f64.mul - (f64.abs (local.get $x0)) - (f64.abs (local.get $x0)) - )) - (drop (f32.mul - (f32.abs (local.get $y0)) - (f32.abs (local.get $y0)) - )) - (drop (f64.mul - (f64.abs (f64.add (local.get $x0) (local.get $x1))) - (f64.abs (f64.add (local.get $x0) (local.get $x1))) - )) - - ;; abs(x) * abs(y) ==> abs(x * y) - (drop (f64.mul - (f64.abs (local.get $x0)) - (f64.abs (local.get $x1)) - )) - (drop (f32.mul - (f32.abs (local.get $y1)) - (f32.abs (local.get $y0)) - )) - - (drop (f64.mul - (f64.abs (local.get $x0)) - (f64.abs (f64.const 0)) ;; skip - )) - (drop (f32.mul - (f32.abs (f32.const 0)) ;; skip - (f32.abs (local.get $y0)) - )) - (drop (f64.mul - (f64.abs (f64.add (local.get $x0) (local.get $x1))) - (f64.abs (f64.add (local.get $x0) (local.get $x0))) - )) - - - ;; abs(-x) ==> abs(x) - (drop (f64.abs - (f64.neg (local.get $x0)) - )) - (drop (f32.abs - (f32.neg (local.get $y0)) - )) - - ;; abs(0 - x) ==> skip for non-fast math - (drop (f64.abs - (f64.sub - (f64.const 0) - (local.get $x0) - ) - )) - (drop (f32.abs - (f32.sub - (f32.const 0) - (local.get $y0) - ) - )) - - ;; abs(x) / abs(x) ==> x / x - (drop (f64.div - (f64.abs (local.get $x0)) - (f64.abs (local.get $x0)) - )) - (drop (f32.div - (f32.abs (local.get $y0)) - (f32.abs (local.get $y0)) - )) - (drop (f64.div - (f64.abs (f64.add (local.get $x0) (local.get $x1))) - (f64.abs (f64.add (local.get $x0) (local.get $x1))) - )) - - ;; abs(x) / abs(y) ==> abs(x / y) - (drop (f64.div - (f64.abs (local.get $x0)) - (f64.abs (local.get $x1)) - )) - (drop (f32.div - (f32.abs (local.get $y1)) - (f32.abs (local.get $y0)) - )) - - ;; abs(x * x) ==> x * x - (drop (f64.abs - (f64.mul - (local.get $x0) - (local.get $x0) - ) - )) - (drop (f32.abs - (f32.mul - (local.get $y0) - (local.get $y0) - ) - )) - - ;; abs(x / x) ==> x / x - (drop (f64.abs - (f64.div - (local.get $x0) - (local.get $x0) - ) - )) - (drop (f32.abs - (f32.div - (local.get $y0) - (local.get $y0) - ) - )) - - (drop (f64.div - (f64.abs (local.get $x0)) - (f64.abs (f64.const 0)) ;; skip - )) - (drop (f32.div - (f32.abs (f32.const 0)) ;; skip - (f32.abs (local.get $y0)) - )) - (drop (f64.div - (f64.abs (f64.add (local.get $x0) (local.get $x1))) - (f64.abs (f64.add (local.get $x0) (local.get $x0))) - )) - ) - ;; CHECK: (func $ternary (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary (param $x i32) (param $y i32) - (drop - (select - (i32.const 0) - (i32.eqz - (local.get $y) - ) - (local.get $x) - ) - ) - (drop - (select - (i32.const 1) - (i32.eqz - (local.get $y) - ) - (local.get $x) - ) - ) - (drop - (select - (i32.eqz - (local.get $y) - ) - (i32.const 0) - (local.get $x) - ) - ) - (drop - (select - (i32.eqz - (local.get $y) - ) - (i32.const 1) - (local.get $x) - ) - ) - ;; if works too - (drop - (if (result i32) - (local.get $x) - (i32.eqz - (local.get $y) - ) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $ternary-i64-0 (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (if (result i64) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-i64-0 (param $x i32) (param $y i64) - (drop - (if (result i32) - (local.get $x) - (i32.const 0) - (i64.eqz - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $ternary-i64-1 (param $x i32) (param $y i64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eqz - ;; CHECK-NEXT: (if (result i64) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-i64-1 (param $x i32) (param $y i64) - (drop - (if (result i32) - (local.get $x) - (i64.eqz - (local.get $y) - ) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $ternary-no (param $x i32) (param $y i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-no (param $x i32) (param $y i32) - (drop - (select - (i32.const 2) ;; only 0 and 1 work - (i32.eqz - (local.get $y) - ) - (local.get $x) - ) - ) - ) - ;; CHECK: (func $ternary-no-unreachable-1 (param $x i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-no-unreachable-1 (param $x i32) (result i32) - (if (result i32) - (local.get $x) - ;; one arm is an eqz, the other is 0 or 1, so we can put an eqz on the - ;; outside in theory, but we'd need to be careful with the unreachable - ;; type here. ignore this case, as DCE is the proper optimization anyhow. - (i32.eqz - (unreachable) - ) - (i32.const 0) - ) - ) - ;; CHECK: (func $ternary-no-unreachable-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-no-unreachable-2 (param $x i32) (result i32) - (if (result i32) - (local.get $x) - ;; as before, but flipped - (i32.const 0) - (i32.eqz - (unreachable) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms (param $x i32) (param $y i32) (param $z i32) - (drop - (select - (i32.eqz (local.get $x)) - (i32.eqz (local.get $y)) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-if (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-if (param $x i32) (param $y i32) (param $z i32) - (drop - (if (result i32) - (local.get $z) - (i32.eqz (local.get $x)) - (i32.eqz (local.get $y)) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-type-change (param $x f64) (param $y f64) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.demote_f64 - ;; CHECK-NEXT: (f64.floor - ;; CHECK-NEXT: (if (result f64) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-type-change (param $x f64) (param $y f64) (param $z i32) - (drop - ;; the if's type begins as f32, but after moving code out it will be - ;; f64 - (if (result f32) - (local.get $z) - (f32.demote_f64 (f64.floor (local.get $x))) - (f32.demote_f64 (f64.floor (local.get $y))) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-more (param $x f32) (param $y f32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.floor - ;; CHECK-NEXT: (f32.neg - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-more (param $x f32) (param $y f32) (param $z i32) - (drop - (select - (f32.floor (f32.neg (local.get $x))) - (f32.floor (f32.neg (local.get $y))) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-morer (param $x f32) (param $y f32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.floor - ;; CHECK-NEXT: (f32.neg - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-morer (param $x f32) (param $y f32) (param $z i32) - (drop - (select - (f32.abs (f32.floor (f32.neg (local.get $x)))) - (f32.abs (f32.floor (f32.neg (local.get $y)))) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32) - (if - (local.get $z) - (drop (i32.eqz (local.get $x))) - (drop (i32.eqz (local.get $y))) - ) - ) - ;; CHECK: (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.const 2.34) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32) - (if - (local.get $z) - ;; the drop cannot be hoisted out, since the children's type mismatch - ;; would not allow us to give a proper type to the if. - (drop (i32.const 1)) - (drop (f64.const 2.34)) - ) - ) - ;; CHECK: (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block24 (result i32) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32) - (drop - (select - ;; identical arms, but they are control flow structures - (block (result i32) - (i32.eqz (local.get $x)) - ) - (block (result i32) - (i32.eqz (local.get $y)) - ) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-but-binary (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-but-binary (param $x i32) (param $y i32) (param $z i32) - (drop - (select - ;; identical arms, but they are binaries, not unaries - (i32.add - (local.get $x) - (local.get $x) - ) - (i32.add - (local.get $y) - (local.get $y) - ) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32) - (block $block - (if - (local.get $z) - ;; two br_ifs with the same target are shallowly identical - (br_if $block - (local.get $x) - ) - (br_if $block - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (block $block2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (br_if $block1 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $block2 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32) - (block $block1 - (block $block2 - (if - (local.get $z) - ;; two br_ifs with different targets are not shallowly identical - (br_if $block1 - (local.get $x) - ) - (br_if $block2 - (local.get $y) - ) - ) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32) - (block $block - (if - (local.get $z) - (return - (local.get $x) - ) - (return - (local.get $y) - ) - ) - ) - ) - ;; CHECK: (func $ternary-identical-arms-return-select (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-return-select (param $x i32) (param $y i32) (param $z i32) (result i32) - (block $block - ;; we cannot optimize a select currently as the return has side effects - (select - (return - (local.get $x) - ) - (return - (local.get $y) - ) - (local.get $z) - ) - ) - ) - ;; CHECK: (func $send-i32 (param $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $send-i32 (param i32)) - ;; CHECK: (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32) - ;; CHECK-NEXT: (call $send-i32 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32) - (if - (local.get $z) - (call $send-i32 - (local.get $x) - ) - (call $send-i32 - (local.get $y) - ) - ) - ) - ;; CHECK: (func $if-dont-change-to-unreachable (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-dont-change-to-unreachable (param $x i32) (param $y i32) (param $z i32) (result i32) - ;; if we move the returns outside, we'd become unreachable; avoid that. - (if (result i32) - (local.get $x) - (return - (local.get $y) - ) - (return - (local.get $z) - ) - ) - ) - - ;; f32.reinterpret_i32(i32.load(x)) => f32.load(x) - ;; f64.reinterpret_i64(i64.load(x)) => f64.load(x) - ;; i32.reinterpret_f32(f32.load(x)) => i32.load(x) - ;; i64.reinterpret_f64(f64.load(x)) => i64.load(x) - - ;; CHECK: (func $simplify_reinterpret_and_load (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.load - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.reinterpret_i32 - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.reinterpret_i64 - ;; CHECK-NEXT: (i64.load32_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $simplify_reinterpret_and_load (param $x i32) - (drop (f32.reinterpret_i32 (i32.load (local.get $x)))) - (drop (f64.reinterpret_i64 (i64.load (local.get $x)))) - (drop (i32.reinterpret_f32 (f32.load (local.get $x)))) - (drop (i64.reinterpret_f64 (f64.load (local.get $x)))) - (drop (f32.reinterpret_i32 (i32.load8_s (local.get $x)))) ;; skip - (drop (f64.reinterpret_i64 (i64.load32_u (local.get $x)))) ;; skip - ) - - ;; f32.store(y, f32.reinterpret_i32(x)) => i32.store(y, x) - ;; f64.store(y, f64.reinterpret_i64(x)) => i64.store(y, x) - ;; i32.store(y, i32.reinterpret_f32(x)) => f32.store(y, x) - ;; i64.store(y, i64.reinterpret_f64(x)) => f64.store(y, x) - - ;; CHECK: (func $simplify_store_and_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (i32.const 40) - ;; CHECK-NEXT: (i32.reinterpret_f32 - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (i32.const 44) - ;; CHECK-NEXT: (i64.reinterpret_f64 - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $simplify_store_and_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) - (f32.store (i32.const 8) (f32.reinterpret_i32 (local.get $x))) - (f64.store (i32.const 16) (f64.reinterpret_i64 (local.get $y))) - (i32.store (i32.const 24) (i32.reinterpret_f32 (local.get $z))) - (i64.store (i32.const 32) (i64.reinterpret_f64 (local.get $w))) - (i32.store8 (i32.const 40) (i32.reinterpret_f32 (local.get $z))) ;; skip - (i64.store32 (i32.const 44) (i64.reinterpret_f64 (local.get $w))) ;; skip - ) - - ;; i32.reinterpret_f32(f32.reinterpret_i32(x)) => x - ;; i64.reinterpret_f64(f64.reinterpret_i64(x)) => x - ;; f32.reinterpret_i32(i32.reinterpret_f32(x)) => x - ;; f64.reinterpret_i64(i64.reinterpret_f64(x)) => x - - ;; CHECK: (func $eliminate_reinterpret_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $w) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $eliminate_reinterpret_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) - (drop (i32.reinterpret_f32 (f32.reinterpret_i32 (local.get $x)))) - (drop (i64.reinterpret_f64 (f64.reinterpret_i64 (local.get $y)))) - (drop (f32.reinterpret_i32 (i32.reinterpret_f32 (local.get $z)))) - (drop (f64.reinterpret_i64 (i64.reinterpret_f64 (local.get $w)))) - ) - - ;; u64(i32.load(_8|_16)(_u|_s)(x)) => i64.load(_8|_16|_32)(_u|_s)(x) - ;; except: - ;; i64.extend_i32_u(i32.load8_s(x)) and - ;; i64.extend_i32_u(i32.load16_s(x)) - - ;; CHECK: (func $combine_load_and_extend_u (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load8_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load16_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load32_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load8_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (i32.load16_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $combine_load_and_extend_u (param $x i32) - (drop (i64.extend_i32_u (i32.load8_u (local.get $x)))) - (drop (i64.extend_i32_u (i32.load16_u (local.get $x)))) - (drop (i64.extend_i32_u (i32.load (local.get $x)))) - - ;; skips - (drop (i64.extend_i32_u (i32.load8_s (local.get $x)))) - (drop (i64.extend_i32_u (i32.load16_s (local.get $x)))) - ) - - ;; i64(i32.load(_8|_16)(_u|_s)(x)) => i64.load(_8|_16|_32)(_u|_s)(x) - - ;; CHECK: (func $combine_load_and_extend_s (param $x i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load8_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load16_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load8_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load16_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.load32_s - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $combine_load_and_extend_s (param $x i32) - (drop (i64.extend_i32_s (i32.load8_u (local.get $x)))) - (drop (i64.extend_i32_s (i32.load16_u (local.get $x)))) - (drop (i64.extend_i32_s (i32.load8_s (local.get $x)))) - (drop (i64.extend_i32_s (i32.load16_s (local.get $x)))) - (drop (i64.extend_i32_s (i32.load (local.get $x)))) - ) -) diff -Nru binaryen-108/test/lit/passes/O.wast binaryen-99/test/lit/passes/O.wast --- binaryen-108/test/lit/passes/O.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/O.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -O -S -o - | filecheck %s - -(module - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (type $i64_=>_none (func (param i64))) - - ;; CHECK: (export "ret" (func $ret)) - - ;; CHECK: (export "waka" (func $if-0-unreachable-to-none)) - - ;; CHECK: (export "many-selects" (func $many-selects)) - - ;; CHECK: (export "end-if-else" (func $end-if-else)) - - ;; CHECK: (export "end-if-else-call" (func $end-if-else-call)) - - ;; CHECK: (func $ret (; has Stack IR ;) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $ret) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $ret) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 999) - ;; CHECK-NEXT: ) - (func $ret (export "ret") (result i32) - (block $out (result i32) - (drop (call $ret)) - (if (call $ret) - (return - (return - (i32.const 1) - ) - ) - ) - (drop (br_if $out (i32.const 999) (i32.const 1))) - (unreachable) - ) - ) - ;; CHECK: (func $if-0-unreachable-to-none (; has Stack IR ;) (param $0 i64) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $if-0-unreachable-to-none (export "waka") (param $var$0 i64) - (local $var$1 i64) - (local $var$2 i64) - (block $label$1 - (if - (i32.const 0) - (br $label$1) - (unreachable) - ) - ) - ) - ;; CHECK: (func $many-selects (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const -1073741824) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1073741823) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 1073741823) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -1073741824) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $many-selects (export "many-selects") (param $0 i32) (result i32) - (if - (i32.lt_s - (local.get $0) - (i32.const -1073741824) - ) - (local.set $0 - (i32.const -1073741824) - ) - (if - (i32.gt_s - (local.get $0) - (i32.const 1073741823) - ) - (local.set $0 - (i32.const 1073741823) - ) - ) - ) - (local.get $0) - ) - ;; CHECK: (func $end-if-else (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $end-if-else (export "end-if-else") (param $x i32) (result i32) - (if - (local.get $x) - (local.set $x - (i32.const 1) - ) - ) - (local.get $x) - ) - ;; CHECK: (func $end-if-else-call (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (call $ret) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $end-if-else-call (export "end-if-else-call") (param $x i32) (result i32) - (if - (local.get $x) - (local.set $x - (call $ret) - ) - ) - (local.get $x) - ) -) - diff -Nru binaryen-108/test/lit/passes/Oz.wast binaryen-99/test/lit/passes/Oz.wast --- binaryen-108/test/lit/passes/Oz.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/Oz.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,286 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt -Oz --all-features -S -o - | filecheck %s - -(module - (memory 100 100) - ;; CHECK: (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - - ;; CHECK: (type $none_=>_v128 (func (result v128))) - - ;; CHECK: (memory $0 100 100) - - ;; CHECK: (export "localcse" (func $basics)) - - ;; CHECK: (export "localcse-2" (func $8)) - - ;; CHECK: (export "propagate-sign-for-mul-i32-lhs-const-pot" (func $9)) - - ;; CHECK: (export "propagate-sign-for-mul-i32-smin" (func $10)) - - ;; CHECK: (export "eliminate-redundant-checks-1" (func $11)) - - ;; CHECK: (export "eliminate-redundant-checks-1a" (func $11)) - - ;; CHECK: (export "eliminate-redundant-checks-2" (func $12)) - - ;; CHECK: (export "eliminate-redundant-checks-2a" (func $12)) - - ;; CHECK: (export "eliminate-redundant-checks-skip-1" (func $13)) - - ;; CHECK: (export "eliminate-redundant-checks-skip-2" (func $14)) - - ;; CHECK: (export "precompute-simd" (func $precompute-simd)) - - ;; CHECK: (func $basics (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $basics (export "localcse") (param $x i32) ($param $y i32) (result i32) ;; -O3 does localcse - (local $x2 i32) - (local $y2 i32) - (local.set $x2 - (i32.add (local.get $x) (local.get $y)) - ) - (local.set $y2 - (i32.add (local.get $x) (local.get $y)) - ) - (i32.add (local.get $x2) (local.get $y2)) - ) - ;; CHECK: (func $8 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.tee $0 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -75) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $8 (export "localcse-2") (param $var$0 i32) - (param $var$1 i32) - (param $var$2 i32) - (param $var$3 i32) - (result i32) - (block $label$0 (result i32) - (i32.store - (local.tee $var$2 - (i32.add - (local.get $var$1) - (i32.const 4) - ) - ) - (i32.and - (i32.load - (local.get $var$2) - ) - (i32.xor - (local.tee $var$2 - (i32.const 74) - ) - (i32.const -1) - ) - ) - ) - (i32.store - (local.tee $var$1 - (i32.add - (local.get $var$1) - (i32.const 4) - ) - ) - (i32.or - (i32.load - (local.get $var$1) - ) - (i32.and - (local.get $var$2) - (i32.const 8) - ) - ) - ) - (i32.const 0) - ) - ) - - ;; CHECK: (func $9 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const -4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $9 (export "propagate-sign-for-mul-i32-lhs-const-pot") (param $0 i32) (result i32) - (i32.mul - (i32.const 4) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - ) - - ;; CHECK: (func $10 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 31) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $10 (export "propagate-sign-for-mul-i32-smin") (param $0 i32) (result i32) - (i32.mul - (i32.sub - (i32.const 0) - (local.get $0) - ) - (i32.const 0x80000000) - ) - ) - - ;; CHECK: (func $11 (; has Stack IR ;) (param $0 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $11 (export "eliminate-redundant-checks-1") (param $0 i32) (result i32) - (if - (local.get $0) - (if - (local.get $0) - (return (local.get $0)) - ) - ) - (i32.const 0) - ) - (func $11a (export "eliminate-redundant-checks-1a") (param $0 i32) (result i32) - (if - (select - (local.get $0) - (i32.const 0) - (local.get $0) - ) - (return (local.get $0)) - ) - (i32.const 0) - ) - ;; CHECK: (func $12 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $12 (export "eliminate-redundant-checks-2") (param $0 i32) (param $1 i32) (result i32) - (if - (local.tee $1 (local.get $0)) - (if - (local.get $1) - (return (local.get $1)) - ) - ) - (i32.const 0) - ) - (func $12a (export "eliminate-redundant-checks-2a") (param $0 i32) (param $1 i32) (result i32) - (if - (select - (local.tee $1 (local.get $0)) - (i32.const 0) - (local.get $1) - ) - (return (local.get $1)) - ) - (i32.const 0) - ) - ;; CHECK: (func $13 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $13 (export "eliminate-redundant-checks-skip-1") (param $0 i32) (param $1 i32) (result i32) - (if - (select - (local.get $1) - (i32.const 0) - (local.tee $1 (local.get $0)) - ) - (return (local.get $1)) - ) - (i32.const 0) - ) - - ;; CHECK: (func $14 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - (func $14 (export "eliminate-redundant-checks-skip-2") (param $0 i32) (param $1 i32) (result i32) - (if - (select - (i32.const 0) - (local.get $1) - (local.tee $1 (local.get $0)) - ) - (return (local.get $1)) - ) - (i32.const 0) - ) - - ;; CHECK: (func $precompute-simd (; has Stack IR ;) (result v128) - ;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) - ;; CHECK-NEXT: ) - (func $precompute-simd (export "precompute-simd") (result v128) - (i32x4.splat - (i32.const 0) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/poppify-globals.wast binaryen-99/test/lit/passes/poppify-globals.wast --- binaryen-108/test/lit/passes/poppify-globals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/poppify-globals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; TODO: enable validation -;; RUN: wasm-opt %s --poppify --no-validation -all -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $foo (mut i32) (i32.const 0)) - (global $foo (mut i32) (i32.const 0)) - - ;; CHECK: (global $tuple$1 f64 (f64.const 0)) - (global $tuple$1 f64 (f64.const 0)) ;; interfering name! - - (global $tuple (mut (i32 i64 f32)) - (tuple.make (global.get $foo) (i64.const 1) (f32.const 2)) - ) - - (global $other-tuple (i32 i64 f32) (global.get $tuple)) - - ;; CHECK: (global $tuple$2 (mut f32) (f32.const 2)) - - ;; CHECK: (global $tuple$1_0 (mut i64) (i64.const 1)) - - ;; CHECK: (global $tuple$0 (mut i32) (global.get $foo)) - - ;; CHECK: (global $other-tuple$2 f32 (global.get $tuple$2)) - - ;; CHECK: (global $other-tuple$1 i64 (global.get $tuple$1_0)) - - ;; CHECK: (global $other-tuple$0 i32 (global.get $tuple$0)) - - ;; CHECK: (func $global-get-tuple (result i32 i64 f32) - ;; CHECK-NEXT: (global.get $tuple$0) - ;; CHECK-NEXT: (global.get $tuple$1_0) - ;; CHECK-NEXT: (global.get $tuple$2) - ;; CHECK-NEXT: ) - (func $global-get-tuple (result i32 i64 f32) - (global.get $tuple) - ) - - ;; CHECK: (func $global-set-tuple - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: (global.set $tuple$2 - ;; CHECK-NEXT: (pop f32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $tuple$1_0 - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $tuple$0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $global-set-tuple - (global.set $tuple - (tuple.make - (i32.const 0) - (i64.const 1) - (f32.const 2) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/poppify.wast binaryen-99/test/lit/passes/poppify.wast --- binaryen-108/test/lit/passes/poppify.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/poppify.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,471 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; TODO: enable validation -;; RUN: wasm-opt %s --poppify --no-validation -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e (param i32)) - (tag $e (param i32)) - - ;; CHECK: (func $id (param $x i32) (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - (func $id (param $x i32) (result i32) - (local.get $x) - ) - - ;; CHECK: (func $add (param $x i32) (param $y i32) (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $add (param $x i32) (param $y i32) (result i32) - (i32.add - (local.get $x) - (local.get $y) - ) - ) - - ;; CHECK: (func $expr-tree (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $expr-tree (result i32) - (i32.add - (i32.mul - (i32.const 0) - (i32.const 1) - ) - (i32.mul - (i32.const 2) - (i32.const 3) - ) - ) - ) - - ;; CHECK: (func $block (result i32) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block (result i32) - (block i32 - (nop) - (i32.const 0) - ) - ) - - ;; CHECK: (func $nested (result i32) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (block $block0 (result i32) - ;; CHECK-NEXT: (block $block1 (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested (result i32) - (block i32 - (block i32 - (block i32 - (i32.const 0) - ) - ) - ) - ) - - ;; CHECK: (func $child-blocks (result i32) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (block $block2 (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block3 (result i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $child-blocks (result i32) - (block (result i32) - (i32.add - (block (result i32) - (i32.const 0) - ) - (block (result i32) - (i32.const 1) - ) - ) - ) - ) - - ;; CHECK: (func $block-br (result i32) - ;; CHECK-NEXT: (block $l (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (br $l - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $block-br (result i32) - (block $l i32 - (nop) - (br $l - (i32.const 0) - ) - ) - ) - - ;; CHECK: (func $loop - ;; CHECK-NEXT: (loop $l - ;; CHECK-NEXT: (br $l) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $loop - (loop $l - (br $l) - ) - ) - - ;; CHECK: (func $if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if - (if - (i32.const 0) - (nop) - ) - ) - - ;; CHECK: (func $if-else (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else (result i32) - (if i32 - (i32.const 0) - (i32.const 1) - (i32.const 2) - ) - ) - - ;; CHECK: (func $try-catch (result i32) - ;; CHECK-NEXT: (try $try (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-catch (result i32) - (try i32 - (do - (throw $e - (i32.const 0) - ) - ) - (catch $e - (pop i32) - ) - (catch_all - (i32.const 1) - ) - ) - ) - - ;; CHECK: (func $try-delegate (result i32) - ;; CHECK-NEXT: (try $l0 (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate (result i32) - (try $l0 i32 - (do - (try - (do - (throw $e - (i32.const 0) - ) - ) - (delegate $l0) - ) - ) - (catch $e - (pop i32) - ) - ) - ) - - ;; CHECK: (func $tuple (result i32 i64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: ) - (func $tuple (result i32 i64) - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - - ;; CHECK: (func $extract-first (result i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop f32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $extract-first (result i32) - (tuple.extract 0 - (tuple.make - (i32.const 0) - (i64.const 1) - (f32.const 2) - ) - ) - ) - - ;; CHECK: (func $extract-middle (result i64) - ;; CHECK-NEXT: (local $0 i64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop f32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $extract-middle (result i64) - (tuple.extract 1 - (tuple.make - (i32.const 0) - (i64.const 1) - (f32.const 2) - ) - ) - ) - - ;; CHECK: (func $extract-last (result f32) - ;; CHECK-NEXT: (local $0 f32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop f32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - (func $extract-last (result f32) - (tuple.extract 2 - (tuple.make - (i32.const 0) - (i64.const 1) - (f32.const 2) - ) - ) - ) - - ;; CHECK: (func $drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $drop - (drop - (i32.const 0) - ) - ) - - ;; CHECK: (func $drop-tuple - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $drop-tuple - (drop - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - ) - - ;; CHECK: (func $local-get-tuple (result i32 i64) - ;; CHECK-NEXT: (local $x (i32 i64)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - (func $local-get-tuple (result i32 i64) - (local $x (i32 i64)) - (local.get $x) - ) - - ;; CHECK: (func $local-set - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-set - (local $x i32) - (local.set $x - (i32.const 0) - ) - ) - - ;; CHECK: (func $local-set-tuple - ;; CHECK-NEXT: (local $x (i32 i64)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-set-tuple - (local $x (i32 i64)) - (local.set $x - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - ) - - ;; CHECK: (func $local-tee-tuple (result i32 i64) - ;; CHECK-NEXT: (local $x (i32 i64)) - ;; CHECK-NEXT: (local $1 i32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (pop i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $1 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - (func $local-tee-tuple (result i32 i64) - (local $x (i32 i64)) - (local.tee $x - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - ) - - ;; CHECK: (func $break-tuple (result i32 i64) - ;; CHECK-NEXT: (block $l (result i32 i64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (br $l - ;; CHECK-NEXT: (pop i32 i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $break-tuple (result i32 i64) - (block $l (result i32 i64) - (br $l - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - ) - ) - - ;; CHECK: (func $return-tuple (result i32 i64) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (pop i32 i64) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $return-tuple (result i32 i64) - (return - (tuple.make - (i32.const 0) - (i64.const 1) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/precompute-gc-immutable.wast binaryen-99/test/lit/passes/precompute-gc-immutable.wast --- binaryen-108/test/lit/passes/precompute-gc-immutable.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/precompute-gc-immutable.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,822 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; RUN: foreach %s %t wasm-opt --precompute-propagate -all --nominal -S -o - | filecheck %s - -(module - ;; CHECK: (type $struct-imm (struct_subtype (field i32) data)) - (type $struct-imm (struct_subtype i32 data)) - - ;; CHECK: (type $struct-mut (struct_subtype (field (mut i32)) data)) - (type $struct-mut (struct_subtype (mut i32) data)) - - ;; CHECK: (func $propagate (type $none_=>_none) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (local $ref-mut (ref null $struct-mut)) - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $ref-mut - ;; CHECK-NEXT: (struct.new $struct-mut - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-mut 0 - ;; CHECK-NEXT: (local.get $ref-mut) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate - (local $ref-imm (ref null $struct-imm)) - (local $ref-mut (ref null $struct-mut)) - ;; We can propagate from an immutable field of a struct created in this - ;; function. - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 1) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ;; But the same thing on a mutable field fails. - (local.set $ref-mut - (struct.new $struct-mut - (i32.const 1) - ) - ) - (call $helper - (struct.get $struct-mut 0 - (local.get $ref-mut) - ) - ) - ) - - ;; CHECK: (func $non-constant (type $i32_=>_none) (param $param i32) - ;; CHECK-NEXT: (local $ref (ref null $struct-imm)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-imm 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $non-constant (param $param i32) - (local $ref (ref null $struct-imm)) - (local.set $ref - (struct.new $struct-imm - ;; This value is not constant, so we have nothing to propagate. - (local.get $param) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $unreachable (type $none_=>_none) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (local.tee $ref-imm - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-imm 0 - ;; CHECK-NEXT: (local.get $ref-imm) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable - (local $ref-imm (ref null $struct-imm)) - ;; Test we do not error on an unreachable value. - (local.set $ref-imm - (struct.new $struct-imm - (unreachable) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - - ;; CHECK: (func $param (type $ref?|$struct-imm|_=>_none) (param $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-imm 0 - ;; CHECK-NEXT: (local.get $ref-imm) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $param (param $ref-imm (ref null $struct-imm)) - ;; Test we ignore a param value, whose data we do not know. - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - - ;; CHECK: (func $local-null (type $none_=>_none) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-imm 0 - ;; CHECK-NEXT: (ref.null $struct-imm) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-null - (local $ref-imm (ref null $struct-imm)) - ;; Test we ignore a local value that is null. - ;; TODO: this could be precomputed to an unreachable - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - - ;; CHECK: (func $local-unknown (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-imm 0 - ;; CHECK-NEXT: (local.get $ref-imm) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-unknown (param $x i32) - (local $ref-imm (ref null $struct-imm)) - ;; Do not propagate if a local has more than one possible struct.new with - ;; different values. - (if - (local.get $x) - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 1) - ) - ) - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 2) - ) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - - ;; CHECK: (func $local-unknown-ref-same-value (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct-imm 0 - ;; CHECK-NEXT: (local.get $ref-imm) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $local-unknown-ref-same-value (param $x i32) - (local $ref-imm (ref null $struct-imm)) - ;; As above, but the two different refs have the same value, so we can in - ;; theory optimize. However, atm we do nothing here, as the analysis stops - ;; when it sees it cannot propagate the local value (the ref, which has two - ;; possible values). - (if - (local.get $x) - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 1) - ) - ) - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 1) - ) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - - ;; CHECK: (func $propagate-multi-refs (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-multi-refs (param $x i32) - (local $ref-imm (ref null $struct-imm)) - ;; Propagate more than once in a function, using the same local that is - ;; reused. - (if - (local.get $x) - (block - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 1) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - (block - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 2) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - ) - ) - - ;; CHECK: (func $propagate-multi-values (type $i32_=>_none) (param $x i32) - ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) - ;; CHECK-NEXT: (local.set $ref-imm - ;; CHECK-NEXT: (struct.new $struct-imm - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate-multi-values (param $x i32) - (local $ref-imm (ref null $struct-imm)) - ;; Propagate a ref's value more than once - (local.set $ref-imm - (struct.new $struct-imm - (i32.const 1) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - (call $helper - (struct.get $struct-imm 0 - (local.get $ref-imm) - ) - ) - ) - - ;; CHECK: (func $helper (type $i32_=>_none) (param $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param i32)) -) - -(module - ;; One field is immutable, the other is not, so we can only propagate the - ;; former. - ;; CHECK: (type $struct (struct_subtype (field (mut i32)) (field i32) data)) - (type $struct (struct_subtype (mut i32) i32 data)) - - ;; CHECK: (func $propagate (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $struct)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $propagate - (local $ref (ref null $struct)) - ;; We can propagate from an immutable field of a struct created in this - ;; function. - (local.set $ref - (struct.new $struct - (i32.const 1) - (i32.const 2) - ) - ) - (call $helper - (struct.get $struct 0 - (local.get $ref) - ) - ) - (call $helper - (struct.get $struct 1 - (local.get $ref) - ) - ) - ) - - ;; CHECK: (func $helper (type $i32_=>_none) (param $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param i32)) -) - -(module - ;; Create an immutable vtable in an immutable field, which lets us read from - ;; it. - - ;; CHECK: (type $object (struct_subtype (field (ref $vtable)) data)) - - ;; CHECK: (type $vtable (struct_subtype (field funcref) data)) - (type $vtable (struct_subtype funcref data)) - (type $object (struct_subtype (ref $vtable) data)) - - ;; CHECK: (func $nested-creations (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (struct.new $vtable - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations - (local $ref (ref null $object)) - ;; Create an object with a reference to another object, and propagate - ;; through both of them to a constant value, which saves two struct.gets. - (local.set $ref - (struct.new $object - (struct.new $vtable - (ref.func $nested-creations) - ) - ) - ) - (call $helper - (struct.get $vtable 0 - (struct.get $object 0 - (local.get $ref) - ) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) - -(module - ;; As above, but make $vtable not immutable, which prevents optimization. - - ;; CHECK: (type $object (struct_subtype (field (ref $vtable)) data)) - - ;; CHECK: (type $vtable (struct_subtype (field (mut funcref)) data)) - (type $vtable (struct_subtype (mut funcref) data)) - (type $object (struct_subtype (ref $vtable) data)) - - ;; CHECK: (func $nested-creations (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (struct.new $vtable - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $vtable 0 - ;; CHECK-NEXT: (struct.get $object 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations - (local $ref (ref null $object)) - (local.set $ref - (struct.new $object - (struct.new $vtable - (ref.func $nested-creations) - ) - ) - ) - (call $helper - (struct.get $vtable 0 - ;; Note that we *can* precompute the first struct.get here, but there - ;; is no constant expression we can emit for it, so we do nothing. - (struct.get $object 0 - (local.get $ref) - ) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) - - -(module - ;; As above, but make $object not immutable, which prevents optimization. - - ;; CHECK: (type $object (struct_subtype (field (mut (ref $vtable))) data)) - - ;; CHECK: (type $vtable (struct_subtype (field funcref) data)) - (type $vtable (struct_subtype funcref data)) - (type $object (struct_subtype (mut (ref $vtable)) data)) - - ;; CHECK: (func $nested-creations (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (struct.new $vtable - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $vtable 0 - ;; CHECK-NEXT: (struct.get $object 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations - (local $ref (ref null $object)) - (local.set $ref - (struct.new $object - (struct.new $vtable - (ref.func $nested-creations) - ) - ) - ) - (call $helper - (struct.get $vtable 0 - (struct.get $object 0 - (local.get $ref) - ) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) - -(module - ;; Create an immutable vtable in an immutable global, which we can optimize - ;; with. - - ;; CHECK: (type $vtable (struct_subtype (field funcref) data)) - (type $vtable (struct_subtype funcref data)) - ;; CHECK: (type $object (struct_subtype (field (ref $vtable)) data)) - (type $object (struct_subtype (ref $vtable) data)) - - ;; CHECK: (global $vtable (ref $vtable) (struct.new $vtable - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: )) - (global $vtable (ref $vtable) - (struct.new $vtable - (ref.func $nested-creations) - ) - ) - - ;; CHECK: (func $nested-creations (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations - (local $ref (ref null $object)) - (local.set $ref - (struct.new $object - (global.get $vtable) - ) - ) - (call $helper - (struct.get $vtable 0 - (struct.get $object 0 - (local.get $ref) - ) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) - -(module - ;; Create an immutable vtable in an mutable global, whose mutability prevents - ;; optimization. - - ;; CHECK: (type $vtable (struct_subtype (field funcref) data)) - (type $vtable (struct_subtype funcref data)) - ;; CHECK: (type $object (struct_subtype (field (ref $vtable)) data)) - (type $object (struct_subtype (ref $vtable) data)) - - ;; CHECK: (global $vtable (mut (ref $vtable)) (struct.new $vtable - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: )) - (global $vtable (mut (ref $vtable)) - (struct.new $vtable - (ref.func $nested-creations) - ) - ) - - ;; CHECK: (func $nested-creations (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (struct.get $vtable 0 - ;; CHECK-NEXT: (struct.get $object 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations - (local $ref (ref null $object)) - (local.set $ref - (struct.new $object - (global.get $vtable) - ) - ) - (call $helper - (struct.get $vtable 0 - (struct.get $object 0 - (local.get $ref) - ) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) - -(module - ;; Create an immutable vtable in an immutable global, but using an array - ;; instead of a struct. - - ;; CHECK: (type $object (struct_subtype (field (ref $vtable)) data)) - - ;; CHECK: (type $vtable (array_subtype funcref data)) - (type $vtable (array_subtype funcref data)) - (type $object (struct_subtype (ref $vtable) data)) - - ;; CHECK: (global $vtable (ref $vtable) (array.init_static $vtable - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: )) - (global $vtable (ref $vtable) - (array.init_static $vtable - (ref.func $nested-creations) - ) - ) - - ;; CHECK: (func $nested-creations (type $i32_=>_none) (param $param i32) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (global.get $vtable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (array.get $vtable - ;; CHECK-NEXT: (struct.get $object 0 - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations (param $param i32) - (local $ref (ref null $object)) - (local.set $ref - (struct.new $object - (global.get $vtable) - ) - ) - (call $helper - (array.get $vtable - (struct.get $object 0 - (local.get $ref) - ) - (i32.const 0) - ) - ) - ;; The second operation here uses a param for the array index, which is not - ;; constant. - (call $helper - (array.get $vtable - (struct.get $object 0 - (local.get $ref) - ) - (local.get $param) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) - -(module - ;; A j2wasm-like itable pattern: An itable is an array of (possibly-null) - ;; data that is filled with vtables of different types. On usage, we do a - ;; cast of the vtable type. - - ;; CHECK: (type $itable (array_subtype (ref null data) data)) - (type $itable (array_subtype (ref null data) data)) - - ;; CHECK: (type $object (struct_subtype (field (ref $itable)) data)) - (type $object (struct_subtype (ref $itable) data)) - - ;; CHECK: (type $vtable-0 (struct_subtype (field funcref) data)) - (type $vtable-0 (struct_subtype funcref data)) - - ;; CHECK: (type $vtable-1 (struct_subtype (field funcref) data)) - (type $vtable-1 (struct_subtype funcref data)) - - ;; CHECK: (global $itable (ref $itable) (array.init_static $itable - ;; CHECK-NEXT: (struct.new $vtable-0 - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.new $vtable-1 - ;; CHECK-NEXT: (ref.func $helper) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: )) - (global $itable (ref $itable) - (array.init_static $itable - (struct.new $vtable-0 - (ref.func $nested-creations) - ) - (struct.new $vtable-1 - (ref.func $helper) - ) - ) - ) - - ;; CHECK: (func $nested-creations (type $none_=>_none) - ;; CHECK-NEXT: (local $ref (ref null $object)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new $object - ;; CHECK-NEXT: (global.get $itable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (ref.func $nested-creations) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (ref.func $helper) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-creations - (local $ref (ref null $object)) - (local.set $ref - (struct.new $object - (global.get $itable) - ) - ) - ;; We can precompute all these operations away into the final constants. - (call $helper - (struct.get $vtable-0 0 - (ref.cast_static $vtable-0 - (array.get $itable - (struct.get $object 0 - (local.get $ref) - ) - (i32.const 0) - ) - ) - ) - ) - (call $helper - (struct.get $vtable-1 0 - (ref.cast_static $vtable-1 - (array.get $itable - (struct.get $object 0 - (local.get $ref) - ) - (i32.const 1) - ) - ) - ) - ) - ) - - ;; CHECK: (func $helper (type $funcref_=>_none) (param $0 funcref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper (param funcref)) -) diff -Nru binaryen-108/test/lit/passes/precompute-gc.wast binaryen-99/test/lit/passes/precompute-gc.wast --- binaryen-108/test/lit/passes/precompute-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/precompute-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1535 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all -S -o - \ -;; RUN: | filecheck %s -;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $empty (struct )) - ;; NOMNL: (type $empty (struct_subtype data)) - (type $empty (struct)) - - ;; CHECK: (type $struct (struct (field (mut i32)))) - ;; NOMNL: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (mut i32))) - - ;; two incompatible struct types - (type $A (struct (field (mut f32)))) - ;; CHECK: (type $B (struct (field (mut f64)))) - ;; NOMNL: (type $B (struct_subtype (field (mut f64)) data)) - (type $B (struct (field (mut f64)))) - - ;; CHECK: (type $func-return-i32 (func (result i32))) - ;; NOMNL: (type $func-return-i32 (func_subtype (result i32) func)) - (type $func-return-i32 (func (result i32))) - - ;; CHECK: (import "fuzzing-support" "log-i32" (func $log (param i32))) - ;; NOMNL: (import "fuzzing-support" "log-i32" (func $log (param i32))) - (import "fuzzing-support" "log-i32" (func $log (param i32))) - - ;; CHECK: (func $test-fallthrough (result i32) - ;; CHECK-NEXT: (local $x funcref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result funcref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $test-fallthrough) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test-fallthrough (type $func-return-i32) (result i32) - ;; NOMNL-NEXT: (local $x funcref) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (block (result funcref) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $test-fallthrough) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (ref.null func) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - (func $test-fallthrough (result i32) - (local $x funcref) - (local.set $x - ;; the fallthrough value should be used. for that to be possible with a block - ;; we need for it not to have a name, which is why --remove-unused-names is - ;; run - (block (result (funcref)) - ;; make a call so the block is not trivially removable - (drop - (call $test-fallthrough) - ) - (ref.null func) - ) - ) - ;; the null in the local should be propagated to here - (ref.is_null - (local.get $x) - ) - ) - - ;; CHECK: (func $load-from-struct - ;; CHECK-NEXT: (local $x (ref null $struct)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $load-from-struct (type $none_=>_none) - ;; NOMNL-NEXT: (local $x (ref null $struct)) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 3) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $load-from-struct - (local $x (ref null $struct)) - (local.set $x - (struct.new_with_rtt $struct - (i32.const 1) - (rtt.canon $struct) - ) - ) - ;; we don't precompute these, as we don't know if the GC data was modified - ;; elsewhere (we'd need immutability or escape analysis) - (call $log - (struct.get $struct 0 (local.get $x)) - ) - ;; Assign a new struct - (local.set $x - (struct.new_with_rtt $struct - (i32.const 2) - (rtt.canon $struct) - ) - ) - (call $log - (struct.get $struct 0 (local.get $x)) - ) - ;; Assign a new value - (struct.set $struct 0 - (local.get $x) - (i32.const 3) - ) - (call $log - (struct.get $struct 0 (local.get $x)) - ) - ) - ;; CHECK: (func $load-from-struct-bad-merge (param $i i32) - ;; CHECK-NEXT: (local $x (ref null $struct)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $load-from-struct-bad-merge (type $i32_=>_none) (param $i i32) - ;; NOMNL-NEXT: (local $x (ref null $struct)) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $i) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct - ;; NOMNL-NEXT: (i32.const 2) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $load-from-struct-bad-merge (param $i i32) - (local $x (ref null $struct)) - ;; a merge of two different $x values cannot be precomputed - (if - (local.get $i) - (local.set $x - (struct.new_with_rtt $struct - (i32.const 1) - (rtt.canon $struct) - ) - ) - (local.set $x - (struct.new_with_rtt $struct - (i32.const 2) - (rtt.canon $struct) - ) - ) - ) - (call $log - (struct.get $struct 0 (local.get $x)) - ) - ) - ;; CHECK: (func $modify-gc-heap (param $x (ref null $struct)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $modify-gc-heap (type $ref?|$struct|_=>_none) (param $x (ref null $struct)) - ;; NOMNL-NEXT: (struct.set $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.add - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $modify-gc-heap (param $x (ref null $struct)) - (struct.set $struct 0 - (local.get $x) - (i32.add - (struct.get $struct 0 - (local.get $x) - ) - (i32.const 1) - ) - ) - ) - ;; --fuzz-exec verifies the output of this function, checking that the change - ;; makde in modify-gc-heap is not ignored - ;; CHECK: (func $load-from-struct-bad-escape - ;; CHECK-NEXT: (local $x (ref null $struct)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $modify-gc-heap - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $load-from-struct-bad-escape (type $none_=>_none) - ;; NOMNL-NEXT: (local $x (ref null $struct)) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $modify-gc-heap - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $load-from-struct-bad-escape (export "test") - (local $x (ref null $struct)) - (local.set $x - (struct.new_with_rtt $struct - (i32.const 1) - (rtt.canon $struct) - ) - ) - (call $modify-gc-heap - (local.get $x) - ) - (call $log - (struct.get $struct 0 (local.get $x)) - ) - ) - ;; CHECK: (func $load-from-struct-bad-arrive (param $x (ref null $struct)) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $load-from-struct-bad-arrive (type $ref?|$struct|_=>_none) (param $x (ref null $struct)) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $load-from-struct-bad-arrive (param $x (ref null $struct)) - ;; a parameter cannot be precomputed - (call $log - (struct.get $struct 0 (local.get $x)) - ) - ) - ;; CHECK: (func $ref-comparisons (param $x (ref null $struct)) (param $y (ref null $struct)) - ;; CHECK-NEXT: (local $z (ref null $struct)) - ;; CHECK-NEXT: (local $w (ref null $struct)) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $log - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref-comparisons (type $ref?|$struct|_ref?|$struct|_=>_none) (param $x (ref null $struct)) (param $y (ref null $struct)) - ;; NOMNL-NEXT: (local $z (ref null $struct)) - ;; NOMNL-NEXT: (local $w (ref null $struct)) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (ref.null $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (ref.null $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $log - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref-comparisons - (param $x (ref null $struct)) - (param $y (ref null $struct)) - (local $z (ref null $struct)) - (local $w (ref null $struct)) - ;; incoming parameters are unknown - (call $log - (ref.eq - (local.get $x) - (local.get $y) - ) - ) - (call $log - (ref.eq - (local.get $x) - ;; locals are ref.null which are known, and will be propagated - (local.get $z) - ) - ) - (call $log - (ref.eq - (local.get $x) - (local.get $w) - ) - ) - ;; null-initialized locals are known and can be compared - (call $log - (ref.eq - (local.get $z) - (local.get $w) - ) - ) - ) - ;; CHECK: (func $new-ref-comparisons (result i32) - ;; CHECK-NEXT: (local $x (ref null $struct)) - ;; CHECK-NEXT: (local $y (ref null $struct)) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (struct.new_with_rtt $struct - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $new-ref-comparisons (type $func-return-i32) (result i32) - ;; NOMNL-NEXT: (local $x (ref null $struct)) - ;; NOMNL-NEXT: (local $y (ref null $struct)) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local.set $x - ;; NOMNL-NEXT: (struct.new_with_rtt $struct - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $y - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - (func $new-ref-comparisons (result i32) - (local $x (ref null $struct)) - (local $y (ref null $struct)) - (local $tempresult i32) - (local.set $x - (struct.new_with_rtt $struct - (i32.const 1) - (rtt.canon $struct) - ) - ) - (local.set $y - (local.get $x) - ) - ;; assign the result, so that propagate calculates the ref.eq. both $x and $y - ;; must refer to the same data, so we can precompute a 1 here. - (local.set $tempresult - (ref.eq - (local.get $x) - (local.get $y) - ) - ) - ;; and that 1 is propagated to here. - (local.get $tempresult) - ) - ;; CHECK: (func $propagate-equal (result i32) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.tee $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-equal (type $func-return-i32) (result i32) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.tee $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - (func $propagate-equal (result i32) - (local $tempresult i32) - (local $tempref (ref null $empty)) - ;; assign the result, so that propagate calculates the ref.eq - (local.set $tempresult - (ref.eq - ;; allocate one struct - (local.tee $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - (local.get $tempref) - ) - ) - ;; we can compute a 1 here as the ref.eq compares a struct to itself. note - ;; that the ref.eq itself cannot be precomputed away (as it has side effects). - (local.get $tempresult) - ) - ;; CHECK: (func $propagate-unequal (result i32) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-unequal (type $func-return-i32) (result i32) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - (func $propagate-unequal (result i32) - (local $tempresult i32) - (local $tempref (ref null $empty)) - ;; assign the result, so that propagate calculates the ref.eq. - ;; the structs are different, so we will precompute a 0 here, and as creating - ;; heap data does not have side effects, we can in fact replace the ref.eq - ;; with that value - (local.set $tempresult - ;; allocate two different structs - (ref.eq - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - ) - (local.get $tempresult) - ) - - ;; CHECK: (func $propagate-uncertain-param (param $input (ref $empty)) (result i32) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $input) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $tempresult) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-uncertain-param (type $ref|$empty|_=>_i32) (param $input (ref $empty)) (result i32) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $input) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $tempresult) - ;; NOMNL-NEXT: ) - (func $propagate-uncertain-param (param $input (ref $empty)) (result i32) - (local $tempresult i32) - (local $tempref (ref null $empty)) - (local.set $tempresult - ;; allocate a struct and compare it to a param, which we know nothing about, - ;; so we can infer nothing here at all. - (ref.eq - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - (local.get $input) - ) - ) - (local.get $tempresult) - ) - - ;; CHECK: (func $propagate-different-params (param $input1 (ref $empty)) (param $input2 (ref $empty)) (result i32) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $input1) - ;; CHECK-NEXT: (local.get $input2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $tempresult) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-different-params (type $ref|$empty|_ref|$empty|_=>_i32) (param $input1 (ref $empty)) (param $input2 (ref $empty)) (result i32) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $input1) - ;; NOMNL-NEXT: (local.get $input2) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $tempresult) - ;; NOMNL-NEXT: ) - (func $propagate-different-params (param $input1 (ref $empty)) (param $input2 (ref $empty)) (result i32) - (local $tempresult i32) - (local.set $tempresult - ;; We cannot say anything about parameters - they might alias, or not. - (ref.eq - (local.get $input1) - (local.get $input2) - ) - ) - (local.get $tempresult) - ) - - ;; CHECK: (func $propagate-same-param (param $input (ref $empty)) (result i32) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $input) - ;; CHECK-NEXT: (local.get $input) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $tempresult) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-same-param (type $ref|$empty|_=>_i32) (param $input (ref $empty)) (result i32) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $input) - ;; NOMNL-NEXT: (local.get $input) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $tempresult) - ;; NOMNL-NEXT: ) - (func $propagate-same-param (param $input (ref $empty)) (result i32) - (local $tempresult i32) - (local.set $tempresult - ;; We could optimize this in principle, but atm do not. - ;; Note that optimize-instructions can handle patterns like this. - (ref.eq - (local.get $input) - (local.get $input) - ) - ) - (local.get $tempresult) - ) - - ;; CHECK: (func $propagate-uncertain-local (result i32) - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local $stashedref (ref null $empty)) - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $stashedref - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: (local.get $stashedref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $tempresult) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-uncertain-local (type $func-return-i32) (result i32) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $stashedref - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: (local.get $stashedref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $tempresult) - ;; NOMNL-NEXT: ) - (func $propagate-uncertain-local (result i32) - (local $tempresult i32) - (local $tempref (ref null $empty)) - (local $stashedref (ref null $empty)) - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - (local.set $stashedref - (local.get $tempref) - ) - ;; This if makes it impossible to know what value the ref.eq later should - ;; return. - (if - (call $helper - (i32.const 0) - ) - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - ) - (local.set $tempresult - (ref.eq - (local.get $tempref) - (local.get $stashedref) - ) - ) - (local.get $tempresult) - ) - - ;; CHECK: (func $propagate-uncertain-loop - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local $stashedref (ref null $empty)) - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $stashedref - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: (local.get $stashedref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (local.get $tempresult) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-uncertain-loop (type $none_=>_none) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $stashedref - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (loop $loop - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: (local.get $stashedref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br_if $loop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (local.get $tempresult) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $propagate-uncertain-loop - (local $tempresult i32) - (local $tempref (ref null $empty)) - (local $stashedref (ref null $empty)) - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - (local.set $stashedref - (local.get $tempref) - ) - (loop $loop - ;; Each iteration in this loop may see a different struct, so we cannot - ;; precompute the ref.eq here. - (local.set $tempresult - (ref.eq - (local.get $tempref) - (local.get $stashedref) - ) - ) - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - (br_if $loop - (call $helper - (local.get $tempresult) - ) - ) - ) - ) - - ;; CHECK: (func $propagate-certain-loop - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local $stashedref (ref null $empty)) - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $stashedref - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-certain-loop (type $none_=>_none) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $stashedref - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (loop $loop - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br_if $loop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $propagate-certain-loop - (local $tempresult i32) - (local $tempref (ref null $empty)) - (local $stashedref (ref null $empty)) - ;; As above, but remove the new in the loop, so that each loop iteration does - ;; in fact have the ref locals identical, and we can precompute a 1. - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - (local.set $stashedref - (local.get $tempref) - ) - (loop $loop - (local.set $tempresult - (ref.eq - (local.get $tempref) - (local.get $stashedref) - ) - ) - (br_if $loop - (call $helper - (local.get $tempresult) - ) - ) - ) - ) - - ;; CHECK: (func $propagate-certain-loop-2 - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local $stashedref (ref null $empty)) - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $stashedref - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-certain-loop-2 (type $none_=>_none) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) - ;; NOMNL-NEXT: (loop $loop - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $stashedref - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br_if $loop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $propagate-certain-loop-2 - (local $tempresult i32) - (local $tempref (ref null $empty)) - (local $stashedref (ref null $empty)) - (loop $loop - ;; Another example of a loop where we can optimize. Here the new is inside - ;; the loop. - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - (local.set $stashedref - (local.get $tempref) - ) - (local.set $tempresult - (ref.eq - (local.get $tempref) - (local.get $stashedref) - ) - ) - (br_if $loop - (call $helper - (local.get $tempresult) - ) - ) - ) - ) - - ;; CHECK: (func $propagate-possibly-certain-loop - ;; CHECK-NEXT: (local $tempresult i32) - ;; CHECK-NEXT: (local $tempref (ref null $empty)) - ;; CHECK-NEXT: (local $stashedref (ref null $empty)) - ;; CHECK-NEXT: (loop $loop - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempref - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $stashedref - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $tempresult - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $tempref) - ;; CHECK-NEXT: (local.get $stashedref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (local.get $tempresult) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $propagate-possibly-certain-loop (type $none_=>_none) - ;; NOMNL-NEXT: (local $tempresult i32) - ;; NOMNL-NEXT: (local $tempref (ref null $empty)) - ;; NOMNL-NEXT: (local $stashedref (ref null $empty)) - ;; NOMNL-NEXT: (loop $loop - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempref - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $stashedref - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $tempresult - ;; NOMNL-NEXT: (ref.eq - ;; NOMNL-NEXT: (local.get $tempref) - ;; NOMNL-NEXT: (local.get $stashedref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br_if $loop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (local.get $tempresult) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $propagate-possibly-certain-loop - (local $tempresult i32) - (local $tempref (ref null $empty)) - (local $stashedref (ref null $empty)) - (loop $loop - ;; As above, but move the set of $stashedref below the if. That means that - ;; it must be identical to $tempref in each iteration. However, that is - ;; something we cannot infer atm (while SSA could), so we do not infer - ;; anything here for now. - (if - (call $helper - (i32.const 0) - ) - (local.set $tempref - (struct.new_with_rtt $empty - (rtt.canon $empty) - ) - ) - ) - (local.set $stashedref - (local.get $tempref) - ) - (local.set $tempresult - (ref.eq - (local.get $tempref) - (local.get $stashedref) - ) - ) - (br_if $loop - (call $helper - (local.get $tempresult) - ) - ) - ) - ) - - ;; CHECK: (func $helper (param $0 i32) (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $helper (type $i32_=>_i32) (param $0 i32) (result i32) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $helper (param i32) (result i32) - (unreachable) - ) - - ;; CHECK: (func $odd-cast-and-get - ;; CHECK-NEXT: (local $temp (ref null $B)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 0 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $odd-cast-and-get (type $none_=>_none) - ;; NOMNL-NEXT: (local $temp (ref null $B)) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get $B 0 - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $odd-cast-and-get - (local $temp (ref null $B)) - ;; Try to cast a null of A to B. While the types are incompatible, ref.cast - ;; returns a null when given a null (and the null must have the type that the - ;; ref.cast instruction has, that is, the value is a null of type $B). So this - ;; is an odd cast that "works". - (local.set $temp - (ref.cast - (ref.null $A) - (rtt.canon $B) - ) - ) - (drop - ;; Read from the local, which precompute should set to a null with the proper - ;; type. - (struct.get $B 0 - (local.get $temp) - ) - ) - ) - - ;; CHECK: (func $odd-cast-and-get-tuple - ;; CHECK-NEXT: (local $temp ((ref null $B) i32)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $B 0 - ;; CHECK-NEXT: (ref.null $B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $odd-cast-and-get-tuple (type $none_=>_none) - ;; NOMNL-NEXT: (local $temp ((ref null $B) i32)) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (tuple.make - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: (i32.const 10) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (struct.get $B 0 - ;; NOMNL-NEXT: (ref.null $B) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $odd-cast-and-get-tuple - (local $temp ((ref null $B) i32)) - ;; As above, but with a tuple. - (local.set $temp - (tuple.make - (ref.cast - (ref.null $A) - (rtt.canon $B) - ) - (i32.const 10) - ) - ) - (drop - (struct.get $B 0 - (tuple.extract 0 - (local.get $temp) - ) - ) - ) - ) - - ;; CHECK: (func $receive-f64 (param $0 f64) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $receive-f64 (type $f64_=>_none) (param $0 f64) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $receive-f64 (param f64) - (unreachable) - ) - - ;; CHECK: (func $odd-cast-and-get-non-null (param $temp (ref $func-return-i32)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.func $receive-f64) - ;; CHECK-NEXT: (rtt.canon $func-return-i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $odd-cast-and-get-non-null (type $ref|$func-return-i32|_=>_none) (param $temp (ref $func-return-i32)) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.func $receive-f64) - ;; NOMNL-NEXT: (rtt.canon $func-return-i32) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call_ref - ;; NOMNL-NEXT: (local.get $temp) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $odd-cast-and-get-non-null (param $temp (ref $func-return-i32)) - ;; Try to cast a function to an incompatible type. - (local.set $temp - (ref.cast - (ref.func $receive-f64) - (rtt.canon $func-return-i32) - ) - ) - (drop - ;; Read from the local, checking whether precompute set a value there (it - ;; should not, as the cast fails). - (call_ref - (local.get $temp) - ) - ) - ) - - ;; Regression test checking that breaking RTTs are interpreted correctly. - ;; CHECK: (func $cast-breaking-rtt - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (ref.cast - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: (call $unreachable-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $unreachable-rtt) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $cast-breaking-rtt (type $none_=>_none) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (ref.cast - ;; NOMNL-NEXT: (struct.new_default $struct) - ;; NOMNL-NEXT: (call $unreachable-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (call $unreachable-rtt) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $cast-breaking-rtt - (drop - (ref.cast - (ref.cast - (struct.new_default $struct) - (call $unreachable-rtt) - ) - (call $unreachable-rtt) - ) - ) - ) - - ;; CHECK: (func $unreachable-rtt (result (rtt $struct)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unreachable-rtt (type $none_=>_rtt_$struct) (result (rtt $struct)) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $unreachable-rtt (result (rtt $struct)) - (unreachable) - ) - - ;; CHECK: (func $new_block_unreachable (result anyref) - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $new_block_unreachable (type $none_=>_anyref) (result anyref) - ;; NOMNL-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (block - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (rtt.canon $struct) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $new_block_unreachable (result anyref) - (struct.new_with_rtt $struct - ;; The value is a block with an unreachable. precompute will get rid of the - ;; block, after which fuzz-exec should not crash - this is a regression test - ;; for us being careful in how we execute an unreachable struct.new - (block $label$1 (result i32) - (unreachable) - ) - (rtt.canon $struct) - ) - ) - - ;; CHECK: (func $br_on_cast-on-creation-rtt (result (ref $empty)) - ;; CHECK-NEXT: (block $label (result (ref $empty)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast $label - ;; CHECK-NEXT: (struct.new_default_with_rtt $empty - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $br_on_cast-on-creation-rtt (type $none_=>_ref|$empty|) (result (ref $empty)) - ;; NOMNL-NEXT: (block $label (result (ref $empty)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_on_cast $label - ;; NOMNL-NEXT: (struct.new_default_with_rtt $empty - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (rtt.canon $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $br_on_cast-on-creation-rtt (result (ref $empty)) - (block $label (result (ref $empty)) - (drop - ;; The br_on_cast will read the GC data created from struct.new, which must - ;; emit it properly, including with an RTT which it will read from (since - ;; this instructions uses an RTT). - (br_on_cast $label - (struct.new_default_with_rtt $empty - (rtt.canon $empty) - ) - (rtt.canon $empty) - ) - ) - (unreachable) - ) - ) - - ;; CHECK: (func $br_on_cast-on-creation-nortt (result (ref $empty)) - ;; CHECK-NEXT: (block $label (result (ref $empty)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast_static $label $empty - ;; CHECK-NEXT: (struct.new_default $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $br_on_cast-on-creation-nortt (type $none_=>_ref|$empty|) (result (ref $empty)) - ;; NOMNL-NEXT: (block $label (result (ref $empty)) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_on_cast_static $label $empty - ;; NOMNL-NEXT: (struct.new_default $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $br_on_cast-on-creation-nortt (result (ref $empty)) - (block $label (result (ref $empty)) - (drop - ;; As above, but with no RTTs. - (br_on_cast_static $label $empty - (struct.new_default $empty) - ) - ) - (unreachable) - ) - ) - - ;; CHECK: (func $ref.is_null (param $param i32) - ;; CHECK-NEXT: (local $ref (ref null $empty)) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (ref.null $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: (local.set $ref - ;; CHECK-NEXT: (struct.new_default $empty) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $helper - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (local.get $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $ref.is_null (type $i32_=>_none) (param $param i32) - ;; NOMNL-NEXT: (local $ref (ref null $empty)) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (ref.null $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (if - ;; NOMNL-NEXT: (local.get $param) - ;; NOMNL-NEXT: (local.set $ref - ;; NOMNL-NEXT: (struct.new_default $empty) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (call $helper - ;; NOMNL-NEXT: (ref.is_null - ;; NOMNL-NEXT: (local.get $ref) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $ref.is_null (param $param i32) - (local $ref (ref null $empty)) - ;; Test ref.null on references, and also test that we can infer multiple - ;; assignments in the same function, without confusion between them. - (local.set $ref - (struct.new $empty) - ) - (drop - (call $helper - ;; The reference here is definitely not null. - (ref.is_null - (local.get $ref) - ) - ) - ) - (local.set $ref - (ref.null $empty) - ) - (drop - (call $helper - ;; The reference here is definitely null. - (ref.is_null - (local.get $ref) - ) - ) - ) - (if - (local.get $param) - (local.set $ref - (struct.new $empty) - ) - ) - (drop - (call $helper - ;; The reference here might be null. - (ref.is_null - (local.get $ref) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/remove-unused-brs-gc.wast binaryen-99/test/lit/passes/remove-unused-brs-gc.wast --- binaryen-108/test/lit/passes/remove-unused-brs-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/remove-unused-brs-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-brs -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (type $struct (struct )) - (type $struct (struct )) - - ;; CHECK: (func $br_on_non_data-1 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $any (result anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $any - ;; CHECK-NEXT: (ref.func $br_on_non_data-1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_non_data-1 - (drop - (block $any (result anyref) - (drop - ;; A function is not data, and so we should branch. - (br_on_non_data $any - (ref.func $br_on_non_data-1) - ) - ) - (ref.null any) - ) - ) - ) - ;; CHECK: (func $br_on_non_data-2 (param $data dataref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $any (result anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_non_data-2 (param $data (ref data)) - (drop - (block $any (result anyref) - (drop - ;; Data is provided here, and so we will not branch. - (br_on_non_data $any - (local.get $data) - ) - ) - (ref.null any) - ) - ) - ) - - ;; CHECK: (func $br_on-if (param $0 dataref) - ;; CHECK-NEXT: (block $label - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (select (result dataref) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on-if (param $0 (ref data)) - (block $label - (drop - ;; This br is never taken, as the input is non-nullable, so we can remove - ;; it. When we do so, we replace it with the if. We should not rescan that - ;; if, which has already been walked, as that would hit an assertion. - ;; - (br_on_null $label - ;; This if can also be turned into a select, separately from the above - ;; (that is not specifically intended to be tested here). - (if (result (ref data)) - (i32.const 0) - (local.get $0) - (local.get $0) - ) - ) - ) - ) - ) - - ;; CHECK: (func $nested_br_on (result dataref) - ;; CHECK-NEXT: (block $label$1 (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $label$1 - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested_br_on (result dataref) - (block $label$1 (result dataref) - (drop - ;; The inner br_on_data will become a direct br since the type proves it - ;; is in fact data. That then becomes unreachable, and the parent must - ;; handle that properly (do nothing without hitting an assertion). - (br_on_data $label$1 - (br_on_data $label$1 - (struct.new_default $struct) - ) - ) - ) - (unreachable) - ) - ) - - ;; CHECK: (func $br_on_cast_static (result (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $struct)) - ;; CHECK-NEXT: (block $block (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br $block - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_cast_static (result (ref $struct)) - (local $temp (ref null $struct)) - (block $block (result (ref $struct)) - (drop - ;; This static cast can be computed at compile time: it will definitely be - ;; taken, so we can turn it into a normal br. - (br_on_cast_static $block $struct - (struct.new $struct) - ) - ) - (unreachable) - ) - ) - - ;; CHECK: (func $br_on_cast_static_no (result (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $struct)) - ;; CHECK-NEXT: (block $block (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast_static $block $struct - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_cast_static_no (result (ref $struct)) - (local $temp (ref null $struct)) - (block $block (result (ref $struct)) - (drop - (br_on_cast_static $block $struct - ;; As above, but now the type is nullable, so we cannot infer anything. - (ref.null $struct) - ) - ) - (unreachable) - ) - ) - - ;; CHECK: (func $br_on_cast_fail_static (result (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $struct)) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_cast_fail_static (result (ref $struct)) - (local $temp (ref null $struct)) - (block $block (result (ref $struct)) - (drop - ;; As $br_on_cast_static, but this checks for a failing cast, so we know it will - ;; *not* be taken. - (br_on_cast_static_fail $block $struct - (struct.new $struct) - ) - ) - (unreachable) - ) - ) - - ;; CHECK: (func $br_on_cast_dynamic (result (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $struct)) - ;; CHECK-NEXT: (block $block (result (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_cast $block - ;; CHECK-NEXT: (struct.new_default_with_rtt $struct - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rtt.canon $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $br_on_cast_dynamic (result (ref $struct)) - (local $temp (ref null $struct)) - (block $block (result (ref $struct)) - (drop - ;; This dynamic cast happens to be optimizable since we see both sides use - ;; rtt.canon, but we do not inspect things that closely, and leave such - ;; dynamic casts to runtime. - (br_on_cast $block - (struct.new_with_rtt $struct - (rtt.canon $struct) - ) - (rtt.canon $struct) - ) - ) - (unreachable) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/remove-unused-brs.wast binaryen-99/test/lit/passes/remove-unused-brs.wast --- binaryen-108/test/lit/passes/remove-unused-brs.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/remove-unused-brs.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,545 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-brs -all -S -o - \ -;; RUN: | filecheck %s - - -(module - ;; CHECK: (type $none_=>_i32 (func (result i32))) - (type $none_=>_i32 (func (result i32))) - ;; CHECK: (type $i32_=>_none (func (param i32))) - (type $i32_=>_none (func (param i32))) - - ;; Regression test in which we need to calculate a proper LUB. - ;; CHECK: (func $selectify-fresh-lub (param $x i32) (result anyref) - ;; CHECK-NEXT: (select (result funcref) - ;; CHECK-NEXT: (ref.null $none_=>_i32) - ;; CHECK-NEXT: (ref.null $i32_=>_none) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $selectify-fresh-lub (param $x i32) (result anyref) - (if - (local.get $x) - (return - (ref.null $none_=>_i32) - ) - (return - (ref.null $i32_=>_none) - ) - ) - ) - - ;; CHECK: (func $selectify-simple (param $0 i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 97) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $selectify-simple (param $0 i32) (result i32) - (if (result i32) - (i32.lt_u - (i32.sub - (local.get $0) - (i32.const 48) - ) - (i32.const 10) - ) - (i32.const 1) - (i32.lt_u - (i32.sub - (i32.or - (local.get $0) - (i32.const 32) - ) - (i32.const 97) - ) - (i32.const 6) - ) - ) - ) - - ;; CHECK: (func $restructure-br_if (param $x i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if (param $x i32) (result i32) - ;; this block+br_if can be turned into an if. - (block $x (result i32) - (drop - (br_if $x - (i32.const 100) - (local.get $x) - ) - ) - (drop (i32.const 200)) - (i32.const 300) - ) - ) - - ;; CHECK: (func $nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nothing) - - - ;; CHECK: (func $restructure-br_if-condition-reorderable (param $x i32) (result i32) - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if-condition-reorderable (param $x i32) (result i32) - (block $x (result i32) - (drop - (br_if $x - (i32.const 100) - ;; the condition has side effects, but can be reordered with the value - (block (result i32) - (call $nothing) - (local.get $x) - ) - ) - ) - (drop (i32.const 200)) - (i32.const 300) - ) - ) - - ;; CHECK: (func $restructure-br_if-value-effectful (param $x i32) (result i32) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 200) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block0 (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if-value-effectful (param $x i32) (result i32) - (block $x (result i32) - (drop - (br_if $x - ;; the value has side effects, but we can use a select instead - ;; of an if, which keeps the value first - (block (result i32) - (call $nothing) - (i32.const 100) - ) - ;; the condition has side effects too, but can be be reordered - ;; to the end of the block - (block (result i32) - (call $nothing) - (local.get $x) - ) - ) - ) - (drop (i32.const 200)) - (i32.const 300) - ) - ) - - ;; CHECK: (func $restructure-br_if-value-effectful-corner-case-1 (param $x i32) (result i32) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $x - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block1 (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if-value-effectful-corner-case-1 (param $x i32) (result i32) - (block $x (result i32) - (drop - (br_if $x - (block (result i32) - (call $nothing) - (i32.const 100) - ) - (block (result i32) - (call $nothing) - (local.get $x) - ) - ) - ) - ;; the condition cannot be reordered with this - (call $nothing) - (i32.const 300) - ) - ) - - ;; CHECK: (func $get-i32 (result i32) - ;; CHECK-NEXT: (i32.const 400) - ;; CHECK-NEXT: ) - (func $get-i32 (result i32) - (i32.const 400) - ) - - ;; CHECK: (func $restructure-br_if-value-effectful-corner-case-2 (param $x i32) (result i32) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $x - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block2 (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $get-i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if-value-effectful-corner-case-2 (param $x i32) (result i32) - (block $x (result i32) - (drop - (br_if $x - (block (result i32) - (call $nothing) - (i32.const 100) - ) - (block (result i32) - (call $nothing) - (local.get $x) - ) - ) - ) - (drop (i32.const 300)) - ;; the condition cannot be reordered with this - (call $get-i32) - ) - ) - ;; CHECK: (func $restructure-br_if-value-effectful-corner-case-3 (param $x i32) (result i32) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $x - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if-value-effectful-corner-case-3 (param $x i32) (result i32) - (block $x (result i32) - (drop - (br_if $x - ;; we can't do an if because of effects here - (block (result i32) - (call $nothing) - (i32.const 100) - ) - (local.get $x) - ) - ) - ;; and we can't do a select because of effects here - (call $nothing) - (i32.const 100) - ) - ) - - ;; CHECK: (func $restructure-br_if-value-effectful-corner-case-4 (param $x i32) (result i32) - ;; CHECK-NEXT: (block $x (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $x - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $nothing) - ;; CHECK-NEXT: (i32.const 100) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 300) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $get-i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-br_if-value-effectful-corner-case-4 (param $x i32) (result i32) - (block $x (result i32) - (drop - (br_if $x - ;; we can't do an if because of effects here - (block (result i32) - (call $nothing) - (i32.const 100) - ) - (local.get $x) - ) - ) - (drop (i32.const 300)) - ;; and we can't do a select because of effects here - (call $get-i32) - ) - ) - - ;; CHECK: (func $restructure-select-no-multivalue - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $block (result i32 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_if $block - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $restructure-br_if - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $restructure-select-no-multivalue - (drop - (block $block (result i32 i32) - (drop - (br_if $block - (tuple.make - (i32.const 1) - ;; Add a side effect to prevent us turning $block into a - ;; restructured if - instead, we will try a restructured select. - ;; But, selects cannot return multiple values in the spec, so we - ;; can do nothing here. - (call $restructure-br_if - (i32.const 2) - ) - ) - (i32.const 3) - ) - ) - (tuple.make - (i32.const 4) - (i32.const 5) - ) - ) - ) - ) - - ;; CHECK: (func $if-of-if - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-of-if) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-of-if - (local $x i32) - ;; The outer if has side effects in the condition while the inner one does - ;; not, which means we can fold them. - (if - (local.tee $x - (i32.const 1) - ) - (if - (local.get $x) - (call $if-of-if) - ) - ) - ) - - ;; CHECK: (func $if-of-if-but-side-effects - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-of-if-but-side-effects) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-of-if-but-side-effects - (local $x i32) - ;; The inner if has side effects in the condition, which prevents this - ;; optimization. - (if - (local.tee $x - (i32.const 1) - ) - (if - (local.tee $x - (i32.const 2) - ) - (call $if-of-if-but-side-effects) - ) - ) - ) - - ;; CHECK: (func $if-of-if-but-too-costly - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-of-if-but-too-costly) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-of-if-but-too-costly - (local $x i32) - ;; The inner if's condition has no effects, but it is very costly, so do not - ;; run it unconditionally - leave this unoptimized. - (if - (local.tee $x - (i32.const 1) - ) - (if - (i32.eqz (i32.eqz (i32.eqz (i32.eqz (i32.eqz (i32.eqz (i32.eqz (i32.eqz (i32.eqz - (local.get $x) - ))))))))) - (call $if-of-if-but-too-costly) - ) - ) - ) - - ;; CHECK: (func $if-of-if-but-inner-else - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $if-of-if-but-inner-else) - ;; CHECK-NEXT: (call $if-of-if) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-of-if-but-inner-else - (local $x i32) - ;; The inner if has an else. For now, leave this unoptimized. - (if - (local.tee $x - (i32.const 1) - ) - (if - (local.get $x) - (call $if-of-if-but-inner-else) - (call $if-of-if) - ) - ) - ) - - ;; CHECK: (func $if-of-if-but-outer-else - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (call $if-of-if-but-outer-else) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $if-of-if) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-of-if-but-outer-else - (local $x i32) - ;; The outer if has an else. For now, leave this unoptimized. - (if - (local.tee $x - (i32.const 1) - ) - (if - (local.get $x) - (call $if-of-if-but-outer-else) - ) - (call $if-of-if) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/remove-unused-module-elements-eh.wast binaryen-99/test/lit/passes/remove-unused-module-elements-eh.wast --- binaryen-108/test/lit/passes/remove-unused-module-elements-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/remove-unused-module-elements-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -;; RUN: wasm-opt %s --remove-unused-module-elements -all -S -o - | filecheck %s - -;; Non-exported and unused tags can be removed -(module - (type $0 (func (param i32))) - - ;; CHECK-NOT: (tag $e-remove - ;; CHECK: (tag $e-export - ;; CHECK: (tag $e-throw - ;; CHECK: (tag $e-catch - (tag $e-remove (type $0)) ;; can be removed - (tag $e-export (param i64)) ;; cannot be removed (exported) - (tag $e-throw (type $0)) ;; cannot be removed (used in throw) - (tag $e-catch (type $0)) ;; cannot be removed (used in catch) - - (export "e-export" (tag $e-export)) - (import "env" "e" (tag $e-import (param i32))) - - (start $start) - (func $start - (try - (do - (throw $e-throw (i32.const 0)) - ) - (catch $e-catch - (drop (pop i32)) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/remove-unused-module-elements-refs.wast binaryen-99/test/lit/passes/remove-unused-module-elements-refs.wast --- binaryen-108/test/lit/passes/remove-unused-module-elements-refs.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/remove-unused-module-elements-refs.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,338 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --remove-unused-module-elements --nominal -all -S -o - | filecheck %s - -(module - ;; CHECK: (type $A (func_subtype func)) - (type $A (func)) - ;; CHECK: (type $B (func_subtype func)) - (type $B (func)) - - ;; CHECK: (elem declare func $target-A $target-B) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (export "foo") - ;; This export has two RefFuncs, and one CallRef. - (drop - (ref.func $target-A) - ) - (drop - (ref.func $target-B) - ) - (call_ref - (ref.null $A) - ) - ;; Verify that we do not crash on an unreachable call_ref, which has no - ;; heap type for us to analyze. - (call_ref - (unreachable) - ) - ) - - ;; CHECK: (func $target-A (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-A (type $A) - ;; This function is reachable from the export "foo": there is a RefFunc and - ;; a CallRef for it there. - ) - - (func $target-A-noref (type $A) - ;; This function is not reachable. We have a CallRef of the right type, but - ;; no RefFunc. - ) - - ;; CHECK: (func $target-B (type $B) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $target-B (type $B) - ;; This function is not reachable. We have a RefFunc in "foo" but no - ;; suitable CallRef. - ;; - ;; Note that we cannot remove the function, as the RefFunc must refer to - ;; something in order to validate. But we can clear out the body of this - ;; function with an unreachable. - ) -) - -;; As above, but reverse the order inside $foo, so we see the CallRef first. -(module - ;; CHECK: (type $A (func_subtype func)) - (type $A (func)) - (type $B (func)) - - ;; CHECK: (elem declare func $target-A) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (export "foo") - (call_ref - (ref.null $A) - ) - (drop - (ref.func $target-A) - ) - ) - - ;; CHECK: (func $target-A (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-A (type $A) - ;; This function is reachable. - ) - - (func $target-A-noref (type $A) - ;; This function is not reachable. - ) -) - -;; As above, but interleave CallRefs with RefFuncs. -(module - ;; CHECK: (type $A (func_subtype func)) - (type $A (func)) - (type $B (func)) - - ;; CHECK: (elem declare func $target-A-1 $target-A-2) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-A-1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-A-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (export "foo") - (call_ref - (ref.null $A) - ) - (drop - (ref.func $target-A-1) - ) - (call_ref - (ref.null $A) - ) - (drop - (ref.func $target-A-2) - ) - ) - - ;; CHECK: (func $target-A-1 (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-A-1 (type $A) - ;; This function is reachable. - ) - - ;; CHECK: (func $target-A-2 (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-A-2 (type $A) - ;; This function is reachable. - ) - - (func $target-A-3 (type $A) - ;; This function is not reachable. - ) -) - -;; As above, with the order reversed inside $foo. The results should be the -;; same. -(module - ;; CHECK: (type $A (func_subtype func)) - (type $A (func)) - (type $B (func)) - - ;; CHECK: (elem declare func $target-A-1 $target-A-2) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-A-1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-A-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (export "foo") - (drop - (ref.func $target-A-1) - ) - (call_ref - (ref.null $A) - ) - (drop - (ref.func $target-A-2) - ) - (call_ref - (ref.null $A) - ) - ) - - ;; CHECK: (func $target-A-1 (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-A-1 (type $A) - ;; This function is reachable. - ) - - ;; CHECK: (func $target-A-2 (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-A-2 (type $A) - ;; This function is reachable. - ) - - (func $target-A-3 (type $A) - ;; This function is not reachable. - ) -) - -;; The call.without.effects intrinsic does a call to the reference given to it, -;; but for now other imports do not (until we add a flag for closed-world). -(module - ;; CHECK: (type $A (func_subtype func)) - (type $A (func)) - - ;; CHECK: (type $funcref_=>_none (func_subtype (param funcref) func)) - - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) - (import "binaryen-intrinsics" "call.without.effects" - (func $call-without-effects (param funcref))) - - ;; CHECK: (import "other" "import" (func $other-import (param funcref))) - (import "other" "import" - (func $other-import (param funcref))) - - ;; CHECK: (elem declare func $target-drop $target-keep) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (call $call-without-effects - ;; CHECK-NEXT: (ref.func $target-keep) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $other-import - ;; CHECK-NEXT: (ref.func $target-drop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (export "foo") - ;; Calling the intrinsic with a reference is considered a call of the - ;; reference, so we will not remove $target-keep. - (call $call-without-effects - (ref.func $target-keep) - ) - ;; The other import is not enough to keep $target-drop alive. - (call $other-import - (ref.func $target-drop) - ) - ) - - ;; CHECK: (func $target-keep (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-keep (type $A) - ) - - ;; CHECK: (func $target-drop (type $A) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $target-drop (type $A) - ) -) - -;; As above, but now the call to the intrinsic does not let us see the exact -;; function being called. -(module - ;; CHECK: (type $A (func_subtype func)) - (type $A (func)) - - ;; CHECK: (type $funcref_=>_none (func_subtype (param funcref) func)) - - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call-without-effects (param funcref))) - (import "binaryen-intrinsics" "call.without.effects" - (func $call-without-effects (param funcref))) - - ;; CHECK: (import "other" "import" (func $other-import (param funcref))) - (import "other" "import" - (func $other-import (param funcref))) - - ;; CHECK: (elem declare func $target-keep $target-keep-2) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (call $call-without-effects - ;; CHECK-NEXT: (ref.null $A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.func $target-keep) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $other-import - ;; CHECK-NEXT: (ref.func $target-keep-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (export "foo") - ;; Call the intrinsic without a RefFunc. All we infer here is the type, - ;; which means we must assume anything with type $A (and a reference) can be - ;; called, which will keep alive both $target-keep and $target-keep-2 - (call $call-without-effects - (ref.null $A) - ) - (drop - (ref.func $target-keep) - ) - (call $other-import - (ref.func $target-keep-2) - ) - ) - - ;; CHECK: (func $target-keep (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-keep (type $A) - ) - - ;; CHECK: (func $target-keep-2 (type $A) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $target-keep-2 (type $A) - ) -) diff -Nru binaryen-108/test/lit/passes/remove-unused-names-eh.wast binaryen-99/test/lit/passes/remove-unused-names-eh.wast --- binaryen-108/test/lit/passes/remove-unused-names-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/remove-unused-names-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --remove-unused-names -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $tag$0 (param i32)) - (tag $tag$0 (param i32)) - - ;; CHECK: (func $func0 - ;; CHECK-NEXT: (try $label$9 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (try $label$8 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (rethrow $label$9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $label$8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func0 - (try $label$9 ;; needed due to a rethrow - (do) - (catch_all - (try $label$8 ;; needed due to a delegate - (do - (try $label$6 ;; this one is not needed - (do - (rethrow $label$9) - ) - (delegate $label$8) - ) - ) - (catch $tag$0 - (drop - (pop i32) - ) - ) - ) - ) - ) - ) - - ;; CHECK: (func $func1 - ;; CHECK-NEXT: (try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func1 - (try $label$3 ;; this one is not needed - (do - (nop) - ) - (delegate 0) ;; delegates to the caller - ) - ) -) diff -Nru binaryen-108/test/lit/passes/roundtrip-gc-types.wast binaryen-99/test/lit/passes/roundtrip-gc-types.wast --- binaryen-108/test/lit/passes/roundtrip-gc-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/roundtrip-gc-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --roundtrip --nominal -S -o - | filecheck %s --check-prefix NOMNL - -;; Regression test for an issue in which roundtripping failed to reproduce the -;; original types because type canonicalization was incorrect when the canonical -;; types already existed in the store. - -(module - ;; CHECK: (type $A (struct (field (ref $C)))) - ;; NOMNL: (type $A (struct_subtype (field (ref $C)) data)) - (type $A (struct (field (ref $C)))) - ;; CHECK: (type $C (struct (field (mut (ref $B))))) - - ;; CHECK: (type $B (func (param (ref $A)) (result (ref $B)))) - ;; NOMNL: (type $C (struct_subtype (field (mut (ref $B))) data)) - - ;; NOMNL: (type $B (func_subtype (param (ref $A)) (result (ref $B)) func)) - (type $B (func (param (ref $A)) (result (ref $B)))) - (type $C (struct (field (mut (ref $B))))) - ;; CHECK: (type $D (struct (field (ref $C)) (field (ref $A)))) - ;; NOMNL: (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) - (type $D (struct_subtype (field (ref $C)) (field (ref $A)) $A)) - ;; CHECK: (global $g0 (rtt 0 $A) (rtt.canon $A)) - ;; NOMNL: (global $g0 (rtt 0 $A) (rtt.canon $A)) - (global $g0 (rtt 0 $A) (rtt.canon $A)) - ;; CHECK: (global $g1 (rtt 1 $D) (rtt.sub $D - ;; CHECK-NEXT: (global.get $g0) - ;; CHECK-NEXT: )) - ;; NOMNL: (global $g1 (rtt 1 $D) (rtt.sub $D - ;; NOMNL-NEXT: (global.get $g0) - ;; NOMNL-NEXT: )) - (global $g1 (rtt 1 $D) (rtt.sub $D - (global.get $g0) - )) -) diff -Nru binaryen-108/test/lit/passes/roundtrip-gc.wast binaryen-99/test/lit/passes/roundtrip-gc.wast --- binaryen-108/test/lit/passes/roundtrip-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/roundtrip-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --generate-stack-ir --optimize-stack-ir --roundtrip --nominal -S -o - | filecheck %s --check-prefix NOMNL - -(module - (type ${i32} (struct (field i32))) - ;; CHECK: (export "export" (func $test)) - ;; NOMNL: (export "export" (func $test)) - (export "export" (func $test)) - ;; CHECK: (func $test - ;; CHECK-NEXT: (call $help - ;; CHECK-NEXT: (rtt.canon $\7bi32\7d) - ;; CHECK-NEXT: (block $label$1 (result i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $test (type $none_=>_none) - ;; NOMNL-NEXT: (call $help - ;; NOMNL-NEXT: (rtt.canon $\7bi32\7d) - ;; NOMNL-NEXT: (block $label$1 (result i32) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (i32.const 1) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $test - (call $help - (rtt.canon ${i32}) - ;; Stack IR optimizations can remove this block, leaving a nop in an odd - ;; "stacky" location. On load, we would normally use a local to work around - ;; that, creating a block to contain the rtt before us and the nop, and then - ;; returning the local. But we can't use a local for an rtt, so we should not - ;; optimize this sort of thing in stack IR. - (block (result i32) - (nop) - (i32.const 1) - ) - ) - ) - ;; CHECK: (func $help (param $3 (rtt $\7bi32\7d)) (param $4 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $help (type $rtt_$\7bi32\7d_i32_=>_none) (param $3 (rtt $\7bi32\7d)) (param $4 i32) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: ) - (func $help (param $3 (rtt ${i32})) (param $4 i32) - (nop) - ) -) diff -Nru binaryen-108/test/lit/passes/roundtrip-table.wast binaryen-99/test/lit/passes/roundtrip-table.wast --- binaryen-108/test/lit/passes/roundtrip-table.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/roundtrip-table.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --roundtrip -S -o - - -(module - (type $functype (func)) - (table $0 48 funcref) - ;; a type that appears in the table and nowhere else. this test checks that - ;; we do not crash during the roundtrip on seeing an unexpected type that - ;; collectHeapTypes() did not scan. - (elem (table $0) (i32.const 0) funcref (ref.null $functype)) -) diff -Nru binaryen-108/test/lit/passes/roundtrip.wast binaryen-99/test/lit/passes/roundtrip.wast --- binaryen-108/test/lit/passes/roundtrip.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/roundtrip.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s - -(module - ;; CHECK: (type $none (func)) - (type $none (func)) - ;; CHECK: (func $foo - ;; CHECK-NEXT: (local $0 (funcref (ref null $none))) - ;; CHECK-NEXT: (local $1 funcref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (block $label$1 (result funcref (ref $none)) - ;; CHECK-NEXT: (tuple.make - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result funcref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (tuple.extract 0 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (tuple.extract 1 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (drop - ;; a tuple type with a non-nullable element, that must be carefully handled - (block (result funcref (ref $none)) - (tuple.make - (ref.null func) - (ref.func $foo) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/rse-eh.wast binaryen-99/test/lit/passes/rse-eh.wast --- binaryen-108/test/lit/passes/rse-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/rse-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,813 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --rse -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e (param i32)) - (tag $e (param i32)) - ;; CHECK: (tag $e2 (param)) - (tag $e2) - - ;; CHECK: (func $try1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try1 - (local $x i32) - (try - (do) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ;; try will not throw. So this should NOT be dropped - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try2 - (local $x i32) - (try - (do - (throw $e (i32.const 0)) - (local.set $x (i32.const 1)) - ) - (catch_all) - ) - ;; local.set is after 'throw' so it will not run. This should NOT be - ;; dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try3 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try3 - (local $x i32) - (try - (do - (throw $e (i32.const 0)) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ;; try body will throw and catch_all contains the same local.set. This - ;; should be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo) - - ;; CHECK: (func $try4 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try4 - (local $x i32) - (try - (do - (call $foo) - (local.set $x (i32.const 1)) - ) - (catch_all) - ) - ;; (call $foo) may throw and the local.set may not run, so this should NOT - ;; be dropped - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try5 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try5 - (local $x i32) - (try - (do - (local.set $x (i32.const 1)) - (call $foo) - ) - (catch_all) - ) - ;; Even if (call $foo) throws, local.set runs before it, so this should be - ;; dropped - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $nested-try1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (rethrow $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-try1 - (local $x i32) - (try - (do - (try $l0 - (do - (throw $e (i32.const 0)) - ) - (catch_all - (rethrow $l0) - ) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ;; The exception is caught by the inner catch_all and rethrown and again - ;; caught by the outer catch_all, which runs the local.set. So this should - ;; be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $nested-try2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rethrow $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-try2 - (local $x i32) - (try - (do - (try $l0 - (do - (throw $e (i32.const 0)) - ) - (catch_all - (local.set $x (i32.const 1)) - (rethrow $l0) - ) - ) - ) - (catch_all) - ) - ;; The exception is caught by the inner catch_all, which runs the local.set, - ;; so this should be dropped - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $nested-try3 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (rethrow $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-try3 - (local $x i32) - (try - (do - (try $l0 - (do - (throw $e (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - (local.set $x (i32.const 1)) - (rethrow $l0) - ) - ) - ) - (catch_all) - ) - ;; Unlike nested-try2, the exception may not be caught by the inner catch, - ;; so the local.set may not run. So this should NOT be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $nested-catch1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e2 - ;; CHECK-NEXT: (try $try0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e2 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-catch1 - (local $x i32) - (try - (do - (throw $e (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - ) - (catch $e2 - (try - (do - (throw $e (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - ) - (catch $e2 - (local.set $x (i32.const 1)) - ) - ) - ) - ) - ;; This should NOT be dropped because the exception might not be caught by - ;; the inner catches, and the local.set above us may not have run, and - ;; other possible code paths do not even set the local. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $nested-catch2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (try $try1 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-catch2 - (local $x i32) - (try - (do - (throw $e (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - (local.set $x (i32.const 1)) - ) - (catch_all - (try - (do - (throw $e (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - (local.set $x (i32.const 1)) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ) - ) - ;; This should be dropped because the exception is guaranteed to be caught - ;; by one of the catches and it will set the local to 1. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $catchless-try - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $catchless-try - (local $x i32) - (try - (do - (call $foo) - (local.set $x (i32.const 1)) - ) - ) - ;; The only way we end up here is when (call $foo) does not throw, because - ;; if (call $foo) throws, it will throw to the caller because it is within - ;; a catchless try. In that case the local.set after (call $foo) would have - ;; run before this, so this can be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try-delegate0 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try2 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate0 - (local $x i32) - (try $l0 - (do - (try - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate $l0) - ) - ) - (catch_all) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ;; The innermost try has a delegate, which delegates to the outermost try's - ;; catch_all, which has the same local.set. So this can be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try-delegate1 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try3 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate1 - (local $x i32) - (try $l0 - (do - (try - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate $l0) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ) - (catch_all) - ) - ;; The middle try's catch_all has the same local.set, but it is skipped - ;; because the innermost try-delegate delegates to the outer try while - ;; skipping the middle try-catch_all. So this should NOT be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try-delegate2 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try4 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate2 - (local $x i32) - (try $l0 - (do - (try - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate 2) ;; delegate to caller - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ;; The innermost try-delegate delegates to the caller, bypassing all - ;; local.sets in the middle and the outermost try-catch_alls. So this should - ;; NOT be dropped. (Instead this is unreachable, but that's DCE's work) - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try-delegate3 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $l1 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try5 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try6 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate3 - (local $x i32) - (try $l0 - (do - (try - (do - (try $l1 - (do - (try - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate $l1) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ) - (delegate $l0) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ) - (catch_all) - ) - ;; The innermost try delegates to $l1, which in turn delegates to $l0, - ;; skipping all local.sets in between. So this should NOT be dropped. - (local.set $x (i32.const 1)) - ) - - ;; CHECK: (func $try-delegate4 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (try $l0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $l1 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try7 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try8 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $l0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate4 - (local $x i32) - (try $l0 - (do - (try - (do - (try $l1 - (do - (try - (do - (try - (do - (throw $e (i32.const 0)) - ) - (delegate $l1) - ) - ) - (catch_all) - ) - ) - (delegate $l0) - ) - ) - (catch_all) - ) - ) - (catch_all - (local.set $x (i32.const 1)) - ) - ) - ;; The innermost try delegates to $l1, which in turn delgates to $l0, whose - ;; catch_all runs the same local.set. So this can be dropped. - (local.set $x (i32.const 1)) - ) -) diff -Nru binaryen-108/test/lit/passes/rse-gc.wast binaryen-99/test/lit/passes/rse-gc.wast --- binaryen-108/test/lit/passes/rse-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/rse-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --rse --enable-gc-nn-locals -all -S -o - | filecheck %s - -(module - ;; CHECK: (func $test - ;; CHECK-NEXT: (local $single (ref func)) - ;; CHECK-NEXT: (local $tuple ((ref any) (ref any))) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $test - ;; A non-nullable local. The pass should ignore it (as we cannot optimize - ;; anything here anyhow: the code must assign to the local before reading from - ;; it, so no sets can be redundant in that sense). - (local $single (ref func)) - ;; A non-nullable tuple. - (local $tuple ((ref any) (ref any))) - ) -) diff -Nru binaryen-108/test/lit/passes/signature-pruning.wast binaryen-99/test/lit/passes/signature-pruning.wast --- binaryen-108/test/lit/passes/signature-pruning.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/signature-pruning.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,812 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --signature-pruning -all -S -o - | filecheck %s - -(module - ;; CHECK: (type $sig (func_subtype (param i32 f64) func)) - (type $sig (func_subtype (param i32) (param i64) (param f32) (param f64) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $sig) (param $0 i32) (param $1 f64) - ;; CHECK-NEXT: (local $2 f32) - ;; CHECK-NEXT: (local $3 i64) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) - ;; Use the first and last parameter. The middle parameters will be removed - ;; both from the function and from $sig, and also in the calls below. - (i32.store - (i32.const 0) - (local.get $i32) - ) - (f64.store - (i32.const 0) - (local.get $f64) - ) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (f64.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (f64.const 7) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $foo - (i32.const 0) - (i64.const 1) - (f32.const 2) - (f64.const 3) - ) - (call_ref - (i32.const 4) - (i64.const 5) - (f32.const 6) - (f64.const 7) - (ref.func $foo) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype (param i64 f32) func)) - (type $sig (func_subtype (param i32) (param i64) (param f32) (param f64) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $sig) (param $0 i64) (param $1 f32) - ;; CHECK-NEXT: (local $2 f64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) - ;; Use the middle two parameters. - (i64.store - (i32.const 0) - (local.get $i64) - ) - (f32.store - (i32.const 0) - (local.get $f32) - ) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: (f32.const 6) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $foo - (i32.const 0) - (i64.const 1) - (f32.const 2) - (f64.const 3) - ) - (call_ref - (i32.const 4) - (i64.const 5) - (f32.const 6) - (f64.const 7) - (ref.func $foo) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype (param i32 i64 f32) func)) - (type $sig (func_subtype (param i32) (param i64) (param f32) (param f64) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $sig) (param $0 i32) (param $1 i64) (param $2 f32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) - ;; Use the middle two parameters. - (i64.store - (i32.const 0) - (local.get $i64) - ) - (f32.store - (i32.const 0) - (local.get $f32) - ) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $caller) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: (f32.const 6) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - ;; As above, but now one of the unused parameters has a side effect which - ;; prevents us from removing it (flattening the IR first would avoid this - ;; limitation). We only end up removing a single unused param, the last. - (call $foo - (block (result i32) - (call $caller) - (i32.const 0) - ) - (i64.const 1) - (f32.const 2) - (f64.const 3) - ) - (call_ref - (i32.const 4) - (i64.const 5) - (f32.const 6) - (f64.const 7) - (ref.func $foo) - ) - ) -) - -;; As above, but with the effects on a call_ref. Once more, we can only optimize -;; away the very last param. -(module - ;; CHECK: (type $sig (func_subtype (param i32 i64 f32) func)) - (type $sig (func_subtype (param i32) (param i64) (param f32) (param f64) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $sig) (param $0 i32) (param $1 i64) (param $2 f32) - ;; CHECK-NEXT: (local $3 f64) - ;; CHECK-NEXT: (i64.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) - (i64.store - (i32.const 0) - (local.get $i64) - ) - (f32.store - (i32.const 0) - (local.get $f32) - ) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i64.const 1) - ;; CHECK-NEXT: (f32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (call $caller) - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i64.const 5) - ;; CHECK-NEXT: (f32.const 6) - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $foo - (i32.const 0) - (i64.const 1) - (f32.const 2) - (f64.const 3) - ) - (call_ref - (block (result i32) - (call $caller) - (i32.const 4) - ) - (i64.const 5) - (f32.const 6) - (f64.const 7) - (ref.func $foo) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype func)) - (type $sig (func_subtype (param i32) (param i64) (param f32) (param f64) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $sig) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (local $1 f32) - ;; CHECK-NEXT: (local $2 i64) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) (param $i64 i64) (param $f32 f32) (param $f64 f64) - ;; Use nothing at all: all params can be removed. - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $foo - (i32.const 0) - (i64.const 1) - (f32.const 2) - (f64.const 3) - ) - (call_ref - (i32.const 4) - (i64.const 5) - (f32.const 6) - (f64.const 7) - (ref.func $foo) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype func)) - (type $sig (func_subtype (param i32) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $foo (type $sig) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ;; Use the parameters' index, but not its value. We can still remove it, - ;; and the value set in the function is then set to a local and not a param, - ;; which works just as well. - (local.set $i32 - (i32.const 1) - ) - (i32.store - (i32.const 0) - (local.get $i32) - ) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - (func $caller - (local $x i32) - (call $foo - ;; (avoid passing in a constant value to avoid other opts kicking in) - (local.get $x) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype func)) - (type $sig (func_subtype (param i32) func)) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $foo (type $sig) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ;; This function does not use the parameter. It also has no calls, but that - ;; is not a problem - we can still remove the parameter. - ) -) - -(module - ;; CHECK: (type $sig (func_subtype (param i32) func)) - (type $sig (func_subtype (param i32) func)) - - ;; As above, but now an import also uses this signature, which prevents us - ;; from changing anything. - ;; CHECK: (import "out" "func" (func $import (param i32))) - (import "out" "func" (func $import (type $sig) (param i32))) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $foo (type $sig) (param $i32 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype (param i32) func)) - (type $sig (func_subtype (param i32) func)) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $foo (type $sig) (param $i32 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ) - - ;; CHECK: (func $bar (type $sig) (param $i32 i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (type $sig) (param $i32 i32) - ;; As above, but now there is a second (non-imported) function using this - ;; signature, and it does use the param, so we cannot optimize. - (i32.store - (i32.const 0) - (local.get $i32) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype func)) - (type $sig (func_subtype (param i32) func)) - - ;; CHECK: (type $sig2 (func_subtype (param i32) func)) - (type $sig2 (func_subtype (param i32) func)) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $foo (type $sig) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ) - - ;; CHECK: (func $bar (type $sig2) (param $i32 i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (type $sig2) (param $i32 i32) - ;; As above, but now the second function has a different signature, so we - ;; can optimize one while not modifying the other. - (i32.store - (i32.const 0) - (local.get $i32) - ) - ) -) - -(module - ;; CHECK: (type $sig (func_subtype func)) - (type $sig (func_subtype (param i32) func)) - - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $bar $foo) - - ;; CHECK: (func $foo (type $sig) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ) - - ;; CHECK: (func $bar (type $sig) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $bar (type $sig) (param $i32 i32) - ;; As above, but the second function also does not use the parameter, and - ;; has the same type. We can optimize both at once. - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.func $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $foo - (i32.const 0) - ) - (call $bar - (i32.const 1) - ) - (call_ref - (i32.const 2) - (ref.func $foo) - ) - (call_ref - (i32.const 2) - (ref.func $bar) - ) - ) - - ;; CHECK: (func $caller-2 (type $none_=>_none) - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller-2 - ;; Also add some more calls to see they are updated too. - (call $bar - (i32.const 1) - ) - (call_ref - (i32.const 2) - (ref.func $foo) - ) - ) -) - -(module - ;; The presence of a table prevents us from doing any optimizations. - (table 1 1 anyref) - - ;; CHECK: (type $sig (func_subtype (param i32) func)) - (type $sig (func_subtype (param i32) func)) - - ;; CHECK: (table $0 1 1 anyref) - - ;; CHECK: (func $foo (type $sig) (param $i32 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (type $sig) (param $i32 i32) - ) -) - -;; Exports cannot be optimized in any way: we cannot remove parameters from -;; them, and also we cannot apply constant parameter values either. -(module - ;; CHECK: (type $sig (func_subtype (param i32) func)) - (type $sig (func_subtype (param i32) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (export "foo" (func $foo)) - - ;; CHECK: (export "bar" (func $bar)) - - ;; CHECK: (func $foo (type $sig) (param $i32 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (export "foo") (type $sig) (param $i32 i32) - ) - - ;; CHECK: (func $bar (type $sig) (param $i32 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $bar (export "bar") (type $sig) (param $i32 i32) - ) - - ;; CHECK: (func $call-bar (type $none_=>_none) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-bar - (call $bar - (i32.const 42) - ) - ) -) - -;; Two functions with two different types have an unused parameter. After -;; removing the parameter from each, they both have no parameters. They should -;; *not* have the same type, however: the type should be different nominally -;; even though after the pruning they are identical structurally. -(module - ;; CHECK: (type $sig1 (func_subtype func)) - (type $sig1 (func_subtype (param i32) func)) - ;; CHECK: (type $sig2 (func_subtype func)) - (type $sig2 (func_subtype (param f64) func)) - - ;; CHECK: (func $foo1 (type $sig1) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo1 (type $sig1) (param $i32 i32) - ) - - ;; CHECK: (func $foo2 (type $sig2) - ;; CHECK-NEXT: (local $0 f64) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo2 (type $sig2) (param $f64 f64) - ) -) - -(module - ;; CHECK: (type $sig-foo (func_subtype func)) - (type $sig-foo (func_subtype (param i32) func)) - ;; CHECK: (type $sig-bar (func_subtype (param i32) func)) - (type $sig-bar (func_subtype (param i32) func)) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $foo (type $sig-foo) - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig-foo) (param $i32 i32) - ;; This function is always called with the same constant, and we can - ;; apply that constant here and prune the param. - (i32.store - (i32.const 0) - (local.get $i32) - ) - (call $foo (i32.const 42)) - (call $foo (i32.const 42)) - (call $foo (i32.const 42)) - ) - - ;; CHECK: (func $bar (type $sig-bar) (param $i32 i32) - ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (type $sig-bar) (param $i32 i32) - ;; This function is called with various values, and cannot be optimized like - ;; the previous one. - (i32.store - (i32.const 0) - (local.get $i32) - ) - (call $bar (i32.const 42)) - (call $bar (i32.const 43)) - ) -) - -;; As above, but $foo's parameter is a ref.func, which is also a constant -;; value that we can optimize in the case of $foo (but not $bar, again, as $bar -;; is not always sent a constant value). -(module - ;; CHECK: (type $sig-foo (func_subtype func)) - (type $sig-foo (func_subtype (param funcref) func)) - ;; CHECK: (type $sig-bar (func_subtype (param funcref) func)) - (type $sig-bar (func_subtype (param funcref) func)) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $bar $foo) - - ;; CHECK: (func $foo (type $sig-foo) - ;; CHECK-NEXT: (local $0 funcref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig-foo) (param $funcref funcref) - (drop (local.get $funcref)) - (call $foo (ref.func $foo)) - (call $foo (ref.func $foo)) - (call $foo (ref.func $foo)) - ) - - ;; CHECK: (func $bar (type $sig-bar) (param $funcref funcref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $funcref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (ref.func $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (type $sig-bar) (param $funcref funcref) - (drop (local.get $funcref)) - (call $bar (ref.func $foo)) - (call $bar (ref.func $bar)) - ) -) - -;; As above, but the values are now ref.nulls. All nulls compare equal, so we -;; can still optimize even though the types differ. -(module - ;; CHECK: (type $sig-foo (func_subtype func)) - (type $sig-foo (func_subtype (param anyref) func)) - ;; CHECK: (type $sig-bar (func_subtype (param anyref) func)) - (type $sig-bar (func_subtype (param anyref) func)) - - (memory 1 1) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (elem declare func $foo) - - ;; CHECK: (func $foo (type $sig-foo) - ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo (type $sig-foo) (param $anyref anyref) - (drop (local.get $anyref)) - (call $foo (ref.null any)) - (call $foo (ref.null func)) - ) - - ;; CHECK: (func $bar (type $sig-bar) (param $anyref anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $anyref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $bar - ;; CHECK-NEXT: (ref.null func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (type $sig-bar) (param $anyref anyref) - (drop (local.get $anyref)) - ;; Mixing a null with something else prevents optimization, of course. - (call $bar (ref.func $foo)) - (call $bar (ref.null func)) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $A (struct_subtype data)) - (type $A (struct_subtype data)) - ;; CHECK: (func $0 (type $none_=>_none) - ;; CHECK-NEXT: (local $0 f32) - ;; CHECK-NEXT: (ref.cast_static $A - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $0 (param $0 f32) - ;; $A is only used in an unreachable cast. We should not error when - ;; removing the param from this function, during which we collect heap - ;; types, and must find this one even though the cast is unreachable, as - ;; we do need to handle it in the optimization as well as print it (note how - ;; type $A is declared in the output here - it would be a bug if it were - ;; not, which this is a regression test for). - (ref.cast_static $A - (unreachable) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/signature-refining.wast binaryen-99/test/lit/passes/signature-refining.wast --- binaryen-108/test/lit/passes/signature-refining.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/signature-refining.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,676 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --signature-refining -all -S -o - | filecheck %s - -(module - ;; $func is defined with an anyref parameter but always called with a $struct, - ;; and we can specialize the heap type to that. That will both update the - ;; heap type's definition as well as the types of the parameters as printed - ;; on the function (which are derived from the heap type). - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param (ref $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func - (struct.new $struct) - ) - ) -) - -(module - ;; As above, but the call is via call_ref. - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param (ref $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func) - - ;; CHECK: (func $func (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: (ref.func $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call_ref - (struct.new $struct) - (ref.func $func) - ) - ) -) - -(module - ;; A combination of call types, and the LUB is affected by all of them: one - ;; call uses a nullable $struct, the other a non-nullable dataref, so the LUB - ;; is a nullable dataref. - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param (ref null data)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func) - - ;; CHECK: (func $func (type $sig) (param $x (ref null data)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (local $struct (ref null $struct)) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.as_data - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.func $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (local $struct (ref null $struct)) - (call $func - ;; Use a local to avoid a ref.null being updated. - (local.get $struct) - ) - (call_ref - (ref.as_data - (struct.new $struct) - ) - (ref.func $func) - ) - ) -) - -(module - ;; Multiple functions with the same heap type. Again, the LUB is in the - ;; middle, this time the parent $struct and not a subtype. - - ;; CHECK: (type $sig (func_subtype (param (ref $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype data)) - - ;; CHECK: (type $struct-sub1 (struct_subtype $struct)) - (type $struct-sub1 (struct_subtype $struct)) - - ;; CHECK: (type $struct-sub2 (struct_subtype $struct)) - (type $struct-sub2 (struct_subtype $struct)) - - (type $struct (struct_subtype data)) - - ;; CHECK: (func $func-1 (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-1 (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $func-2 (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-2 (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func-1 - ;; CHECK-NEXT: (struct.new_default $struct-sub1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $func-2 - ;; CHECK-NEXT: (struct.new_default $struct-sub2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func-1 - (struct.new $struct-sub1) - ) - (call $func-2 - (struct.new $struct-sub2) - ) - ) -) - -(module - ;; As above, but now only one of the functions is called. The other is still - ;; updated, though, as they share a heap type. - - ;; CHECK: (type $sig (func_subtype (param (ref $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func-1 (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-1 (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $func-2 (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-2 (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func-1 - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func-1 - (struct.new $struct) - ) - ) -) - -(module - ;; Define a field in the struct of the signature type that will be updated, - ;; to check for proper validation after the update. - - ;; CHECK: (type $sig (func_subtype (param (ref $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $struct (struct_subtype (field (ref $sig)) data)) - (type $struct (struct_subtype (field (ref $sig)) data)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func) - - ;; CHECK: (func $func (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (local $temp (ref null $sig)) - ;; CHECK-NEXT: (local $2 anyref) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ;; Define a local of the signature type that is updated. - (local $temp (ref null $sig)) - ;; Do a local.get of the param, to verify its type is valid. - (drop - (local.get $x) - ) - ;; Copy between the param and the local, to verify their types are still - ;; compatible after the update. Note that we will need to add a fixup local - ;; here, as $x's new type becomes too specific to be assigned the value - ;; here. - (local.set $x - (local.get $temp) - ) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (ref.func $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func - (struct.new $struct - (ref.func $func) - ) - ) - ) -) - -(module - ;; An unreachable value does not prevent optimization: we will update the - ;; param to be $struct. - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param (ref $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func) - - ;; CHECK: (func $func (type $sig) (param $x (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (ref.func $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func - (struct.new $struct) - ) - (call_ref - (unreachable) - (ref.func $func) - ) - ) -) - -(module - ;; When we have only unreachable values, there is nothing to optimize, and we - ;; should not crash. - - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param anyref) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func) - - ;; CHECK: (func $func (type $sig) (param $x anyref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (ref.func $func) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call_ref - (unreachable) - (ref.func $func) - ) - ) -) - -(module - ;; When we have no calls, there is nothing to optimize, and we should not - ;; crash. - - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param anyref) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (func $func (type $sig) (param $x anyref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) -) - -(module - ;; Test multiple fields in multiple types. - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig-1 (func_subtype (param (ref null data) anyref) func)) - (type $sig-1 (func_subtype (param anyref) (param anyref) func)) - ;; CHECK: (type $sig-2 (func_subtype (param anyref (ref $struct)) func)) - (type $sig-2 (func_subtype (param anyref) (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func-2) - - ;; CHECK: (func $func-1 (type $sig-1) (param $x (ref null data)) (param $y anyref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-1 (type $sig-1) (param $x anyref) (param $y anyref) - ) - - ;; CHECK: (func $func-2 (type $sig-2) (param $x anyref) (param $y (ref $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func-2 (type $sig-2) (param $x anyref) (param $y anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (local $any anyref) - ;; CHECK-NEXT: (local $data (ref null data)) - ;; CHECK-NEXT: (local $func funcref) - ;; CHECK-NEXT: (call $func-1 - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $func-1 - ;; CHECK-NEXT: (local.get $data) - ;; CHECK-NEXT: (local.get $any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $func-2 - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (local.get $func) - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: (ref.func $func-2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (local $any (ref null any)) - (local $data (ref null data)) - (local $func (ref null func)) - - (call $func-1 - (struct.new $struct) - (local.get $data) - ) - (call $func-1 - (local.get $data) - (local.get $any) - ) - (call $func-2 - (struct.new $struct) - (struct.new $struct) - ) - (call_ref - (local.get $func) - (struct.new $struct) - (ref.func $func-2) - ) - ) -) - -(module - ;; The presence of a table prevents us from doing any optimizations. - - ;; CHECK: (type $sig (func_subtype (param anyref) func)) - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - (table 1 1 anyref) - - ;; CHECK: (table $0 1 1 anyref) - - ;; CHECK: (func $func (type $sig) (param $x anyref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func - (struct.new $struct) - ) - ) -) - -(module - ;; Pass a null in one call to the function. The null can be updated which - ;; allows us to refine (but the new type must be nullable). - - ;; CHECK: (type $struct (struct_subtype data)) - - ;; CHECK: (type $sig (func_subtype (param (ref null $struct)) func)) - (type $sig (func_subtype (param anyref) func)) - - (type $struct (struct_subtype data)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (func $func (type $sig) (param $x (ref null $struct)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func - (struct.new $struct) - ) - (call $func - (ref.null data) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; This signature has a single function using it, which returns a more - ;; refined type, and we can refine to that. - ;; CHECK: (type $sig-can-refine (func_subtype (result (ref $struct)) func)) - (type $sig-can-refine (func_subtype (result anyref) func)) - - ;; Also a single function, but no refinement is possible. - ;; CHECK: (type $sig-cannot-refine (func_subtype (result anyref) func)) - (type $sig-cannot-refine (func_subtype (result anyref) func)) - - ;; The single function never returns, so no refinement is possible. - ;; CHECK: (type $sig-unreachable (func_subtype (result anyref) func)) - (type $sig-unreachable (func_subtype (result anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (elem declare func $func-can-refine) - - ;; CHECK: (func $func-can-refine (type $sig-can-refine) (result (ref $struct)) - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - (func $func-can-refine (type $sig-can-refine) (result anyref) - (struct.new $struct) - ) - - ;; CHECK: (func $func-cannot-refine (type $sig-cannot-refine) (result anyref) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - (func $func-cannot-refine (type $sig-cannot-refine) (result anyref) - (ref.null any) - ) - - ;; CHECK: (func $func-unreachable (type $sig-unreachable) (result anyref) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $func-unreachable (type $sig-unreachable) (result anyref) - (unreachable) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result (ref $struct)) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call $func-can-refine) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result (ref $struct)) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (call_ref - ;; CHECK-NEXT: (ref.func $func-can-refine) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - ;; Add a call to see that we update call types properly. - ;; Put the call in an if so the refinalize will update the if type and get - ;; printed out conveniently. - (drop - (if (result anyref) - (i32.const 1) - (call $func-can-refine) - (unreachable) - ) - ) - ;; The same with a call_ref. - (drop - (if (result anyref) - (i32.const 1) - (call_ref - (ref.func $func-can-refine) - ) - (unreachable) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - ;; This signature has multiple functions using it, and some of them have nulls - ;; which should be updated when we refine. - ;; CHECK: (type $sig (func_subtype (result (ref null $struct)) func)) - (type $sig (func_subtype (result anyref) func)) - - ;; CHECK: (func $func-1 (type $sig) (result (ref null $struct)) - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - (func $func-1 (type $sig) (result anyref) - (struct.new $struct) - ) - - ;; CHECK: (func $func-2 (type $sig) (result (ref null $struct)) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - (func $func-2 (type $sig) (result anyref) - (ref.null any) - ) - - ;; CHECK: (func $func-3 (type $sig) (result (ref null $struct)) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - (func $func-3 (type $sig) (result anyref) - (ref.null eq) - ) - - ;; CHECK: (func $func-4 (type $sig) (result (ref null $struct)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $func-4 (type $sig) (result anyref) - (if - (i32.const 1) - (return - (ref.null any) - ) - ) - (unreachable) - ) -) - -;; Exports prevent optimization, so $func's type will not change here. -(module - ;; CHECK: (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $struct (struct_subtype data)) - (type $struct (struct_subtype data)) - - (type $sig (func_subtype (param anyref) func)) - - ;; CHECK: (export "prevent-opts" (func $func)) - - ;; CHECK: (func $func (type $sig) (param $x anyref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $func (export "prevent-opts") (type $sig) (param $x anyref) - ) - - ;; CHECK: (func $caller (type $none_=>_none) - ;; CHECK-NEXT: (call $func - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $caller - (call $func - (struct.new $struct) - ) - ) -) - -(module - ;; CHECK: (type $A (func_subtype (param i32) func)) - (type $A (func_subtype (param i32) func)) - ;; CHECK: (type $B (func_subtype (param i32) $A)) - (type $B (func_subtype (param i32) $A)) - - ;; CHECK: (func $bar (type $B) (param $x i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $bar (type $B) (param $x i32) - ;; The parameter to this function can be pruned. But while doing so we must - ;; properly preserve the subtyping of $B from $A, which means we cannot just - ;; remove it - we'd need to remove it from $A as well, which we don't - ;; attempt to do in the pass atm. So we do not optimize here. - (nop) - ) -) diff -Nru binaryen-108/test/lit/passes/simplify-globals-non-init.wast binaryen-99/test/lit/passes/simplify-globals-non-init.wast --- binaryen-108/test/lit/passes/simplify-globals-non-init.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/simplify-globals-non-init.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,143 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --simplify-globals --enable-mutable-globals -S -o - | filecheck %s - -;; A global that is written its initial value in all subsequent writes can -;; remove those writes. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global-0 i32 (i32.const 0)) - (global $global-0 (mut i32) (i32.const 0)) - ;; CHECK: (global $global-1 i32 (i32.const 1)) - (global $global-1 (mut i32) (i32.const 1)) - - ;; CHECK: (func $sets - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sets - ;; All these writes can be turned into drops. - - (global.set $global-0 (i32.const 0)) - (global.set $global-0 (i32.const 0)) - - (global.set $global-1 (i32.const 1)) - (global.set $global-1 (i32.const 1)) - ) - - ;; CHECK: (func $gets - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $gets - ;; Add gets to avoid other opts from removing the sets. - (drop (global.get $global-0)) - (drop (global.get $global-1)) - ) -) - -;; As above, but now we write other values. -(module - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global-0 (mut i32) (i32.const 0)) - (global $global-0 (mut i32) (i32.const 0)) - ;; CHECK: (global $global-1 (mut i32) (i32.const 1)) - (global $global-1 (mut i32) (i32.const 1)) - - ;; CHECK: (func $sets (param $unknown i32) - ;; CHECK-NEXT: (global.set $global-0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global-0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global-1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global-1 - ;; CHECK-NEXT: (local.get $unknown) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sets (param $unknown i32) - (global.set $global-0 (i32.const 0)) - (global.set $global-0 (i32.const 1)) ;; a non-init value - - (global.set $global-1 (i32.const 1)) - (global.set $global-1 (local.get $unknown)) ;; a totally unknown value - ) - - ;; CHECK: (func $gets - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $global-0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $global-1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $gets - (drop (global.get $global-0)) - (drop (global.get $global-1)) - ) -) - -;; Globals without constant initial values. -(module - ;; An imported global. - ;; CHECK: (type $i32_=>_none (func (param i32))) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (import "env" "import_global" (global $global-0 (mut i32))) - (import "env" "import_global" (global $global-0 (mut i32))) - - ;; A global that initializes with another global. - ;; CHECK: (global $global-1 (mut i32) (global.get $global-0)) - (global $global-1 (mut i32) (global.get $global-0)) - - ;; CHECK: (func $sets (param $unknown i32) - ;; CHECK-NEXT: (global.set $global-0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global-1 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $sets (param $unknown i32) - (global.set $global-0 (i32.const 0)) - - (global.set $global-1 (i32.const 1)) - ) - - ;; CHECK: (func $gets - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $global-0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $global-1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $gets - ;; Add gets to avoid other opts from removing the sets. - (drop (global.get $global-0)) - (drop (global.get $global-1)) - ) -) diff -Nru binaryen-108/test/lit/passes/simplify-globals-read_only_to_write.wast binaryen-99/test/lit/passes/simplify-globals-read_only_to_write.wast --- binaryen-108/test/lit/passes/simplify-globals-read_only_to_write.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/simplify-globals-read_only_to_write.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,807 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --simplify-globals -S -o - | filecheck %s - -;; A global that is only read in order to be written is not needed. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global i32 (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (func $simple - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $simple - (if - (global.get $global) - (global.set $global (i32.const 1)) - ) - ) - ;; CHECK: (func $more-with-no-side-effects - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $more-with-no-side-effects - (if - ;; Also test for other operations in the condition, with no effects. - (i32.eqz - (global.get $global) - ) - ;; Also test for other operations in the body, with no effects. - (block - (nop) - (global.set $global (i32.const 1)) - ) - ) - ) - ;; CHECK: (func $additional-set - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $additional-set - ;; An additional set does not prevent this optimization: the value written - ;; will never be read in a way that matters. - (global.set $global (i32.const 2)) - ) -) -;; An additional read prevents the read-only-to-write optimization. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global (mut i32) (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (func $additional-read - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $additional-read - (if - (global.get $global) - (global.set $global (i32.const 1)) - ) - (drop - (global.get $global) - ) - ) -) -;; We do not optimize if-elses in the read-only-to-write optimization. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global (mut i32) (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (func $if-else - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $if-else - (if - (global.get $global) - (global.set $global (i32.const 1)) - (nop) - ) - ) -) -;; Side effects in the body prevent the read-only-to-write optimization. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global (mut i32) (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (global $other (mut i32) (i32.const 0)) - (global $other (mut i32) (i32.const 0)) - ;; CHECK: (func $side-effects-in-body - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $other - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-body - (if - (global.get $global) - (block - (global.set $global (i32.const 1)) - (global.set $other (i32.const 2)) - (drop (global.get $other)) - ) - ) - ) -) -;; Nested patterns work as well, in a single run of the pass. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $a i32 (i32.const 0)) - (global $a (mut i32) (i32.const 0)) - ;; CHECK: (global $b i32 (i32.const 0)) - (global $b (mut i32) (i32.const 0)) - ;; CHECK: (global $c i32 (i32.const 0)) - (global $c (mut i32) (i32.const 0)) - - ;; CHECK: (func $nested - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested - (if - (global.get $a) - (block - (global.set $a (i32.const 1)) - (if - (global.get $b) - (block - (if - (global.get $c) - (block - (global.set $c (i32.const 2)) - ) - ) - (global.set $b (i32.const 3)) - ) - ) - ) - ) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once i32 (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $clinit - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $clinit - ;; A read-only-to-write that takes an entire function body, and is in the - ;; form if "if already set, return; set it". In particular, the set is not - ;; in the if body in this case. - (if - (global.get $once) - (return) - ) - (global.set $once - (i32.const 1) - ) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $clinit - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $clinit - ;; As above, but the optimization fails because the function body has too - ;; many elements - a nop is added at the end. - (if - (global.get $once) - (return) - ) - (global.set $once - (i32.const 1) - ) - (nop) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $clinit - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $clinit - ;; As above, but the optimization fails because the if has an else. - (if - (global.get $once) - (return) - (nop) - ) - (global.set $once - (i32.const 1) - ) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $clinit - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $clinit - ;; As above, but the optimization fails because the if body is not a - ;; return. - (if - (global.get $once) - (nop) - ) - (global.set $once - (i32.const 1) - ) - ) -) - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (func $clinit - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $clinit - ;; As above, but the optimization fails because the if condition has effects. - (if - (call $foo ;; This call may have side effects and it receives the global's - ;; value, which is dangerous. - (global.get $once) - ) - (return) - ) - (global.set $once - (i32.const 1) - ) - ) - - ;; CHECK: (func $foo (param $x i32) (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (param $x i32) (result i32) - (unreachable) - ) -) - -;; Using the global's value in a way that can cause side effects prevents the -;; read-only-to-write optimization. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (global $global (mut i32) (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (global $other i32 (i32.const 0)) - (global $other (mut i32) (i32.const 0)) - ;; CHECK: (func $side-effects-in-condition - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-condition - (if - (if (result i32) - (global.get $global) ;; the global's value may cause foo() to be called - (call $foo) - (i32.const 1) - ) - (global.set $global (i32.const 1)) - ) - ) - - ;; CHECK: (func $foo (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (result i32) - (unreachable) - ) -) - -;; As above, but now the global's value is not the condition of the if, so there -;; is no problem. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (type $none_=>_i32 (func (result i32))) - - ;; CHECK: (global $global i32 (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (global $other i32 (i32.const 0)) - (global $other (mut i32) (i32.const 0)) - ;; CHECK: (func $side-effects-in-condition-2 - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-condition-2 - (if - (if (result i32) - (call $foo) ;; these side effects are not a problem, as the global's - ;; value cannot reach them. - (i32.const 1) - (global.get $global) ;; the global's value flows out through the if, - ;; safely - ) - (global.set $global (i32.const 1)) - ) - ) - - ;; CHECK: (func $foo (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (result i32) - (unreachable) - ) -) - -;; As above, but now the global's value flows into a side effect. -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $global (mut i32) (i32.const 0)) - (global $global (mut i32) (i32.const 0)) - ;; CHECK: (global $other i32 (i32.const 0)) - (global $other (mut i32) (i32.const 0)) - ;; CHECK: (func $side-effects-in-condition-3 - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (global.get $global) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $global - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-condition-3 - (local $temp i32) - (if - (local.tee $temp - (global.get $global) ;; the global's value flows into a place that has - ) ;; side effects, so it may be noticed. - (global.set $global (i32.const 1)) - ) - ) -) - -;; As above, but now the global's value flows through multiple layers of -;; things that have no side effects and are safe. -(module - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once i32 (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $side-effects-in-condition-4 - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1337) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $side-effects-in-condition-4 - (local $x i32) - (local $y i32) - (if - (i32.eqz - (select - (local.tee $x - (i32.const 1) - ) - (i32.load - (i32.const 2) - ) - (i32.add - (global.get $once) - (i32.const 1337) - ) - ) - ) - (global.set $once - (i32.const 1) - ) - ) - ) -) - -(module - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once i32 (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $nested-pattern - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-pattern - (local $x i32) - (local $y i32) - (if - (block (result i32) - ;; Another appearance of the pattern nested inside this one. This should - ;; not prevent us from optimizing. - (if - (i32.eqz - (global.get $once) - ) - (global.set $once - (i32.const 1) - ) - ) - (i32.eq - (global.get $once) - (i32.const 0) - ) - ) - (global.set $once - (i32.const 1) - ) - ) - ) -) - -(module - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $almost-nested-pattern - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $almost-nested-pattern - (local $x i32) - (local $y i32) - (if - (block (result i32) - ;; This is almost the nested pattern, but not quite, as it has an - ;; "else" arm. - (if - (i32.eqz - (global.get $once) - ) - (global.set $once - (i32.const 1) - ) - (nop) ;; This breaks the pattern we are looking for. - ) - (i32.eq - (global.get $once) - (i32.const 0) - ) - ) - (global.set $once - (i32.const 1) - ) - ) - ) -) - -(module - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once i32 (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $nested-pattern-thrice - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (block $block1 (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-pattern-thrice - (local $x i32) - (local $y i32) - (if - (block (result i32) - (if - (i32.eqz - (block (result i32) - ;; A third nested appearance. - (if - (global.get $once) - (global.set $once - (i32.const 1) - ) - ) - (global.get $once) - ) - ) - (global.set $once - (i32.const 1) - ) - ) - (i32.eq - (global.get $once) - (i32.const 0) - ) - ) - (global.set $once - (i32.const 1) - ) - ) - ) -) - -(module - (memory 1 1) - - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (global $once (mut i32) (i32.const 0)) - (global $once (mut i32) (i32.const 0)) - - ;; CHECK: (memory $0 1 1) - - ;; CHECK: (func $nested-pattern - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (block $block (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (global.get $once) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (global.set $once - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nested-pattern - (local $x i32) - (local $y i32) - (if - (block (result i32) - - ;; As above, but adding a drop of another get. This is *not* the - ;; pattern we are looking for, and it will prevent us from - ;; optimizing as we will no longer see that the number of gets - ;; matches the number of read-only-to-write patterns. In the - ;; future we could do a more complex counting operation to handle - ;; this too. - (drop - (global.get $once) - ) - - (if - (i32.eqz - (global.get $once) - ) - (global.set $once - (i32.const 1) - ) - ) - (i32.eq - (global.get $once) - (i32.const 0) - ) - ) - (global.set $once - (i32.const 1) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/simplify-locals-eh.wast binaryen-99/test/lit/passes/simplify-locals-eh.wast --- binaryen-108/test/lit/passes/simplify-locals-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/simplify-locals-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --simplify-locals -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e-i32 (param i32)) - (tag $e-i32 (param i32)) - ;; CHECK: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo (param i32 i32)) - ;; CHECK: (func $pop-cannot-be-sinked - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-cannot-be-sinked (local $0 i32) - (try - (do) - (catch $e-i32 - ;; This (local.set $0) of (pop i32) cannot be sunk to (local.get $0) - ;; below, because the pop should follow right after 'catch'. - (local.set $0 (pop i32)) - (call $foo - (i32.const 3) - (local.get $0) - ) - ) - ) - ) - - ;; CHECK: (func $pop-within-catch-can-be-sinked - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $foo - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (try $try0 (result i32) - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $pop-within-catch-can-be-sinked (local $0 i32) - (try - (do) - (catch_all - ;; This whole 'try' body can be sinked to eliminate local.set / - ;; local.get. Even though it contains a pop, it is enclosed within - ;; try-catch, so it is OK. - (local.set $0 - (try (result i32) - (do (i32.const 0)) - (catch $e-i32 (pop i32)) - ) - ) - (call $foo - (i32.const 3) - (local.get $0) - ) - ) - ) - ) - - ;; CHECK: (func $bar (result i32) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - (func $bar (result i32) (i32.const 3)) - ;; CHECK: (func $call-cannot-be-sinked-into-try - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $call-cannot-be-sinked-into-try (local $0 i32) - (drop - ;; This local.tee should NOT be sinked into 'try' below, because it may - ;; throw - (local.tee $0 (call $bar)) - ) - (try - (do - (drop (local.get $0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - ) - ) - - ;; CHECK: (func $non-call-can-be-sinked-into-try - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e-i32 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $non-call-can-be-sinked-into-try (local $0 i32) - (drop - ;; This local.tee can be sinked into 'try' below, because it cannot throw - (local.tee $0 (i32.const 3)) - ) - (try - (do - (drop (local.get $0)) - ) - (catch $e-i32 - (drop (pop i32)) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/simplify-locals-gc.wast binaryen-99/test/lit/passes/simplify-locals-gc.wast --- binaryen-108/test/lit/passes/simplify-locals-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/simplify-locals-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,217 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --simplify-locals -all -S -o - \ -;; RUN: | filecheck %s -;; RUN: wasm-opt %s --simplify-locals -all --nominal -S -o - \ -;; RUN: | filecheck %s --check-prefix=NOMNL - -(module - ;; CHECK: (type $struct (struct (field (mut i32)))) - ;; NOMNL: (type $struct (struct_subtype (field (mut i32)) data)) - (type $struct (struct (field (mut i32)))) - - ;; CHECK: (type $struct-immutable (struct (field i32))) - ;; NOMNL: (type $struct-immutable (struct_subtype (field i32) data)) - (type $struct-immutable (struct (field i32))) - - ;; Writes to heap objects cannot be reordered with reads. - ;; CHECK: (func $no-reorder-past-write (param $x (ref $struct)) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $no-reorder-past-write (type $ref|$struct|_=>_i32) (param $x (ref $struct)) (result i32) - ;; NOMNL-NEXT: (local $temp i32) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (struct.get $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $temp) - ;; NOMNL-NEXT: ) - (func $no-reorder-past-write (param $x (ref $struct)) (result i32) - (local $temp i32) - (local.set $temp - (struct.get $struct 0 - (local.get $x) - ) - ) - (struct.set $struct 0 - (local.get $x) - (i32.const 42) - ) - (local.get $temp) - ) - - ;; CHECK: (func $reorder-past-write-if-immutable (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.get $struct-immutable 0 - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $reorder-past-write-if-immutable (type $ref|$struct|_ref|$struct-immutable|_=>_i32) (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) - ;; NOMNL-NEXT: (local $temp i32) - ;; NOMNL-NEXT: (nop) - ;; NOMNL-NEXT: (struct.set $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.get $struct-immutable 0 - ;; NOMNL-NEXT: (local.get $y) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $reorder-past-write-if-immutable (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) - (local $temp i32) - (local.set $temp - (struct.get $struct-immutable 0 - (local.get $y) - ) - ) - (struct.set $struct 0 - (local.get $x) - (i32.const 42) - ) - (local.get $temp) - ) - - ;; CHECK: (func $unreachable-struct.get (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $unreachable-struct.get (type $ref|$struct|_ref|$struct-immutable|_=>_i32) (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) - ;; NOMNL-NEXT: (local $temp i32) - ;; NOMNL-NEXT: (local.tee $temp - ;; NOMNL-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (struct.set $struct 0 - ;; NOMNL-NEXT: (local.get $x) - ;; NOMNL-NEXT: (i32.const 42) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.get $temp) - ;; NOMNL-NEXT: ) - (func $unreachable-struct.get (param $x (ref $struct)) (param $y (ref $struct-immutable)) (result i32) - (local $temp i32) - ;; As above, but the get's ref is unreachable. This tests we do not hit an - ;; assertion on the get's type not having a heap type (as we depend on - ;; finding the heap type there in the reachable case). - ;; We simply do not handle this case, leaving it for DCE. - (local.set $temp - (struct.get $struct-immutable 0 - (unreachable) - ) - ) - (struct.set $struct 0 - (local.get $x) - (i32.const 42) - ) - (local.get $temp) - ) - - ;; CHECK: (func $no-block-values-if-br_on - ;; CHECK-NEXT: (local $temp anyref) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (br_on_null $block - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $no-block-values-if-br_on (type $none_=>_none) - ;; NOMNL-NEXT: (local $temp anyref) - ;; NOMNL-NEXT: (block $block - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (br_on_null $block - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (br $block) - ;; NOMNL-NEXT: (local.set $temp - ;; NOMNL-NEXT: (ref.null any) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: (drop - ;; NOMNL-NEXT: (ref.as_non_null - ;; NOMNL-NEXT: (local.get $temp) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $no-block-values-if-br_on - (local $temp (ref null any)) - (block $block - (drop - ;; This br_on should inhibit trying to create a block return value for - ;; this block. Aside from the br_on, it looks correct, i.e., we have a - ;; break with a set before it, and a set before the end of the block. Due - ;; to the br_on's presence, the pass should not do anything to this - ;; function. - ;; - ;; TODO: support br_on in this optimization eventually, but the variable - ;; possible return values and sent values make that nontrivial. - (br_on_null $block - (ref.null any) - ) - ) - (local.set $temp - (ref.null any) - ) - (br $block) - (local.set $temp - (ref.null any) - ) - ) - ;; Attempt to use the local that the pass will try to move to a block return - ;; value, to cause the optimization to try to run. - (drop - (ref.as_non_null - (local.get $temp) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/simplify-locals-global.wast binaryen-99/test/lit/passes/simplify-locals-global.wast --- binaryen-108/test/lit/passes/simplify-locals-global.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/simplify-locals-global.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --simplify-locals -S -o - | filecheck %s - -(module - ;; CHECK: (global $imm-glob i32 (i32.const 1234)) - (global $imm-glob i32 (i32.const 1234)) - - ;; CHECK: (global $mut-glob (mut i32) (i32.const 5678)) - (global $mut-glob (mut i32) (i32.const 5678)) - - ;; CHECK: (func $reorder-of-immmutable-global (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (call $helper) - ;; CHECK-NEXT: (global.get $imm-glob) - ;; CHECK-NEXT: ) - (func $reorder-of-immmutable-global (result i32) - (local $temp i32) - ;; As the global is immutable, it cannot be modified in the call, and we can - ;; reorder here. - (local.set $temp - (global.get $imm-glob) - ) - (call $helper) - (local.get $temp) - ) - - ;; CHECK: (func $no-reorder-of-mutable-global (result i32) - ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (global.get $mut-glob) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $helper) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - (func $no-reorder-of-mutable-global (result i32) - (local $temp i32) - ;; As the global is mutable, it can be modified in the call, and we cannot - ;; reorder here. - (local.set $temp - (global.get $mut-glob) - ) - (call $helper) - (local.get $temp) - ) - - ;; CHECK: (func $helper - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $helper) -) diff -Nru binaryen-108/test/lit/passes/ssa-gc-nn-locals.wast binaryen-99/test/lit/passes/ssa-gc-nn-locals.wast --- binaryen-108/test/lit/passes/ssa-gc-nn-locals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/ssa-gc-nn-locals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; -g --roundtrip are added to show that we properly handle non-nullable locals -;; through the binary format as well (-g is for the function names). -;; RUN: wasm-opt %s -all --ssa --enable-gc-nn-locals -g --roundtrip -S -o - | filecheck %s - -(module - ;; CHECK: (func $nn-locals - ;; CHECK-NEXT: (local $x (ref func)) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.func $nn-locals) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $nn-locals - ;; A non-nullable local - (local $x (ref func)) - ;; Set the local, and get it later. The SSA pass will normally handle non- - ;; nullability using ref.as_non_null, but with --gc-nn-locals nothing should - ;; be done. - (local.set $x (ref.func $nn-locals)) - (drop (local.get $x)) - (drop (local.get $x)) - ) -) diff -Nru binaryen-108/test/lit/passes/ssa.wast binaryen-99/test/lit/passes/ssa.wast --- binaryen-108/test/lit/passes/ssa.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/ssa.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s -all --ssa -S -o - | filecheck %s - -(module - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo) - - ;; CHECK: (func $bar (param $x (ref func)) - ;; CHECK-NEXT: (local $1 funcref) - ;; CHECK-NEXT: (local $2 funcref) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (ref.func $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $2 - ;; CHECK-NEXT: (ref.func $bar) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $bar (param $x (ref func)) - ;; assign a non-nullable parameter multiple times, which causes ssa to create - ;; new locals so that each is assigned only once - (local.set $x (ref.func $foo)) - (drop (local.get $x)) - (local.set $x (ref.func $bar)) - (drop (local.get $x)) - ) -) diff -Nru binaryen-108/test/lit/passes/stack-check-memory64.wast binaryen-99/test/lit/passes/stack-check-memory64.wast --- binaryen-108/test/lit/passes/stack-check-memory64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/stack-check-memory64.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --stack-check --enable-memory64 -S -o - | filecheck %s - -(module - (memory i64 (data)) - ;; CHECK: (type $none_=>_i64 (func (result i64))) - - ;; CHECK: (type $i64_i64_=>_none (func (param i64 i64))) - - ;; CHECK: (global $sp (mut i64) (i64.const 0)) - (global $sp (mut i64) (i64.const 0)) - (func "use_stack" (result i64) - (global.set $sp (i64.const 42)) - (global.get $sp) - ) -) -;; CHECK: (global $__stack_base (mut i64) (i64.const 0)) - -;; CHECK: (global $__stack_limit (mut i64) (i64.const 0)) - -;; CHECK: (memory $0 i64 0 65536) - -;; CHECK: (data (i64.const 0) "") - -;; CHECK: (export "use_stack" (func $0)) - -;; CHECK: (export "__set_stack_limits" (func $__set_stack_limits)) - -;; CHECK: (func $0 (result i64) -;; CHECK-NEXT: (local $0 i64) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.or -;; CHECK-NEXT: (i64.gt_u -;; CHECK-NEXT: (local.tee $0 -;; CHECK-NEXT: (i64.const 42) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.get $__stack_base) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i64.lt_u -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (global.get $__stack_limit) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (unreachable) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $sp -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.get $sp) -;; CHECK-NEXT: ) - -;; CHECK: (func $__set_stack_limits (param $0 i64) (param $1 i64) -;; CHECK-NEXT: (global.set $__stack_base -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__stack_limit -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -(module - ;; if the global names are taken we should not crash - (memory i64 (data)) - ;; CHECK: (type $i64_i64_=>_none (func (param i64 i64))) - - ;; CHECK: (global $sp (mut i64) (i64.const 0)) - (global $sp (mut i64) (i64.const 0))) - ;; CHECK: (global $__stack_base (mut i64) (i64.const 0)) - (global $__stack_base (mut i64) (i64.const 0)) - ;; CHECK: (global $__stack_limit (mut i64) (i64.const 0)) - (global $__stack_limit (mut i64) (i64.const 0)) - (export "use_stack" (func $0)) - (func $0 (result i64) - (unreachable) - ) -) -;; CHECK: (memory $0 i64 0 65536) - -;; CHECK: (data (i64.const 0) "") - -;; CHECK: (export "__set_stack_limits" (func $__set_stack_limits)) - -;; CHECK: (func $__set_stack_limits (param $0 i64) (param $1 i64) -;; CHECK-NEXT: (global.set $__stack_base -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (global.set $__stack_limit -;; CHECK-NEXT: (local.get $1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/passes/stack-ir-eh.wast binaryen-99/test/lit/passes/stack-ir-eh.wast --- binaryen-108/test/lit/passes/stack-ir-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/stack-ir-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --generate-stack-ir --optimize-stack-ir \ -;; RUN: -all --print-stack-ir | filecheck %s - -(module - ;; CHECK: (tag $e0 (param i32)) - (tag $e0 (param i32)) - - ;; CHECK: (func $eh - ;; CHECK-NEXT: try $l0 - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: throw $e0 - ;; CHECK-NEXT: catch $e0 - ;; CHECK-NEXT: - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: catch_all - ;; CHECK-NEXT: rethrow $l0 - ;; CHECK-NEXT: end - ;; CHECK-NEXT: try $l00 - ;; CHECK-NEXT: try $try - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: throw $e0 - ;; CHECK-NEXT: delegate $l00 - ;; CHECK-NEXT: unreachable - ;; CHECK-NEXT: catch_all - ;; CHECK-NEXT: nop - ;; CHECK-NEXT: end - ;; CHECK-NEXT: try $l01 - ;; CHECK-NEXT: nop - ;; CHECK-NEXT: delegate 0 - ;; CHECK-NEXT: ) - (func $eh - (try $l0 - (do - (throw $e0 (i32.const 0)) - ) - (catch $e0 - (drop (pop i32)) - ) - (catch_all - (rethrow $l0) - ) - ) - - (try $l0 - (do - (try - (do - (throw $e0 (i32.const 0)) - ) - (delegate $l0) - ) - ) - (catch_all) - ) - - (try $l0 - (do) - (delegate 0) ;; delegate to caller - ) - ) -) diff -Nru binaryen-108/test/lit/passes/stack-ir-roundtrip-eh.wast binaryen-99/test/lit/passes/stack-ir-roundtrip-eh.wast --- binaryen-108/test/lit/passes/stack-ir-roundtrip-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/stack-ir-roundtrip-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --generate-stack-ir --roundtrip -all -S -o - | filecheck %s - -(module - (tag $tag (param i32)) - ;; CHECK: (func $delegate-child - ;; CHECK-NEXT: (try $label$9 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $label$7 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (try $label$6 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $tag$0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $delegate-child - (try - (do - (try - (do) - (catch $tag - (drop - (pop i32) - ) - (try - (do) - ;; the binary writer must properly handle this delegate which is - ;; the child of other try's, and not get confused by their - ;; information on the stack (this is a regression test for us - ;; properly ending the scope with a delegate and popping the - ;; relevant stack). - (delegate 2) - ) - ) - ) - ) - (catch $tag - (drop - (pop i32) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/type-refining.wast binaryen-99/test/lit/passes/type-refining.wast --- binaryen-108/test/lit/passes/type-refining.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/type-refining.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,865 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; RUN: foreach %s %t wasm-opt --nominal --type-refining -all -S -o - | filecheck %s - -(module - ;; A struct with three fields. The first will have no writes, the second one - ;; write of the same type, and the last a write of a subtype, which will allow - ;; us to specialize that one. - ;; CHECK: (type $struct (struct_subtype (field (mut anyref)) (field (mut anyref)) (field (mut (ref $ref|$struct|_=>_none))) data)) - (type $struct (struct_subtype (field (mut anyref)) (field (mut anyref)) (field (mut anyref)) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (elem declare func $work) - - ;; CHECK: (func $work (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (struct.set $struct 1 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (ref.null any) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 2 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (ref.func $work) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.get $struct 2 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) - (struct.set $struct 1 - (local.get $struct) - (ref.null any) - ) - (struct.set $struct 2 - (local.get $struct) - (ref.func $work) - ) - (drop - ;; The type of this struct.get must be updated after the field's type - ;; changes, or the validator will complain. - (struct.get $struct 2 - (local.get $struct) - ) - ) - ) -) - -(module - ;; A struct with a nullable field and a write of a non-nullable value. We - ;; must keep the type nullable, unlike in the previous module, due to the - ;; default value being null. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $ref|$struct|_=>_none))) data)) - (type $struct (struct_subtype (field (mut anyref)) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (elem declare func $work) - - ;; CHECK: (func $work (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (ref.func $work) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) - (drop - (struct.new_default $struct) - ) - (struct.set $struct 0 - (local.get $struct) - (ref.func $work) - ) - ) -) - -(module - ;; Multiple writes to a field, with a LUB that is not equal to any of them. - ;; We can at least improve from dataref to a ref of $struct here. Note also - ;; that we do so in all three types, not just the parent to which we write - ;; (the children have no writes, but must still be updated). - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $struct))) data)) - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $ref|$struct|_ref|$child-A|_ref|$child-B|_=>_none (func_subtype (param (ref $struct) (ref $child-A) (ref $child-B)) func)) - - ;; CHECK: (type $child-A (struct_subtype (field (mut (ref $struct))) $struct)) - (type $child-A (struct_subtype (field (mut dataref)) $struct)) - - ;; CHECK: (type $child-B (struct_subtype (field (mut (ref $struct))) $struct)) - (type $child-B (struct_subtype (field (mut dataref)) $struct)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child-A|_ref|$child-B|_=>_none) (param $struct (ref $struct)) (param $child-A (ref $child-A)) (param $child-B (ref $child-B)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $child-A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $child-B) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child-A (ref $child-A)) (param $child-B (ref $child-B)) - (struct.set $struct 0 - (local.get $struct) - (local.get $child-A) - ) - (struct.set $struct 0 - (local.get $struct) - (local.get $child-B) - ) - ) -) - -(module - ;; As above, but all writes are of $child-A, which allows more optimization - ;; up to that type. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $child-A))) data)) - - ;; CHECK: (type $child-A (struct_subtype (field (mut (ref $child-A))) $struct)) - (type $child-A (struct_subtype (field (mut dataref)) $struct)) - - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $ref|$struct|_ref|$child-A|_=>_none (func_subtype (param (ref $struct) (ref $child-A)) func)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $child-B (struct_subtype (field (mut (ref $child-A))) $struct)) - (type $child-B (struct_subtype (field (mut dataref)) $struct)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child-A|_=>_none) (param $struct (ref $struct)) (param $child-A (ref $child-A)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $child-A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $child-A) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child-A (ref $child-A)) - (struct.set $struct 0 - (local.get $struct) - (local.get $child-A) - ) - (struct.set $struct 0 - (local.get $struct) - (local.get $child-A) - ) - ) - - ;; CHECK: (func $keepalive (type $none_=>_none) - ;; CHECK-NEXT: (local $temp (ref null $child-B)) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $keepalive - ;; Add a reference to $child-B just to keep it alive in the output for easier - ;; comparisons to the previous testcase. Note that $child-B's field will be - ;; refined, because its parent $struct forces it to be. - (local $temp (ref null $child-B)) - ) -) - -(module - ;; Write to the parent a child, and to the child a parent. The write to the - ;; child prevents specialization even in the parent and we only improve up to - ;; $struct but not to $child. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $struct))) data)) - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $child (struct_subtype (field (mut (ref $struct))) $struct)) - (type $child (struct_subtype (field (mut dataref)) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $child 0 - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child (ref $child)) - (struct.set $struct 0 - (local.get $struct) - (local.get $child) - ) - (struct.set $child 0 - (local.get $child) - (local.get $struct) - ) - ) -) - -(module - ;; As above, but both writes are of $child, so we can optimize. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $child))) data)) - - ;; CHECK: (type $child (struct_subtype (field (mut (ref $child))) $struct)) - (type $child (struct_subtype (field (mut dataref)) $struct)) - - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $child 0 - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child (ref $child)) - (struct.set $struct 0 - (local.get $struct) - (local.get $child) - ) - (struct.set $child 0 - (local.get $child) - (local.get $child) - ) - ) -) - -(module - ;; As in 2 testcases ago, write to the parent a child, and to the child a - ;; parent, but now the writes happen in struct.new. Even with that precise - ;; info, however, we can't make the parent field more specific than the - ;; child's. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $struct))) data)) - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $child (struct_subtype (field (mut (ref $struct))) $struct)) - (type $child (struct_subtype (field (mut dataref)) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $child - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child (ref $child)) - (drop - (struct.new $struct - (local.get $child) - ) - ) - (drop - (struct.new $child - (local.get $struct) - ) - ) - ) -) - -(module - ;; Write a parent to the parent and a child to the child. We can specialize - ;; each of them to contain their own type. This tests that we are aware that - ;; a struct.new is of a precise type, which means that seeing a type written - ;; to a parent does not limit specialization in a child. - ;; - ;; (Note that we can't do a similar test with struct.set, as that would - ;; imply the fields are mutable, which limits optimization, see the next - ;; testcase after this.) - - ;; CHECK: (type $struct (struct_subtype (field (ref $struct)) data)) - (type $struct (struct_subtype (field dataref) data)) - - ;; CHECK: (type $child (struct_subtype (field (ref $child)) $struct)) - (type $child (struct_subtype (field dataref) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $child - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child (ref $child)) - (drop - (struct.new $struct - (local.get $struct) - ) - ) - (drop - (struct.new $child - (local.get $child) - ) - ) - ) -) - -(module - ;; As above, but the fields are mutable. We cannot specialize them to - ;; different types in this case, and both will become $struct (still an - ;; improvement!) - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $struct))) data)) - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $child (struct_subtype (field (mut (ref $struct))) $struct)) - (type $child (struct_subtype (field (mut dataref)) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $child - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child (ref $child)) - (drop - (struct.new $struct - (local.get $struct) - ) - ) - (drop - (struct.new $child - (local.get $child) - ) - ) - ) -) - -(module - ;; As above, but the child also has a new field that is not in the parent. In - ;; that case there is nothing stopping us from specializing that new field - ;; to $child. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $struct))) data)) - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $child (struct_subtype (field (mut (ref $struct))) (field (mut (ref $child))) $struct)) - (type $child (struct_subtype (field (mut dataref)) (field (mut dataref)) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $child - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) (param $child (ref $child)) - (drop - (struct.new $struct - (local.get $struct) - ) - ) - (drop - (struct.new $child - (local.get $child) - (local.get $child) - ) - ) - ) -) - -(module - ;; A copy of a field does not prevent optimization (even though it assigns - ;; the old type). - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref $struct))) data)) - (type $struct (struct_subtype (field (mut dataref)) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (struct.get $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) - (struct.set $struct 0 - (local.get $struct) - (local.get $struct) - ) - (struct.set $struct 0 - (local.get $struct) - (struct.get $struct 0 - (local.get $struct) - ) - ) - ) -) - -(module - ;; CHECK: (type $X (struct_subtype data)) - - ;; CHECK: (type $Y (struct_subtype $X)) - (type $Y (struct_subtype $X)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $A (struct_subtype (field (ref $Y)) data)) - - ;; CHECK: (type $C (struct_subtype (field (ref $Y)) $A)) - (type $C (struct_subtype (field (ref $X)) $A)) - - ;; CHECK: (type $B (struct_subtype (field (ref $Y)) $A)) - (type $B (struct_subtype (field (ref $X)) $A)) - - (type $A (struct_subtype (field (ref $X)) data)) - - (type $X (struct_subtype data)) - - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (local $unused (ref null $C)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $B - ;; CHECK-NEXT: (struct.new_default $Y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - ;; A use of type $C without ever creating an instance of it. We do still need - ;; to update the type if we update the parent type, and we will in fact update - ;; the parent $A's field from $X to $Y (see below), so we must do the same in - ;; $C. As a result, all the fields with $X in them in all of $A, $B, $C will - ;; be improved to contain $Y. - (local $unused (ref null $C)) - - (drop - (struct.new $B - (struct.new $Y) ;; This value is more specific than the field, which is an - ;; opportunity to subtype, which we do for $B. As $A, our - ;; parent, has no writes at all, we can propagate this - ;; info to there as well, which means we can perform the - ;; same optimization in $A as well. - ) - ) - ) -) - -(module - ;; As above, but remove the struct.new to $B, which means $A, $B, $C all have - ;; no writes to them. There are no optimizations to do here. - - ;; CHECK: (type $X (struct_subtype data)) - (type $X (struct_subtype data)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $A (struct_subtype (field (ref $X)) data)) - - ;; CHECK: (type $C (struct_subtype (field (ref $X)) $A)) - (type $C (struct_subtype (field (ref $X)) $A)) - - ;; CHECK: (type $B (struct_subtype (field (ref $X)) $A)) - (type $B (struct_subtype (field (ref $X)) $A)) - - ;; CHECK: (type $Y (struct_subtype $X)) - (type $Y (struct_subtype $X)) - - (type $A (struct_subtype (field (ref $X)) data)) - - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (local $unused1 (ref null $C)) - ;; CHECK-NEXT: (local $unused2 (ref null $B)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $Y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - (local $unused1 (ref null $C)) - (local $unused2 (ref null $B)) - (drop (struct.new $Y)) - ) -) - -(module - ;; CHECK: (type $X (struct_subtype data)) - (type $X (struct_subtype data)) - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $A (struct_subtype (field (ref $X)) data)) - - ;; CHECK: (type $B (struct_subtype (field (ref $Y)) $A)) - (type $B (struct_subtype (field (ref $Y)) $A)) - - (type $A (struct_subtype (field (ref $X)) data)) - - ;; CHECK: (type $Y (struct_subtype $X)) - (type $Y (struct_subtype $X)) - - ;; CHECK: (func $foo (type $none_=>_none) - ;; CHECK-NEXT: (local $unused2 (ref null $B)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $A - ;; CHECK-NEXT: (struct.new_default $X) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $foo - ;; $B begins with its field of type $Y, which is more specific than the - ;; field is in the supertype $A. There are no writes to $B, and so we end - ;; up looking in the parent to see what to do; we should still emit a - ;; reasonable type for $B, and there is no reason to make it *less* - ;; specific, so leave things as they are. - (local $unused2 (ref null $B)) - (drop - (struct.new $A - (struct.new $X) - ) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $struct))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $update-null (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $update-null (param $struct (ref $struct)) - (struct.set $struct 0 - (local.get $struct) - ;; Write a $struct to the field. - (local.get $struct) - ) - (struct.set $struct 0 - (local.get $struct) - ;; This null can be updated, allowing us to refine the type of the field - ;; to a null of $struct. - (ref.null data) - ) - ) -) - -(module - ;; As above, but now the null is in a child. The result should be the same: - ;; refine the field to nullable $struct. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $struct))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) data)) - ;; CHECK: (type $child (struct_subtype (field (mut (ref null $struct))) $struct)) - (type $child (struct_subtype (field (mut (ref null data))) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $update-null (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $child 0 - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $update-null (param $struct (ref $struct)) (param $child (ref $child)) - (struct.set $struct 0 - (local.get $struct) - (local.get $struct) - ) - (struct.set $child 0 - (local.get $child) - (ref.null data) - ) - ) -) - -(module - ;; As above, but now the null is in a parent. The result should be the same. - - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $struct))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) data)) - ;; CHECK: (type $child (struct_subtype (field (mut (ref null $struct))) $struct)) - (type $child (struct_subtype (field (mut (ref null data))) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $update-null (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $child 0 - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $update-null (param $struct (ref $struct)) (param $child (ref $child)) - (struct.set $struct 0 - (local.get $struct) - (ref.null data) - ) - (struct.set $child 0 - (local.get $child) - (local.get $struct) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null data))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) - ;; The only write to this struct is of a null default value. There is - ;; nothing to optimize here. - (drop - (struct.new_default $struct) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $struct))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) - (drop - (struct.new_default $struct) - ) - ;; Also write a $struct. The null default should not prevent us from - ;; refining the field's type to $struct (but nullable). - (struct.set $struct 0 - (local.get $struct) - (local.get $struct) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $struct))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) data)) - - ;; CHECK: (type $ref|$struct|_=>_none (func_subtype (param (ref $struct)) func)) - - ;; CHECK: (func $work (type $ref|$struct|_=>_none) (param $struct (ref $struct)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (struct.set $struct 0 - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $work (param $struct (ref $struct)) - ;; As before, but instead of new_default, new, and use a null in the given - ;; value, which should be updated. - (drop - (struct.new $struct - (ref.null data) - ) - ) - (struct.set $struct 0 - (local.get $struct) - (local.get $struct) - ) - ) -) - -(module - ;; CHECK: (type $struct (struct_subtype (field (mut (ref null $child))) (field (mut (ref null $struct))) data)) - (type $struct (struct_subtype (field (mut (ref null data))) (field (mut (ref null data))) data)) - - ;; CHECK: (type $child (struct_subtype (field (mut (ref null $child))) (field (mut (ref null $struct))) $struct)) - (type $child (struct_subtype (field (mut (ref null data))) (field (mut (ref null data))) $struct)) - - ;; CHECK: (type $ref|$struct|_ref|$child|_=>_none (func_subtype (param (ref $struct) (ref $child)) func)) - - ;; CHECK: (func $update-null (type $ref|$struct|_ref|$child|_=>_none) (param $struct (ref $struct)) (param $child (ref $child)) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (local.get $child) - ;; CHECK-NEXT: (ref.null $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $struct - ;; CHECK-NEXT: (ref.null $child) - ;; CHECK-NEXT: (local.get $struct) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $update-null (param $struct (ref $struct)) (param $child (ref $child)) - ;; Update nulls in two fields that are separately optimized to separate - ;; values. - (drop - (struct.new $struct - (local.get $child) - (ref.null data) - ) - ) - (drop - (struct.new $struct - (ref.null data) - (local.get $struct) - ) - ) - ) -) - -(module - ;; There are two parallel type hierarchies here: "Outer", which are objects - ;; that have fields, that contain the "Inner" objects. - ;; - ;; Root-Outer -> Leaf1-Outer - ;; -> Leaf2-Outer - ;; - ;; Root-Inner -> Leaf1-Inner - ;; -> Leaf2-Inner - ;; - ;; Adding their contents, where X[Y] means X has a field of type Y: - ;; - ;; Root-Outer[Root-Inner] -> Leaf1-Outer[Leaf1-Inner] - ;; -> Leaf2-Outer[Leaf2-Inner] - - ;; CHECK: (type $Root-Inner (struct_subtype data)) - - ;; CHECK: (type $Leaf2-Inner (struct_subtype $Root-Inner)) - (type $Leaf2-Inner (struct_subtype $Root-Inner)) - - ;; CHECK: (type $none_=>_none (func_subtype func)) - - ;; CHECK: (type $Root-Outer (struct_subtype (field (ref $Leaf2-Inner)) data)) - - ;; CHECK: (type $Leaf1-Outer (struct_subtype (field (ref $Leaf2-Inner)) $Root-Outer)) - (type $Leaf1-Outer (struct_subtype (field (ref $Leaf1-Inner)) $Root-Outer)) - - ;; CHECK: (type $Leaf2-Outer (struct_subtype (field (ref $Leaf2-Inner)) $Root-Outer)) - (type $Leaf2-Outer (struct_subtype (field (ref $Leaf2-Inner)) $Root-Outer)) - - (type $Root-Outer (struct_subtype (field (ref $Root-Inner)) data)) - - (type $Root-Inner (struct_subtype data)) - - (type $Leaf1-Inner (struct_subtype (field i32) $Root-Inner)) - - ;; CHECK: (func $func (type $none_=>_none) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.null $Leaf1-Outer) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (struct.new $Leaf2-Outer - ;; CHECK-NEXT: (struct.new_default $Leaf2-Inner) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $func - (drop - ;; The situation here is that we have only a get for some types, and no - ;; other constraints. As we ignore gets, we work under no constraints at - ;; We then have to pick some type, so we pick the one used by our - ;; supertype - and the supertype might have picked up a type from another - ;; branch of the type tree, which is not a subtype of ours. - ;; - ;; In more detail, we never create an instance of $Leaf1-Outer, and we - ;; only have a get of its field. This optimization ignores the get (to not - ;; be limited by it). It will then optimize $Leaf1-Outer's field of - ;; $Leaf1-Inner (another struct for which we have no creation, and only a - ;; get) into $Leaf2-Inner, which is driven by the fact that we do have a - ;; creation of $Leaf2-Inner. But then this struct.get $Leaf1-Inner on field - ;; 0 is no longer valid, as we turn $Leaf1-Inner => $Leaf2-Inner, and - ;; $Leaf2-Inner has no field 0. To keep the module validating, we must not - ;; emit that. Instead, since there can be no instance of $Leaf1-Inner (as - ;; mentioned before, it is never created, nor anything that can be cast to - ;; it), we know this code is logically unreachable, and can emit an - ;; unreachable here. - (struct.get $Leaf1-Inner 0 - (struct.get $Leaf1-Outer 0 - (ref.null $Leaf1-Outer) - ) - ) - ) - (drop - (struct.new $Leaf2-Outer - (struct.new_default $Leaf2-Inner) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/untee.wast binaryen-99/test/lit/passes/untee.wast --- binaryen-108/test/lit/passes/untee.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/untee.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; NOTE: This test was ported using port_test.py and could be cleaned up. - -;; RUN: foreach %s %t wasm-opt --untee -S -o - | filecheck %s - -(module - ;; CHECK: (type $none_=>_none (func)) - - ;; CHECK: (func $tee - ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (local $y f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result f64) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (f64.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $tee - (local $x i32) - (local $y f64) - (drop (local.tee $x (i32.const 1))) - (drop (local.tee $y (f64.const 2))) - (local.set $x (local.tee $x (i32.const 3))) - (local.set $x (local.tee $x (local.tee $x (i32.const 3)))) - (drop (local.tee $x (unreachable))) - ) -) - diff -Nru binaryen-108/test/lit/passes/vacuum-eh.wast binaryen-99/test/lit/passes/vacuum-eh.wast --- binaryen-108/test/lit/passes/vacuum-eh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/vacuum-eh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s - -(module - ;; CHECK: (tag $e (param i32)) - (tag $e (param i32)) - ;; CHECK: (tag $e2 (param i32)) - (tag $e2 (param i32)) - - ;; CHECK: (func $try-test - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $try-test - ;; When try body does not throw, try-body can be replaced with the try body - (try - (do - (drop (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - ) - ) - ) - - ;; CHECK: (func $inner-try-catch_all-test - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $inner-try-catch_all-test (local $0 i32) - ;; The exception thrown in the inner try is caught by the inner catch_all, - ;; so the outer try body does not throw and the outer try-catch can be - ;; removed - (try - (do - (try - (do - (throw $e (i32.const 0)) - ) - (catch_all - (local.set $0 (i32.const 1)) - ) - ) - ) - (catch $e - (drop (pop i32)) - ) - ) - ) - - ;; CHECK: (func $inner-try-catch-test - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try1 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch $e - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (pop i32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $inner-try-catch-test (local $0 i32) - ;; The exception thrown in the inner try will not be caught by the inner - ;; catch, so the outer try-catch cannot be removed - (try - (do - (try - (do - (throw $e2 (i32.const 0)) - ) - (catch $e - (drop (pop i32)) - (local.set $0 (i32.const 1)) - ) - ) - ) - (catch $e - (drop (pop i32)) - ) - ) - ) - - ;; CHECK: (func $br-in-catch - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $br-in-catch - ;; When catch body is removed, the removal of 'br' inside the catch body - ;; should be propagated up to the outer block, so that its type will be - ;; correctly updated to unreachable. - (block $label$1 - (try - (do - (unreachable) - ) - (catch $e - (drop (pop i32)) - (br $label$1) - ) - ) - ) - ) - - ;; CHECK: (func $try-delegate-outer-target - ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (try $label$0 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (try $try2 - ;; CHECK-NEXT: (do - ;; CHECK-NEXT: (throw $e - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (delegate $label$0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (catch_all - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $try-delegate-outer-target - (local $0 i32) - (try $label$0 ;; outer try - (do - ;; If it were not for the inner (delegate $label0), this middle try - ;; cannot throw even if there is a throw in the inner try, because this - ;; try has a catch_all. And Vacuum can replace the outer try-catch with - ;; the try's body if the body doesn't throw. - ;; - ;; But because the inner try has a delegate that targets the outer try, - ;; this middle try can throw, and we can't do the optimization for - ;; the outer try. - (try ;; middle try - (do - (try ;; inner try - (do - (throw $e - (i32.const 0) - ) - ) - (delegate $label$0) - ) - ) - (catch_all) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/vacuum-gc.wast binaryen-99/test/lit/passes/vacuum-gc.wast --- binaryen-108/test/lit/passes/vacuum-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/vacuum-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s - -(module - (type ${} (struct)) - - ;; CHECK: (func $drop-ref-as (param $x anyref) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_func - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_data - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.as_i31 - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $drop-ref-as (param $x anyref) - ;; Without -tnh, we must assume all ref_as* can have a trap effect, and so - ;; we cannot remove anything here. - (drop - (ref.as_non_null - (local.get $x) - ) - ) - (drop - (ref.as_func - (local.get $x) - ) - ) - (drop - (ref.as_data - (local.get $x) - ) - ) - (drop - (ref.as_i31 - (local.get $x) - ) - ) - ) - - ;; CHECK: (func $vacuum-rtt-with-depth - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $vacuum-rtt-with-depth - (drop - (if (result (rtt 1 ${})) - (i32.const 1) - ;; This block's result is not used. As a consequence vacuum will try to - ;; generate a replacement zero for the block's fallthrough value. An rtt - ;; with depth is a problem for that, since we can't just create an - ;; rtt.canon - we'd need to add some rtt.subs, and it's not clear that we'd - ;; be improving code size while doing so, hence we do not allow making a - ;; zero of that type. Vacuum should not error on trying to do so. And - ;; the end result of this function should simply be empty, as everything - ;; here can be vacuumed away. - (block (result (rtt 1 ${})) - (rtt.sub ${} - (rtt.canon ${}) - ) - ) - (unreachable) - ) - ) - ) -) diff -Nru binaryen-108/test/lit/passes/vacuum-intrinsics.wast binaryen-99/test/lit/passes/vacuum-intrinsics.wast --- binaryen-108/test/lit/passes/vacuum-intrinsics.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/vacuum-intrinsics.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --vacuum -all -S -o - | filecheck %s - -(module - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects (param funcref) (result i32))) - (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects (param funcref) (result i32))) - - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-fj (param f32 funcref) (result i64))) - (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-fj (param f32) (param funcref) (result i64))) - - ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-ref (param funcref) (result (ref any)))) - (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects-ref (param funcref) (result (ref any)))) - - ;; CHECK: (func $used - ;; CHECK-NEXT: (local $i32 i32) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (call $call.without.effects - ;; CHECK-NEXT: (ref.func $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $used - (local $i32 i32) - ;; The result is used (by the local.set), so we cannot do anything here. - (local.set $i32 - (call $call.without.effects (ref.func $i)) - ) - ) - - ;; CHECK: (func $unused - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $unused - ;; The result is unused, so we can remove the call. - (drop - (call $call.without.effects (ref.func $i)) - ) - ) - - ;; CHECK: (func $unused-fj - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $unused-fj - ;; As above, but with an extra float param and a different result type. - (drop - (call $call.without.effects-fj (f32.const 2.71828) (ref.func $fj)) - ) - ) - - ;; CHECK: (func $unused-fj-side-effects - ;; CHECK-NEXT: (local $f32 f32) - ;; CHECK-NEXT: (local.set $f32 - ;; CHECK-NEXT: (f32.const 2.718280076980591) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unused-fj-side-effects - (local $f32 f32) - ;; As above, but side effects in the param. We must keep the params around - ;; and drop them. - (drop - (call $call.without.effects-fj - (local.tee $f32 - (f32.const 2.71828) - ) - (ref.func $fj) - ) - ) - ) - - ;; CHECK: (func $unused-unreachable - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $call.without.effects-fj - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (ref.func $fj) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unused-unreachable - ;; An unused result, but the call is unreachable and so we ignore it (and - ;; leave it for DCE). - (drop - (call $call.without.effects-fj (unreachable) (ref.func $fj)) - ) - ) - - ;; CHECK: (func $used-fallthrough - ;; CHECK-NEXT: (local $i32 i32) - ;; CHECK-NEXT: (local.set $i32 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (block $condition (result i32) - ;; CHECK-NEXT: (call $nop) - ;; CHECK-NEXT: (call $call.without.effects - ;; CHECK-NEXT: (ref.func $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $ifTrue (result i32) - ;; CHECK-NEXT: (call $nop) - ;; CHECK-NEXT: (call $call.without.effects - ;; CHECK-NEXT: (ref.func $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $ifFalse (result i32) - ;; CHECK-NEXT: (call $nop) - ;; CHECK-NEXT: (call $call.without.effects - ;; CHECK-NEXT: (ref.func $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $used-fallthrough - (local $i32 i32) - (local.set $i32 - (if (result i32) - ;; The block falls through a value that is used as the if condition. - (block $condition (result i32) - ;; Add a call to $nop so that the blocks are not optimized away. - (call $nop) - (call $call.without.effects (ref.func $i)) - ) - ;; The arms fall through their blocks and also through the if, and end - ;; up used by the set. - (block $ifTrue (result i32) - (call $nop) - (call $call.without.effects (ref.func $i)) - ) - (block $ifFalse (result i32) - (call $nop) - (call $call.without.effects (ref.func $i)) - ) - ) - ) - ) - - ;; CHECK: (func $unused-fallthrough - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (block $condition (result i32) - ;; CHECK-NEXT: (call $nop) - ;; CHECK-NEXT: (call $call.without.effects - ;; CHECK-NEXT: (ref.func $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $ifTrue (result i32) - ;; CHECK-NEXT: (call $nop) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $ifFalse (result i32) - ;; CHECK-NEXT: (call $nop) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unused-fallthrough - (drop - (if (result i32) - (block $condition (result i32) - (call $nop) - (call $call.without.effects (ref.func $i)) - ) - ;; As above, but now there is a drop outside the if, so the arms are - ;; unused and we can optimize them. - (block $ifTrue (result i32) - (call $nop) - (call $call.without.effects (ref.func $i)) - ) - (block $ifFalse (result i32) - (call $nop) - (call $call.without.effects (ref.func $i)) - ) - ) - ) - ) - - ;; CHECK: (func $unused-fallthrough-bad-type - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (if (result (ref any)) - ;; CHECK-NEXT: (call $i) - ;; CHECK-NEXT: (call $call.without.effects-ref - ;; CHECK-NEXT: (ref.func $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call $call.without.effects-ref - ;; CHECK-NEXT: (ref.func $ref) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unused-fallthrough-bad-type - (drop - (if (result (ref any)) - (call $i) - ;; As above, but the type of these unused values prevents us from - ;; optimizing as we cannot create a "zero" for them. - (call $call.without.effects-ref (ref.func $ref)) - (call $call.without.effects-ref (ref.func $ref)) - ) - ) - ) - - ;; CHECK: (func $i (result i32) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $i (result i32) - ;; Helper function for the above. - (unreachable) - ) - - ;; CHECK: (func $fj (param $0 f32) (result i64) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $fj (param f32) (result i64) - ;; Helper function for the above. - (unreachable) - ) - - ;; CHECK: (func $ref (result (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $ref (result (ref any)) - ;; Helper function for the above. - (unreachable) - ) - - - ;; CHECK: (func $nop - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $nop - ;; Helper function for the above. - (nop) - ) -) diff -Nru binaryen-108/test/lit/passes/vacuum-tnh.wast binaryen-99/test/lit/passes/vacuum-tnh.wast --- binaryen-108/test/lit/passes/vacuum-tnh.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/passes/vacuum-tnh.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --vacuum --traps-never-happen -all -S -o - | filecheck %s - -(module - (memory 1 1) - - ;; CHECK: (type $struct (struct (field (mut i32)))) - (type $struct (struct (field (mut i32)))) - - ;; CHECK: (func $drop (param $x i32) (param $y anyref) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $drop (param $x i32) (param $y anyref) - ;; A load might trap, normally, but if traps never happen then we can - ;; remove it. - (drop - (i32.load (local.get $x)) - ) - - ;; A trap on a null value can also be ignored. - (drop - (ref.as_non_null - (local.get $y) - ) - ) - - ;; Other ref.as* as well. - (drop - (ref.as_func - (local.get $y) - ) - ) - (drop - (ref.as_data - (local.get $y) - ) - ) - (drop - (ref.as_i31 - (local.get $y) - ) - ) - - ;; Ignore unreachable code. - (drop - (unreachable) - ) - ) - - ;; Other side effects prevent us making any changes. - ;; CHECK: (func $other-side-effects (param $x i32) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $other-side-effects - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - (func $other-side-effects (param $x i32) (result i32) - ;; A call has all manner of other side effects. - (drop - (call $other-side-effects (i32.const 1)) - ) - - ;; Add to the load an additional specific side effect, of writing to a - ;; local. We can remove the load, but not the write to a local. - (drop - (block (result i32) - (local.set $x (i32.const 2)) - (i32.load (local.get $x)) - ) - ) - - (i32.const 1) - ) - - ;; A helper function for the above, that returns nothing. - ;; CHECK: (func $return-nothing - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $return-nothing) - - ;; CHECK: (func $partial (param $x (ref $struct)) - ;; CHECK-NEXT: (local $y (ref null $struct)) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $partial (param $x (ref $struct)) - (local $y (ref null $struct)) - ;; The struct.get's side effect can be ignored due to tnh, and the value is - ;; dropped anyhow, so we can remove it. We cannot remove the local.tee - ;; inside it, however, so we must only vacuum out the struct.get and - ;; nothing more. (In addition, a drop of a tee will become a set.) - (drop - (struct.get $struct 0 - (local.tee $y - (local.get $x) - ) - ) - ) - ;; Similar, but with an eqz on the outside, which can also be removed. - (drop - (i32.eqz - (struct.get $struct 0 - (local.tee $y - (local.get $x) - ) - ) - ) - ) - ) - - ;; CHECK: (func $toplevel - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $toplevel - ;; A removable side effect at the top level of a function. We can turn this - ;; into a nop. - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/recursive-type-sort.wast binaryen-99/test/lit/recursive-type-sort.wast --- binaryen-108/test/lit/recursive-type-sort.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/recursive-type-sort.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -;; Test that multiple recursive types are sorted and emitted properly. -;; Regression test for a bug in TypeComparator that made it fail to properly -;; implement the C++ Compare requirements. See #3648. - -;; RUN: wasm-opt %s -all --roundtrip -S -o - | filecheck %s -;; RUN: wasm-opt %s -all --roundtrip --nominal -S -o - | filecheck %s - -;; Check that there's no crash. -;; CHECK: module - -(module - (type $a (func (param (ref null $b)))) - (type $b (struct (field (ref null $i)))) - (type $c (struct (field (ref null $l)))) - (type $d (func (param (ref null $b)))) - (type $e (func (result (ref null $g)))) - (type $f (func (result (ref null $c)))) - (type $g (struct (field (ref null $j)))) - (type $h (struct (field (ref null $k)))) - (type $i (struct (field (mut (ref null $a))))) - (type $j (struct (field (mut (ref null $a))) (field (mut (ref null $a))))) - (type $k (struct (field (mut (ref null $a))) (field (mut (ref null $a))) (field (mut (ref null $e))))) - (type $l (struct (field (mut (ref null $a))) (field (mut (ref null $d))) (field (mut (ref null $f))))) - - (func $foo - (local $1 (ref null $h)) - (local $2 (ref null $b)) - (local $3 (ref null $c)) - ) -) diff -Nru binaryen-108/test/lit/recursive-types.wast binaryen-99/test/lit/recursive-types.wast --- binaryen-108/test/lit/recursive-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/recursive-types.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. -;; Test that a trivial recursive type works properly - -;; RUN: wasm-opt %s -all --name-types -S -o - | filecheck %s - -(module - (type (func (param (ref null 0)) (result (ref null 0)))) - (type (func (param (ref null 1)) (result (ref null 1)))) - (type (func (param (ref null 0)) (result (ref null 1)))) - (type (func (param (ref null 3)) (result (ref null 4)))) - (type (func (param (ref null 4)) (result (ref null 3)))) - - ;; CHECK: (type $type$0 (func (param (ref null $type$0)) (result (ref null $type$0)))) - - ;; CHECK: (func $foo (param $0 (ref null $type$0)) (result (ref null $type$0)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $foo (type 0) - (unreachable) - ) - - ;; CHECK: (func $bar (param $0 (ref null $type$0)) (result (ref null $type$0)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $bar (type 1) - (unreachable) - ) - - ;; CHECK: (func $baz (param $0 (ref null $type$0)) (result (ref null $type$0)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $baz (type 2) - (unreachable) - ) - - ;; CHECK: (func $qux (param $0 (ref null $type$0)) (result (ref null $type$0)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $qux (type 3) - (unreachable) - ) - - ;; CHECK: (func $quux (param $0 (ref null $type$0)) (result (ref null $type$0)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - (func $quux (type 4) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/ref-cast-nop.wast binaryen-99/test/lit/ref-cast-nop.wast --- binaryen-108/test/lit/ref-cast-nop.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/ref-cast-nop.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; RUN: wasm-opt -all %s -S --roundtrip -o - | filecheck %s - -(module - ;; CHECK: (type $struct (struct (field i32))) - (type $struct (struct i32)) - ;; CHECK: (func $ref.cast_nop_static (param $x (ref any)) (result (ref $struct)) - ;; CHECK-NEXT: (ref.cast_nop_static $struct - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $ref.cast_nop_static (param $x (ref any)) (result (ref $struct)) - (ref.cast_nop_static $struct - (local.get $x) - ) - ) -) diff -Nru binaryen-108/test/lit/relaxed-simd.wast binaryen-99/test/lit/relaxed-simd.wast --- binaryen-108/test/lit/relaxed-simd.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/relaxed-simd.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,621 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: wasm-as %s -all -g -o %t.wasm -;; RUN: wasm-dis %t.wasm -all -o %t.wast -;; RUN: wasm-as %s -all -o %t.nodebug.wasm -;; RUN: wasm-dis %t.nodebug.wasm -all -o %t.nodebug.wast -;; RUN: wasm-opt %t.wast -all -o %t.text.wast -g -S -;; RUN: cat %t.wast | filecheck %s --check-prefix=CHECK-BINARY -;; RUN: cat %t.nodebug.wast | filecheck %s --check-prefix=CHECK-NODEBUG -;; RUN: cat %t.text.wast | filecheck %s --check-prefix=CHECK-TEXT -(module - (memory 1 1) - - ;; CHECK-BINARY: (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) - - ;; CHECK-BINARY: (type $v128_v128_=>_v128 (func (param v128 v128) (result v128))) - - ;; CHECK-BINARY: (type $v128_=>_v128 (func (param v128) (result v128))) - - ;; CHECK-BINARY: (memory $0 1 1) - - ;; CHECK-BINARY: (func $i8x16.relaxed_swizzle (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i8x16.relaxed_swizzle - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) - - ;; CHECK-TEXT: (type $v128_v128_=>_v128 (func (param v128 v128) (result v128))) - - ;; CHECK-TEXT: (type $v128_=>_v128 (func (param v128) (result v128))) - - ;; CHECK-TEXT: (memory $0 1 1) - - ;; CHECK-TEXT: (func $i8x16.relaxed_swizzle (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i8x16.relaxed_swizzle - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i8x16.relaxed_swizzle (param $0 v128) (param $1 v128) (result v128) - (i8x16.relaxed_swizzle - (local.get $0) - (local.get $1) - ) - ) - - ;; CHECK-BINARY: (func $i32x4.relaxed_trunc_f32x4_s (param $0 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i32x4.relaxed_trunc_f32x4_s - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i32x4.relaxed_trunc_f32x4_s (param $0 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i32x4.relaxed_trunc_f32x4_s - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i32x4.relaxed_trunc_f32x4_s (param $0 v128) (result v128) - (i32x4.relaxed_trunc_f32x4_s - (local.get $0) - ) - ) - ;; CHECK-BINARY: (func $i32x4.relaxed_trunc_f32x4_u (param $0 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i32x4.relaxed_trunc_f32x4_u - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i32x4.relaxed_trunc_f32x4_u (param $0 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i32x4.relaxed_trunc_f32x4_u - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i32x4.relaxed_trunc_f32x4_u (param $0 v128) (result v128) - (i32x4.relaxed_trunc_f32x4_u - (local.get $0) - ) - ) - ;; CHECK-BINARY: (func $i32x4.relaxed_trunc_f64x2_s_zero (param $0 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i32x4.relaxed_trunc_f64x2_s_zero - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i32x4.relaxed_trunc_f64x2_s_zero (param $0 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i32x4.relaxed_trunc_f64x2_s_zero - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i32x4.relaxed_trunc_f64x2_s_zero (param $0 v128) (result v128) - (i32x4.relaxed_trunc_f64x2_s_zero - (local.get $0) - ) - ) - ;; CHECK-BINARY: (func $i32x4.relaxed_trunc_f64x2_u_zero (param $0 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i32x4.relaxed_trunc_f64x2_u_zero - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i32x4.relaxed_trunc_f64x2_u_zero (param $0 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i32x4.relaxed_trunc_f64x2_u_zero - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i32x4.relaxed_trunc_f64x2_u_zero (param $0 v128) (result v128) - (i32x4.relaxed_trunc_f64x2_u_zero - (local.get $0) - ) - ) - - ;; CHECK-BINARY: (func $f32x4.relaxed_fma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f32x4.relaxed_fma - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f32x4.relaxed_fma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f32x4.relaxed_fma - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f32x4.relaxed_fma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (f32x4.relaxed_fma - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ;; CHECK-BINARY: (func $f32x4.relaxed_fms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f32x4.relaxed_fms - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f32x4.relaxed_fms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f32x4.relaxed_fms - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f32x4.relaxed_fms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (f32x4.relaxed_fms - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ;; CHECK-BINARY: (func $f64x2.relaxed_fma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f64x2.relaxed_fma - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f64x2.relaxed_fma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f64x2.relaxed_fma - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f64x2.relaxed_fma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (f64x2.relaxed_fma - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ;; CHECK-BINARY: (func $f64x2.relaxed_fms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f64x2.relaxed_fms - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f64x2.relaxed_fms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f64x2.relaxed_fms - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f64x2.relaxed_fms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (f64x2.relaxed_fms - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - - ;; CHECK-BINARY: (func $i8x16.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i8x16.laneselect - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i8x16.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i8x16.laneselect - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i8x16.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (i8x16.laneselect - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ;; CHECK-BINARY: (func $i16x8.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i16x8.laneselect - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i16x8.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i16x8.laneselect - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i16x8.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (i16x8.laneselect - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ;; CHECK-BINARY: (func $i32x4.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i32x4.laneselect - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i32x4.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i32x4.laneselect - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i32x4.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (i32x4.laneselect - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - ;; CHECK-BINARY: (func $i64x2.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i64x2.laneselect - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: (local.get $2) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i64x2.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i64x2.laneselect - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: (local.get $2) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i64x2.laneselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (i64x2.laneselect - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - - ;; CHECK-BINARY: (func $f32x4.relaxed_min (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f32x4.relaxed_min - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f32x4.relaxed_min (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f32x4.relaxed_min - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f32x4.relaxed_min (param $0 v128) (param $1 v128) (result v128) - (f32x4.relaxed_min - (local.get $0) - (local.get $1) - ) - ) - ;; CHECK-BINARY: (func $f32x4.relaxed_max (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f32x4.relaxed_max - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f32x4.relaxed_max (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f32x4.relaxed_max - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f32x4.relaxed_max (param $0 v128) (param $1 v128) (result v128) - (f32x4.relaxed_max - (local.get $0) - (local.get $1) - ) - ) - ;; CHECK-BINARY: (func $f64x2.relaxed_min (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f64x2.relaxed_min - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f64x2.relaxed_min (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f64x2.relaxed_min - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f64x2.relaxed_min (param $0 v128) (param $1 v128) (result v128) - (f64x2.relaxed_min - (local.get $0) - (local.get $1) - ) - ) - ;; CHECK-BINARY: (func $f64x2.relaxed_max (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (f64x2.relaxed_max - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $f64x2.relaxed_max (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (f64x2.relaxed_max - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $f64x2.relaxed_max (param $0 v128) (param $1 v128) (result v128) - (f64x2.relaxed_max - (local.get $0) - (local.get $1) - ) - ) - - ;; CHECK-BINARY: (func $i16x8.relaxed_q15mulr_s (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i16x8.relaxed_q15mulr_s - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i16x8.relaxed_q15mulr_s (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i16x8.relaxed_q15mulr_s - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i16x8.relaxed_q15mulr_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.relaxed_q15mulr_s - (local.get $0) - (local.get $1) - ) - ) - - ;; CHECK-BINARY: (func $i16x8.dot_i8x16_i7x16_s (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i16x8.dot_i8x16_i7x16_s - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i16x8.dot_i8x16_i7x16_s (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i16x8.dot_i8x16_i7x16_s - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i16x8.dot_i8x16_i7x16_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.dot_i8x16_i7x16_s - (local.get $0) - (local.get $1) - ) - ) - - ;; CHECK-BINARY: (func $i16x8.dot_i8x16_i7x16_u (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-BINARY-NEXT: (i16x8.dot_i8x16_i7x16_u - ;; CHECK-BINARY-NEXT: (local.get $0) - ;; CHECK-BINARY-NEXT: (local.get $1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $i16x8.dot_i8x16_i7x16_u (param $0 v128) (param $1 v128) (result v128) - ;; CHECK-TEXT-NEXT: (i16x8.dot_i8x16_i7x16_u - ;; CHECK-TEXT-NEXT: (local.get $0) - ;; CHECK-TEXT-NEXT: (local.get $1) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $i16x8.dot_i8x16_i7x16_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.dot_i8x16_i7x16_u - (local.get $0) - (local.get $1) - ) - ) - -;; CHECK-BINARY: (func $i32x4.dot_i8x16_i7x16_add_s (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-BINARY-NEXT: (i32x4.dot_i8x16_i7x16_add_s -;; CHECK-BINARY-NEXT: (local.get $0) -;; CHECK-BINARY-NEXT: (local.get $1) -;; CHECK-BINARY-NEXT: (local.get $2) -;; CHECK-BINARY-NEXT: ) -;; CHECK-BINARY-NEXT: ) -;; CHECK-TEXT: (func $i32x4.dot_i8x16_i7x16_add_s (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-TEXT-NEXT: (i32x4.dot_i8x16_i7x16_add_s -;; CHECK-TEXT-NEXT: (local.get $0) -;; CHECK-TEXT-NEXT: (local.get $1) -;; CHECK-TEXT-NEXT: (local.get $2) -;; CHECK-TEXT-NEXT: ) -;; CHECK-TEXT-NEXT: ) -(func $i32x4.dot_i8x16_i7x16_add_s (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (i32x4.dot_i8x16_i7x16_add_s - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - -;; CHECK-BINARY: (func $i32x4.dot_i8x16_i7x16_add_u (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-BINARY-NEXT: (i32x4.dot_i8x16_i7x16_add_u -;; CHECK-BINARY-NEXT: (local.get $0) -;; CHECK-BINARY-NEXT: (local.get $1) -;; CHECK-BINARY-NEXT: (local.get $2) -;; CHECK-BINARY-NEXT: ) -;; CHECK-BINARY-NEXT: ) -;; CHECK-TEXT: (func $i32x4.dot_i8x16_i7x16_add_u (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-TEXT-NEXT: (i32x4.dot_i8x16_i7x16_add_u -;; CHECK-TEXT-NEXT: (local.get $0) -;; CHECK-TEXT-NEXT: (local.get $1) -;; CHECK-TEXT-NEXT: (local.get $2) -;; CHECK-TEXT-NEXT: ) -;; CHECK-TEXT-NEXT: ) -(func $i32x4.dot_i8x16_i7x16_add_u (param $0 v128) (param $1 v128) (param $2 v128) (result v128) - (i32x4.dot_i8x16_i7x16_add_u - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - -) -;; CHECK-NODEBUG: (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) - -;; CHECK-NODEBUG: (type $v128_v128_=>_v128 (func (param v128 v128) (result v128))) - -;; CHECK-NODEBUG: (type $v128_=>_v128 (func (param v128) (result v128))) - -;; CHECK-NODEBUG: (memory $0 1 1) - -;; CHECK-NODEBUG: (func $0 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i8x16.relaxed_swizzle -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $1 (param $0 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.relaxed_trunc_f32x4_s -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $2 (param $0 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.relaxed_trunc_f32x4_u -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $3 (param $0 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.relaxed_trunc_f64x2_s_zero -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $4 (param $0 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.relaxed_trunc_f64x2_u_zero -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $5 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f32x4.relaxed_fma -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $6 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f32x4.relaxed_fms -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $7 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f64x2.relaxed_fma -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $8 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f64x2.relaxed_fms -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $9 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i8x16.laneselect -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $10 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i16x8.laneselect -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $11 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.laneselect -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $12 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i64x2.laneselect -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $13 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f32x4.relaxed_min -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $14 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f32x4.relaxed_max -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $15 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f64x2.relaxed_min -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $16 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (f64x2.relaxed_max -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $17 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i16x8.relaxed_q15mulr_s -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $18 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i16x8.dot_i8x16_i7x16_s -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $19 (param $0 v128) (param $1 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i16x8.dot_i8x16_i7x16_u -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $20 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.dot_i8x16_i7x16_add_s -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $21 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) -;; CHECK-NODEBUG-NEXT: (i32x4.dot_i8x16_i7x16_add_u -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: (local.get $1) -;; CHECK-NODEBUG-NEXT: (local.get $2) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) diff -Nru binaryen-108/test/lit/stdin-stdout.wast binaryen-99/test/lit/stdin-stdout.wast --- binaryen-108/test/lit/stdin-stdout.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/stdin-stdout.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt < %s - -S -o - | filecheck %s -;; RUN: wasm-opt < %s - -g -o - | wasm-opt - -S -o - | filecheck %s - -;; Test that file `-` is interpreted as stdin and stdout. - -(module - ;; CHECK: (func $foo - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - (func $foo - (nop) - ) -) diff -Nru binaryen-108/test/lit/table-first-special.wast binaryen-99/test/lit/table-first-special.wast --- binaryen-108/test/lit/table-first-special.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/table-first-special.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: wasm-as %s -all -g -o %t.wasm -;; RUN: wasm-dis %t.wasm -all -o %t.wast -;; RUN: wasm-as %s -all -o %t.nodebug.wasm -;; RUN: wasm-dis %t.nodebug.wasm -all -o %t.nodebug.wast -;; RUN: wasm-opt %t.wast -all -o %t.text.wast -g -S -;; RUN: cat %t.wast | filecheck %s --check-prefix=CHECK-BINARY -;; RUN: cat %t.nodebug.wast | filecheck %s --check-prefix=CHECK-NODEBUG -;; RUN: cat %t.text.wast | filecheck %s --check-prefix=CHECK-TEXT - -;; The very first table has a specialized type, as does its element segment. -;; Verify that we can roundtrip that. -(module - ;; CHECK-BINARY: (type $vii (func (param i32 i32))) - ;; CHECK-TEXT: (type $vii (func (param i32 i32))) - (type $vii (func (param i32 i32))) - ;; CHECK-BINARY: (table $table-1 10 10 (ref null $vii)) - ;; CHECK-TEXT: (table $table-1 10 10 (ref null $vii)) - (table $table-1 10 10 (ref null $vii)) - ;; CHECK-BINARY: (elem $elem-1 (table $table-1) (i32.const 0) (ref null $vii)) - ;; CHECK-TEXT: (elem $elem-1 (table $table-1) (i32.const 0) (ref null $vii)) - (elem $elem-1 (table $table-1) (i32.const 0) (ref null $vii)) - ;; CHECK-BINARY: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-BINARY-NEXT: (nop) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $foo (param $0 i32) (param $1 i32) - ;; CHECK-TEXT-NEXT: (nop) - ;; CHECK-TEXT-NEXT: ) - (func $foo (param $0 i32) (param $1 i32) - (nop) - ) -) -;; CHECK-NODEBUG: (type $i32_i32_=>_none (func (param i32 i32))) - -;; CHECK-NODEBUG: (table $0 10 10 (ref null $i32_i32_=>_none)) - -;; CHECK-NODEBUG: (elem (table $0) (i32.const 0) (ref null $i32_i32_=>_none)) - -;; CHECK-NODEBUG: (func $0 (param $0 i32) (param $1 i32) -;; CHECK-NODEBUG-NEXT: (nop) -;; CHECK-NODEBUG-NEXT: ) diff -Nru binaryen-108/test/lit/table-operations.wast binaryen-99/test/lit/table-operations.wast --- binaryen-108/test/lit/table-operations.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/table-operations.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,203 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. - -;; RUN: wasm-as %s -all -g -o %t.wasm -;; RUN: wasm-dis %t.wasm -all -o %t.wast -;; RUN: wasm-as %s -all -o %t.nodebug.wasm -;; RUN: wasm-dis %t.nodebug.wasm -all -o %t.nodebug.wast -;; RUN: wasm-opt %t.wast -all -o %t.text.wast -g -S -;; RUN: cat %t.wast | filecheck %s --check-prefix=CHECK-BINARY -;; RUN: cat %t.nodebug.wast | filecheck %s --check-prefix=CHECK-NODEBUG -;; RUN: cat %t.text.wast | filecheck %s --check-prefix=CHECK-TEXT - -(module - ;; CHECK-BINARY: (type $none_=>_none (func)) - - ;; CHECK-BINARY: (type $none_=>_i32 (func (result i32))) - - ;; CHECK-BINARY: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK-BINARY: (table $table-1 1 1 funcref) - ;; CHECK-TEXT: (type $none_=>_none (func)) - - ;; CHECK-TEXT: (type $none_=>_i32 (func (result i32))) - - ;; CHECK-TEXT: (type $i32_=>_i32 (func (param i32) (result i32))) - - ;; CHECK-TEXT: (table $table-1 1 1 funcref) - (table $table-1 funcref - (elem $foo) - ) - - ;; CHECK-BINARY: (table $table-2 3 3 funcref) - ;; CHECK-TEXT: (table $table-2 3 3 funcref) - (table $table-2 funcref - (elem $bar $bar $bar) - ) - - ;; CHECK-BINARY: (elem $0 (table $table-1) (i32.const 0) func $foo) - - ;; CHECK-BINARY: (elem $1 (table $table-2) (i32.const 0) func $bar $bar $bar) - - ;; CHECK-BINARY: (func $foo - ;; CHECK-BINARY-NEXT: (nop) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (elem $0 (table $table-1) (i32.const 0) func $foo) - - ;; CHECK-TEXT: (elem $1 (table $table-2) (i32.const 0) func $bar $bar $bar) - - ;; CHECK-TEXT: (func $foo - ;; CHECK-TEXT-NEXT: (nop) - ;; CHECK-TEXT-NEXT: ) - (func $foo - (nop) - ) - ;; CHECK-BINARY: (func $bar - ;; CHECK-BINARY-NEXT: (drop - ;; CHECK-BINARY-NEXT: (table.get $table-1 - ;; CHECK-BINARY-NEXT: (i32.const 0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (drop - ;; CHECK-BINARY-NEXT: (table.get $table-2 - ;; CHECK-BINARY-NEXT: (i32.const 100) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $bar - ;; CHECK-TEXT-NEXT: (drop - ;; CHECK-TEXT-NEXT: (table.get $table-1 - ;; CHECK-TEXT-NEXT: (i32.const 0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (drop - ;; CHECK-TEXT-NEXT: (table.get $table-2 - ;; CHECK-TEXT-NEXT: (i32.const 100) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $bar - (drop - (table.get $table-1 - (i32.const 0) - ) - ) - (drop - (table.get $table-2 - (i32.const 100) - ) - ) - ) - - ;; CHECK-BINARY: (func $set-get - ;; CHECK-BINARY-NEXT: (table.set $table-1 - ;; CHECK-BINARY-NEXT: (i32.const 0) - ;; CHECK-BINARY-NEXT: (ref.func $foo) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: (drop - ;; CHECK-BINARY-NEXT: (table.get $table-1 - ;; CHECK-BINARY-NEXT: (i32.const 0) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $set-get - ;; CHECK-TEXT-NEXT: (table.set $table-1 - ;; CHECK-TEXT-NEXT: (i32.const 0) - ;; CHECK-TEXT-NEXT: (ref.func $foo) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: (drop - ;; CHECK-TEXT-NEXT: (table.get $table-1 - ;; CHECK-TEXT-NEXT: (i32.const 0) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $set-get - (table.set $table-1 - (i32.const 0) - (ref.func $foo) - ) - (drop - (table.get $table-1 - (i32.const 0) - ) - ) - ) - - ;; CHECK-BINARY: (func $get-table-size (result i32) - ;; CHECK-BINARY-NEXT: (table.size $table-1) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $get-table-size (result i32) - ;; CHECK-TEXT-NEXT: (table.size $table-1) - ;; CHECK-TEXT-NEXT: ) - (func $get-table-size (result i32) - (table.size $table-1) - ) - - ;; CHECK-BINARY: (func $table-grow (param $sz i32) (result i32) - ;; CHECK-BINARY-NEXT: (table.grow $table-1 - ;; CHECK-BINARY-NEXT: (ref.null func) - ;; CHECK-BINARY-NEXT: (local.get $sz) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-BINARY-NEXT: ) - ;; CHECK-TEXT: (func $table-grow (param $sz i32) (result i32) - ;; CHECK-TEXT-NEXT: (table.grow $table-1 - ;; CHECK-TEXT-NEXT: (ref.null func) - ;; CHECK-TEXT-NEXT: (local.get $sz) - ;; CHECK-TEXT-NEXT: ) - ;; CHECK-TEXT-NEXT: ) - (func $table-grow (param $sz i32) (result i32) - (table.grow $table-1 (ref.null func) (local.get $sz)) - ) -) -;; CHECK-NODEBUG: (type $none_=>_none (func)) - -;; CHECK-NODEBUG: (type $none_=>_i32 (func (result i32))) - -;; CHECK-NODEBUG: (type $i32_=>_i32 (func (param i32) (result i32))) - -;; CHECK-NODEBUG: (table $0 1 1 funcref) - -;; CHECK-NODEBUG: (table $1 3 3 funcref) - -;; CHECK-NODEBUG: (elem $0 (table $0) (i32.const 0) func $0) - -;; CHECK-NODEBUG: (elem $1 (table $1) (i32.const 0) func $1 $1 $1) - -;; CHECK-NODEBUG: (func $0 -;; CHECK-NODEBUG-NEXT: (nop) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $1 -;; CHECK-NODEBUG-NEXT: (drop -;; CHECK-NODEBUG-NEXT: (table.get $0 -;; CHECK-NODEBUG-NEXT: (i32.const 0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (drop -;; CHECK-NODEBUG-NEXT: (table.get $1 -;; CHECK-NODEBUG-NEXT: (i32.const 100) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $2 -;; CHECK-NODEBUG-NEXT: (table.set $0 -;; CHECK-NODEBUG-NEXT: (i32.const 0) -;; CHECK-NODEBUG-NEXT: (ref.func $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: (drop -;; CHECK-NODEBUG-NEXT: (table.get $0 -;; CHECK-NODEBUG-NEXT: (i32.const 0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $3 (result i32) -;; CHECK-NODEBUG-NEXT: (table.size $0) -;; CHECK-NODEBUG-NEXT: ) - -;; CHECK-NODEBUG: (func $4 (param $0 i32) (result i32) -;; CHECK-NODEBUG-NEXT: (table.grow $0 -;; CHECK-NODEBUG-NEXT: (ref.null func) -;; CHECK-NODEBUG-NEXT: (local.get $0) -;; CHECK-NODEBUG-NEXT: ) -;; CHECK-NODEBUG-NEXT: ) diff -Nru binaryen-108/test/lit/tail-call.wast binaryen-99/test/lit/tail-call.wast --- binaryen-108/test/lit/tail-call.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/tail-call.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. - -;; Check that tail calls are parsed, validated, and printed correctly - -;; RUN: foreach %s %t wasm-opt -all -S -o - | filecheck %s -;; RUN: foreach %s %t wasm-opt -all -S --nominal -o - | filecheck %s --check-prefix NOMNL - -(module - - ;; CHECK: (type $void (func)) - ;; NOMNL: (type $void (func_subtype func)) - (type $void (func)) - - ;; CHECK: (table $t 1 1 funcref) - ;; NOMNL: (table $t 1 1 funcref) - (table $t 1 1 funcref) - - ;; CHECK: (elem $e (i32.const 0) $foo) - ;; NOMNL: (elem $e (i32.const 0) $foo) - (elem $e (i32.const 0) $foo) - - ;; CHECK: (func $foo - ;; CHECK-NEXT: (return_call $bar) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $foo (type $void) - ;; NOMNL-NEXT: (return_call $bar) - ;; NOMNL-NEXT: ) - (func $foo - (return_call $bar) - ) - - ;; CHECK: (func $bar - ;; CHECK-NEXT: (return_call_indirect $t (type $void) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $bar (type $void) - ;; NOMNL-NEXT: (return_call_indirect $t (type $void) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $bar - (return_call_indirect (type $void) (i32.const 0)) - ) -) - -;; Check GC types and subtyping -(module - ;; CHECK: (type $return-B (func (result (ref $B)))) - ;; NOMNL: (type $return-B (func_subtype (result (ref $B)) func)) - (type $return-B (func (result (ref $B)))) - - ;; CHECK: (type $return-A (func (result (ref null $A)))) - ;; NOMNL: (type $return-A (func_subtype (result (ref null $A)) func)) - (type $return-A (func (result (ref null $A)))) - - ;; CHECK: (type $A (struct (field i32))) - ;; NOMNL: (type $A (struct_subtype (field i32) data)) - (type $A (struct i32)) - - ;; CHECK: (type $B (struct (field i32) (field i32))) - ;; NOMNL: (type $B (struct_subtype (field i32) (field i32) $A)) - (type $B (struct_subtype i32 i32 $A)) - - ;; CHECK: (table $t 1 1 funcref) - ;; NOMNL: (table $t 1 1 funcref) - (table $t 1 1 funcref) - - ;; CHECK: (elem $e (i32.const 0) $callee) - ;; NOMNL: (elem $e (i32.const 0) $callee) - (elem $e (i32.const 0) $callee) - - ;; CHECK: (func $caller (result (ref null $A)) - ;; CHECK-NEXT: (return_call $callee) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $caller (type $return-A) (result (ref null $A)) - ;; NOMNL-NEXT: (return_call $callee) - ;; NOMNL-NEXT: ) - (func $caller (type $return-A) - (return_call $callee) - ) - - ;; CHECK: (func $caller-indirect (result (ref $B)) - ;; CHECK-NEXT: (return_call_indirect $t (type $return-B) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $caller-indirect (type $return-B) (result (ref $B)) - ;; NOMNL-NEXT: (return_call_indirect $t (type $return-B) - ;; NOMNL-NEXT: (i32.const 0) - ;; NOMNL-NEXT: ) - ;; NOMNL-NEXT: ) - (func $caller-indirect (type $return-B) - (return_call_indirect $t (type $return-B) (i32.const 0)) - ) - - ;; CHECK: (func $callee (result (ref $B)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; NOMNL: (func $callee (type $return-B) (result (ref $B)) - ;; NOMNL-NEXT: (unreachable) - ;; NOMNL-NEXT: ) - (func $callee (type $return-B) - (unreachable) - ) -) diff -Nru binaryen-108/test/lit/validation/extended-const.wast binaryen-99/test/lit/validation/extended-const.wast --- binaryen-108/test/lit/validation/extended-const.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/validation/extended-const.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -;; Test that shared memory requires atomics - -;; RUN: not wasm-opt %s 2>&1 | filecheck %s --check-prefix NO-EXTENDED -;; RUN: wasm-opt %s --enable-extended-const -o - -S | filecheck %s --check-prefix EXTENDED - -;; NO-EXTENDED: unexpected false: global init must be valid -;; NO-EXTENDED: unexpected false: memory segment offset should be reasonable - -;; EXTENDED: (import "env" "global" (global $gimport$0 i32)) -;; EXTENDED: (global $1 i32 (i32.add -;; EXTENDED: (global.get $gimport$0) -;; EXTENDED: (i32.const 42) -;; EXTENDED: )) -;; EXTENDED: (data (i32.sub -;; EXTENDED: (global.get $gimport$0) -;; EXTENDED: (i32.const 10) -;; EXTENDED: ) "hello world") - -(module - (memory 1 1) - (import "env" "global" (global i32)) - (global i32 (i32.add (global.get 0) (i32.const 42))) - (data (i32.sub (global.get 0) (i32.const 10)) "hello world") -) diff -Nru binaryen-108/test/lit/validation/nn-tuples.wast binaryen-99/test/lit/validation/nn-tuples.wast --- binaryen-108/test/lit/validation/nn-tuples.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/validation/nn-tuples.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -;; Test for non-nullable types in tuples - -;; RUN: not wasm-opt -all %s 2>&1 | filecheck %s --check-prefix NO-NN-LOCALS -;; RUN: wasm-opt -all %s --enable-gc-nn-locals -o - -S | filecheck %s --check-prefix NN-LOCALS - -;; NO-NN-LOCALS: vars must be defaultable - -;; NN-LOCALS: (module -;; NN-LOCALS: (local $tuple ((ref any) (ref any))) -;; NN-LOCALS: (nop) -;; NN-LOCALS: ) - -(module - (func $foo - (local $tuple ((ref any) (ref any))) - ) -) diff -Nru binaryen-108/test/lit/wasm-emscripten-finalize/em_asm_partial.wat binaryen-99/test/lit/wasm-emscripten-finalize/em_asm_partial.wat --- binaryen-108/test/lit/wasm-emscripten-finalize/em_asm_partial.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-emscripten-finalize/em_asm_partial.wat 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -;; Test that em_asm string are extraced correctly when the __start_em_asm -;; and __stop_em_asm globals are exported. - -;; RUN: wasm-emscripten-finalize %s -S | filecheck %s - -;; Check for the case when __start_em_asm and __stop_em_asm don't define an -;; entire segment. In this case we preserve the segment but zero the data. - -;; CHECK: (data (i32.const 512) "xx\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00yy") - -;; CHECK: "asmConsts": { -;; CHECK-NEXT: "514": "{ console.log('JS hello'); }", -;; CHECK-NEXT: "543": "{ console.log('hello again'); }" -;; CHECK-NEXT: }, - -;; Check that the exports are removed -;; CHECK-NOT: export - -(module - (memory 1 1) - (global (export "__start_em_asm") i32 (i32.const 514)) - (global (export "__stop_em_asm") i32 (i32.const 575)) - (data (i32.const 512) "xx{ console.log('JS hello'); }\00{ console.log('hello again'); }\00yy") -) diff -Nru binaryen-108/test/lit/wasm-emscripten-finalize/em_asm.wat binaryen-99/test/lit/wasm-emscripten-finalize/em_asm.wat --- binaryen-108/test/lit/wasm-emscripten-finalize/em_asm.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-emscripten-finalize/em_asm.wat 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -;; Test that em_asm string are extracted correctly when the __start_em_asm -;; and __stop_em_asm globals are exported. - -;; RUN: wasm-emscripten-finalize %s -S | filecheck %s - -;; Check that the data segment that contains only EM_ASM strings resized to -;; zero, and that the string are extracted into the metadata. - -;; CHECK: (data (i32.const 100) "normal data") -;; CHECK-NEXT: (data (i32.const 512) "") -;; CHECK-NEXT: (data (i32.const 1024) "more data") - -;; CHECK: "asmConsts": { -;; CHECK-NEXT: "512": "{ console.log('JS hello'); }", -;; CHECK-NEXT: "541": "{ console.log('hello again'); }" -;; CHECK-NEXT: }, - -;; Check that the exports are removed -;; CHECK-NOT: export - -(module - (memory 1 1) - (global (export "__start_em_asm") i32 (i32.const 512)) - (global (export "__stop_em_asm") i32 (i32.const 573)) - - (data (i32.const 100) "normal data") - (data (i32.const 512) "{ console.log('JS hello'); }\00{ console.log('hello again'); }\00") - (data (i32.const 1024) "more data") -) diff -Nru binaryen-108/test/lit/wasm-emscripten-finalize/em_js.wat binaryen-99/test/lit/wasm-emscripten-finalize/em_js.wat --- binaryen-108/test/lit/wasm-emscripten-finalize/em_js.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-emscripten-finalize/em_js.wat 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -;; Test that funcions exported with __em_js are correctly removed -;; once they strings they return are extracted. - -;; RUN: wasm-emscripten-finalize %s -S | filecheck %s - -;; All functions should be stripped from the binary, regardless -;; of internal name -;; CHECK-NOT: (global - -;; The data section that contains only em_js strings should -;; be stripped (shrunk to zero size): -;; CHECK: (data (i32.const 1024) "some JS string data\00xxx") -;; CHECK: (data (i32.const 512) "") -;; CHECK: (data (i32.const 2048) "more JS string data\00yyy") - -;; CHECK: "emJsFuncs": { -;; CHECK-NEXT: "bar": "more JS string data", -;; CHECK-NEXT: "baz": "Only em_js strings here", -;; CHECK-NEXT: "foo": "some JS string data" -;; CHECK-NEXT: }, - -(module - (memory 1 1) - (data (i32.const 1024) "some JS string data\00xxx") - (data (i32.const 512) "Only em_js strings here\00") - (data (i32.const 2048) "more JS string data\00yyy") - (export "__em_js__foo" (global $__em_js__foo)) - (export "__em_js__bar" (global $bar)) - (export "__em_js__baz" (global $baz)) - ;; Name matches export name - (global $__em_js__foo i32 (i32.const 1024)) - ;; Name does not match export name - (global $bar i32 (i32.const 2048)) - (global $baz i32 (i32.const 512)) -) diff -Nru binaryen-108/test/lit/wasm-emscripten-finalize/passive-pic.wat binaryen-99/test/lit/wasm-emscripten-finalize/passive-pic.wat --- binaryen-108/test/lit/wasm-emscripten-finalize/passive-pic.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-emscripten-finalize/passive-pic.wat 2021-01-07 20:01:06.000000000 +0000 @@ -4,16 +4,14 @@ ;; RUN: wasm-emscripten-finalize --enable-bulk-memory %s -o out.wasm | filecheck %s ;; CHECK: "asmConsts": { -;; CHECK: "3": "hello" +;; CHECK: "3": ["hello", ["iii"], [""]] ;; CHECK: }, (module (import "env" "memory" (memory $memory 1 1)) (import "env" "__memory_base" (global $__memory_base i32)) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) - (data "xxxhello\00yyy") - (global (export "__start_em_asm") i32 (i32.const 3)) - (global (export "__stop_em_asm") i32 (i32.const 9)) + (data passive "xxxhello\00yyy") ;; memory init function similar to those generated by wasm-ld (start $__wasm_init_memory) (func $__wasm_init_memory diff -Nru binaryen-108/test/lit/wasm-split/asyncify.wast binaryen-99/test/lit/wasm-split/asyncify.wast --- binaryen-108/test/lit/wasm-split/asyncify.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/asyncify.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,174 +0,0 @@ -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.1.wasm -o2 %t.2.wasm --keep-funcs=foo --asyncify -;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY -;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY - -;; Check that the --asyncify option instruments the primary module but not the -;; secondary module. - -(module - (func $foo (param i32) (result i32) - (call $bar (i32.const 0)) - ) - (func $bar (param i32) (result i32) - (call $foo (i32.const 1)) - ) -) - -;; PRIMARY: (module -;; PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; PRIMARY-NEXT: (type $i32_=>_none (func (param i32))) -;; PRIMARY-NEXT: (type $none_=>_none (func)) -;; PRIMARY-NEXT: (type $none_=>_i32 (func (result i32))) -;; PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) -;; PRIMARY-NEXT: (global $global$0 (mut i32) (i32.const 0)) -;; PRIMARY-NEXT: (global $global$1 (mut i32) (i32.const 0)) -;; PRIMARY-NEXT: (memory $0 1 1) -;; PRIMARY-NEXT: (table $0 1 funcref) -;; PRIMARY-NEXT: (elem (i32.const 0) $placeholder_0) -;; PRIMARY-NEXT: (export "%foo" (func $foo)) -;; PRIMARY-NEXT: (export "%table" (table $0)) -;; PRIMARY-NEXT: (export "asyncify_start_unwind" (func $asyncify_start_unwind)) -;; PRIMARY-NEXT: (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) -;; PRIMARY-NEXT: (export "asyncify_start_rewind" (func $asyncify_start_rewind)) -;; PRIMARY-NEXT: (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) -;; PRIMARY-NEXT: (export "asyncify_get_state" (func $asyncify_get_state)) -;; PRIMARY-NEXT: (func $foo (param $0 i32) (result i32) -;; PRIMARY-NEXT: (local $1 i32) -;; PRIMARY-NEXT: (if -;; PRIMARY-NEXT: (i32.eq -;; PRIMARY-NEXT: (global.get $global$0) -;; PRIMARY-NEXT: (i32.const 2) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (block -;; PRIMARY-NEXT: (i32.store -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: (i32.sub -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.const 4) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (local.set $0 -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (local.set $1 -;; PRIMARY-NEXT: (block $label$2 (result i32) -;; PRIMARY-NEXT: (if -;; PRIMARY-NEXT: (i32.eqz -;; PRIMARY-NEXT: (select -;; PRIMARY-NEXT: (if (result i32) -;; PRIMARY-NEXT: (i32.eq -;; PRIMARY-NEXT: (global.get $global$0) -;; PRIMARY-NEXT: (i32.const 2) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (block (result i32) -;; PRIMARY-NEXT: (i32.store -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: (i32.sub -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.const 4) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (local.get $1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.const 0) -;; PRIMARY-NEXT: (global.get $global$0) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (block -;; PRIMARY-NEXT: (local.set $1 -;; PRIMARY-NEXT: (call_indirect (type $i32_=>_i32) -;; PRIMARY-NEXT: (i32.const 0) -;; PRIMARY-NEXT: (i32.const 0) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (drop -;; PRIMARY-NEXT: (br_if $label$2 -;; PRIMARY-NEXT: (i32.const 0) -;; PRIMARY-NEXT: (i32.eq -;; PRIMARY-NEXT: (global.get $global$0) -;; PRIMARY-NEXT: (i32.const 1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (local.set $0 -;; PRIMARY-NEXT: (local.get $1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (if -;; PRIMARY-NEXT: (i32.eqz -;; PRIMARY-NEXT: (global.get $global$0) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (return -;; PRIMARY-NEXT: (local.get $0) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (unreachable) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.store -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (local.get $1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.store -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: (i32.add -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.const 4) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.store -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (local.get $0) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.store -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: (i32.add -;; PRIMARY-NEXT: (i32.load -;; PRIMARY-NEXT: (global.get $global$1) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.const 4) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (i32.const 0) -;; PRIMARY-NEXT: ) -;; PRIMARY: (func $asyncify_start_unwind (param $0 i32) -;; PRIMARY: (func $asyncify_stop_unwind -;; PRIMARY: (func $asyncify_start_rewind (param $0 i32) -;; PRIMARY: (func $asyncify_stop_rewind -;; PRIMARY: (func $asyncify_get_state (result i32) -;; PRIMARY: ) - -;; SECONDARY: (module -;; SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 funcref)) -;; SECONDARY-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) -;; SECONDARY-NEXT: (elem (i32.const 0) $bar) -;; SECONDARY-NEXT: (func $bar (param $0 i32) (result i32) -;; SECONDARY-NEXT: (call $foo -;; SECONDARY-NEXT: (i32.const 1) -;; SECONDARY-NEXT: ) -;; SECONDARY-NEXT: ) -;; SECONDARY-NEXT: ) diff -Nru binaryen-108/test/lit/wasm-split/bar.txt binaryen-99/test/lit/wasm-split/bar.txt --- binaryen-108/test/lit/wasm-split/bar.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/bar.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -bar diff -Nru binaryen-108/test/lit/wasm-split/basic.wast binaryen-99/test/lit/wasm-split/basic.wast --- binaryen-108/test/lit/wasm-split/basic.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/basic.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,52 +1,23 @@ -;; RUN: not wasm-split %s --export-prefix='%' -g -o1 %t.none.1.wasm -o2 %t.none.2.wasm --keep-funcs=@failed-to-open.txt -v 2>&1 \ -;; RUN: | filecheck %s --check-prefix FAILED-TO-OPEN - -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.none.1.wasm -o2 %t.none.2.wasm -v 2>&1 \ -;; RUN: | filecheck %s --check-prefix KEEP-NONE -;; RUN: wasm-dis %t.none.1.wasm | filecheck %s --check-prefix KEEP-NONE-PRIMARY -;; RUN: wasm-dis %t.none.2.wasm | filecheck %s --check-prefix KEEP-NONE-SECONDARY - -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.none.1.wasm -o2 %t.none.2.wasm --keep-funcs=@%S/none.txt -v 2>&1 \ +;; RUN: wasm-split %s --export-prefix='%' -o1 %t.none.1.wasm -o2 %t.none.2.wasm -v 2>&1 \ ;; RUN: | filecheck %s --check-prefix KEEP-NONE ;; RUN: wasm-dis %t.none.1.wasm | filecheck %s --check-prefix KEEP-NONE-PRIMARY ;; RUN: wasm-dis %t.none.2.wasm | filecheck %s --check-prefix KEEP-NONE-SECONDARY -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm --keep-funcs=foo -v 2>&1 \ +;; RUN: wasm-split %s --export-prefix='%' -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm --keep-funcs=foo -v 2>&1 \ ;; RUN: | filecheck %s --check-prefix KEEP-FOO ;; RUN: wasm-dis %t.foo.1.wasm | filecheck %s --check-prefix KEEP-FOO-PRIMARY ;; RUN: wasm-dis %t.foo.2.wasm | filecheck %s --check-prefix KEEP-FOO-SECONDARY -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm --keep-funcs=@%S/foo.txt -v 2>&1 \ -;; RUN: | filecheck %s --check-prefix KEEP-FOO -;; RUN: wasm-dis %t.foo.1.wasm | filecheck %s --check-prefix KEEP-FOO-PRIMARY -;; RUN: wasm-dis %t.foo.2.wasm | filecheck %s --check-prefix KEEP-FOO-SECONDARY - -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm --keep-funcs=bar -v 2>&1 \ -;; RUN: | filecheck %s --check-prefix KEEP-BAR -;; RUN: wasm-dis %t.bar.1.wasm | filecheck %s --check-prefix KEEP-BAR-PRIMARY -;; RUN: wasm-dis %t.bar.2.wasm | filecheck %s --check-prefix KEEP-BAR-SECONDARY - -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm --keep-funcs=@%S/bar.txt -v 2>&1 \ +;; RUN: wasm-split %s --export-prefix='%' -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm --keep-funcs=bar -v 2>&1 \ ;; RUN: | filecheck %s --check-prefix KEEP-BAR ;; RUN: wasm-dis %t.bar.1.wasm | filecheck %s --check-prefix KEEP-BAR-PRIMARY ;; RUN: wasm-dis %t.bar.2.wasm | filecheck %s --check-prefix KEEP-BAR-SECONDARY -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.both.1.wasm -o2 %t.both.2.wasm --keep-funcs=foo,bar -v 2>&1 \ -;; RUN: | filecheck %s --check-prefix KEEP-BOTH -;; RUN: wasm-dis %t.both.1.wasm | filecheck %s --check-prefix KEEP-BOTH-PRIMARY -;; RUN: wasm-dis %t.both.2.wasm | filecheck %s --check-prefix KEEP-BOTH-SECONDARY - -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.both.1.wasm -o2 %t.both.2.wasm --keep-funcs=@%S/both.txt -v 2>&1 \ +;; RUN: wasm-split %s --export-prefix='%' -o1 %t.both.1.wasm -o2 %t.both.2.wasm --keep-funcs=foo,bar -v 2>&1 \ ;; RUN: | filecheck %s --check-prefix KEEP-BOTH ;; RUN: wasm-dis %t.both.1.wasm | filecheck %s --check-prefix KEEP-BOTH-PRIMARY ;; RUN: wasm-dis %t.both.2.wasm | filecheck %s --check-prefix KEEP-BOTH-SECONDARY -;; Also check the inverse workflow using --keep-all and --split-funcs -;; RUN: wasm-split %s --export-prefix='%' -g -o1 %t.split-bar.1.wasm -o2 %t.split-bar.2.wasm --split-funcs=bar -v 2>&1 \ -;; RUN: | filecheck %s --check-prefix KEEP-FOO -;; RUN: wasm-dis %t.split-bar.1.wasm | filecheck %s --check-prefix KEEP-FOO-PRIMARY -;; RUN: wasm-dis %t.split-bar.2.wasm | filecheck %s --check-prefix KEEP-FOO-SECONDARY - (module (table $table 1 1 funcref) (elem (i32.const 0) $foo) @@ -58,29 +29,27 @@ ) ) -;; FAILED-TO-OPEN: Failed opening 'failed-to-open.txt' - ;; KEEP-NONE: warning: not keeping any functions in the primary module ;; KEEP-NONE-PRIMARY: (module ;; KEEP-NONE-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-NONE-PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) -;; KEEP-NONE-PRIMARY-NEXT: (table $table 1 1 funcref) -;; KEEP-NONE-PRIMARY-NEXT: (elem (i32.const 0) $placeholder_0) -;; KEEP-NONE-PRIMARY-NEXT: (export "%table" (table $table)) +;; KEEP-NONE-PRIMARY-NEXT: (import "placeholder" "0" (func $fimport$0 (param i32) (result i32))) +;; KEEP-NONE-PRIMARY-NEXT: (table $0 1 1 funcref) +;; KEEP-NONE-PRIMARY-NEXT: (elem (i32.const 0) $fimport$0) +;; KEEP-NONE-PRIMARY-NEXT: (export "%table" (table $0)) ;; KEEP-NONE-PRIMARY-NEXT: ) ;; KEEP-NONE-SECONDARY: (module ;; KEEP-NONE-SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-NONE-SECONDARY-NEXT: (import "primary" "%table" (table $table 1 1 funcref)) -;; KEEP-NONE-SECONDARY-NEXT: (elem (i32.const 0) $foo) -;; KEEP-NONE-SECONDARY-NEXT: (func $bar (param $0 i32) (result i32) -;; KEEP-NONE-SECONDARY-NEXT: (call $foo +;; KEEP-NONE-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 1 funcref)) +;; KEEP-NONE-SECONDARY-NEXT: (elem (i32.const 0) $1) +;; KEEP-NONE-SECONDARY-NEXT: (func $0 (param $0 i32) (result i32) +;; KEEP-NONE-SECONDARY-NEXT: (call $1 ;; KEEP-NONE-SECONDARY-NEXT: (i32.const 1) ;; KEEP-NONE-SECONDARY-NEXT: ) ;; KEEP-NONE-SECONDARY-NEXT: ) -;; KEEP-NONE-SECONDARY-NEXT: (func $foo (param $0 i32) (result i32) -;; KEEP-NONE-SECONDARY-NEXT: (call $bar +;; KEEP-NONE-SECONDARY-NEXT: (func $1 (param $0 i32) (result i32) +;; KEEP-NONE-SECONDARY-NEXT: (call $0 ;; KEEP-NONE-SECONDARY-NEXT: (i32.const 0) ;; KEEP-NONE-SECONDARY-NEXT: ) ;; KEEP-NONE-SECONDARY-NEXT: ) @@ -91,12 +60,12 @@ ;; KEEP-FOO-PRIMARY: (module ;; KEEP-FOO-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-FOO-PRIMARY-NEXT: (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32))) -;; KEEP-FOO-PRIMARY-NEXT: (table $table 2 2 funcref) -;; KEEP-FOO-PRIMARY-NEXT: (elem (i32.const 0) $foo $placeholder_1) -;; KEEP-FOO-PRIMARY-NEXT: (export "%foo" (func $foo)) -;; KEEP-FOO-PRIMARY-NEXT: (export "%table" (table $table)) -;; KEEP-FOO-PRIMARY-NEXT: (func $foo (param $0 i32) (result i32) +;; KEEP-FOO-PRIMARY-NEXT: (import "placeholder" "1" (func $fimport$0 (param i32) (result i32))) +;; KEEP-FOO-PRIMARY-NEXT: (table $0 2 2 funcref) +;; KEEP-FOO-PRIMARY-NEXT: (elem (i32.const 0) $0 $fimport$0) +;; KEEP-FOO-PRIMARY-NEXT: (export "%foo" (func $0)) +;; KEEP-FOO-PRIMARY-NEXT: (export "%table" (table $0)) +;; KEEP-FOO-PRIMARY-NEXT: (func $0 (param $0 i32) (result i32) ;; KEEP-FOO-PRIMARY-NEXT: (call_indirect (type $i32_=>_i32) ;; KEEP-FOO-PRIMARY-NEXT: (i32.const 0) ;; KEEP-FOO-PRIMARY-NEXT: (i32.const 1) @@ -106,11 +75,11 @@ ;; KEEP-FOO-SECONDARY: (module ;; KEEP-FOO-SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%table" (table $table 2 2 funcref)) -;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%foo" (func $foo (param i32) (result i32))) -;; KEEP-FOO-SECONDARY-NEXT: (elem (i32.const 1) $bar) -;; KEEP-FOO-SECONDARY-NEXT: (func $bar (param $0 i32) (result i32) -;; KEEP-FOO-SECONDARY-NEXT: (call $foo +;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 2 2 funcref)) +;; KEEP-FOO-SECONDARY-NEXT: (elem (i32.const 1) $0) +;; KEEP-FOO-SECONDARY-NEXT: (import "primary" "%foo" (func $fimport$0 (param i32) (result i32))) +;; KEEP-FOO-SECONDARY-NEXT: (func $0 (param $0 i32) (result i32) +;; KEEP-FOO-SECONDARY-NEXT: (call $fimport$0 ;; KEEP-FOO-SECONDARY-NEXT: (i32.const 1) ;; KEEP-FOO-SECONDARY-NEXT: ) ;; KEEP-FOO-SECONDARY-NEXT: ) @@ -121,12 +90,12 @@ ;; KEEP-BAR-PRIMARY: (module ;; KEEP-BAR-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-BAR-PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32))) -;; KEEP-BAR-PRIMARY-NEXT: (table $table 1 1 funcref) -;; KEEP-BAR-PRIMARY-NEXT: (elem (i32.const 0) $placeholder_0) -;; KEEP-BAR-PRIMARY-NEXT: (export "%bar" (func $bar)) -;; KEEP-BAR-PRIMARY-NEXT: (export "%table" (table $table)) -;; KEEP-BAR-PRIMARY-NEXT: (func $bar (param $0 i32) (result i32) +;; KEEP-BAR-PRIMARY-NEXT: (import "placeholder" "0" (func $fimport$0 (param i32) (result i32))) +;; KEEP-BAR-PRIMARY-NEXT: (table $0 1 1 funcref) +;; KEEP-BAR-PRIMARY-NEXT: (elem (i32.const 0) $fimport$0) +;; KEEP-BAR-PRIMARY-NEXT: (export "%bar" (func $0)) +;; KEEP-BAR-PRIMARY-NEXT: (export "%table" (table $0)) +;; KEEP-BAR-PRIMARY-NEXT: (func $0 (param $0 i32) (result i32) ;; KEEP-BAR-PRIMARY-NEXT: (call_indirect (type $i32_=>_i32) ;; KEEP-BAR-PRIMARY-NEXT: (i32.const 1) ;; KEEP-BAR-PRIMARY-NEXT: (i32.const 0) @@ -136,11 +105,11 @@ ;; KEEP-BAR-SECONDARY: (module ;; KEEP-BAR-SECONDARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%table" (table $table 1 1 funcref)) -;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%bar" (func $bar (param i32) (result i32))) -;; KEEP-BAR-SECONDARY-NEXT: (elem (i32.const 0) $foo) -;; KEEP-BAR-SECONDARY-NEXT: (func $foo (param $0 i32) (result i32) -;; KEEP-BAR-SECONDARY-NEXT: (call $bar +;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 1 funcref)) +;; KEEP-BAR-SECONDARY-NEXT: (elem (i32.const 0) $0) +;; KEEP-BAR-SECONDARY-NEXT: (import "primary" "%bar" (func $fimport$0 (param i32) (result i32))) +;; KEEP-BAR-SECONDARY-NEXT: (func $0 (param $0 i32) (result i32) +;; KEEP-BAR-SECONDARY-NEXT: (call $fimport$0 ;; KEEP-BAR-SECONDARY-NEXT: (i32.const 0) ;; KEEP-BAR-SECONDARY-NEXT: ) ;; KEEP-BAR-SECONDARY-NEXT: ) @@ -148,25 +117,25 @@ ;; KEEP-BOTH: warning: not splitting any functions out to the secondary module ;; KEEP-BOTH-NEXT: Keeping functions: bar, foo{{$}} -;; KEEP-BOTH-NEXT: Splitting out functions: {{$}} +;; KEEP-BOTH-NEXT: Splitting out functions:{{$}} ;; KEEP-BOTH-PRIMARY: (module ;; KEEP-BOTH-PRIMARY-NEXT: (type $i32_=>_i32 (func (param i32) (result i32))) -;; KEEP-BOTH-PRIMARY-NEXT: (table $table 1 1 funcref) -;; KEEP-BOTH-PRIMARY-NEXT: (elem (i32.const 0) $foo) -;; KEEP-BOTH-PRIMARY-NEXT: (export "%table" (table $table)) -;; KEEP-BOTH-PRIMARY-NEXT: (func $foo (param $0 i32) (result i32) -;; KEEP-BOTH-PRIMARY-NEXT: (call $bar +;; KEEP-BOTH-PRIMARY-NEXT: (table $0 1 1 funcref) +;; KEEP-BOTH-PRIMARY-NEXT: (elem (i32.const 0) $0) +;; KEEP-BOTH-PRIMARY-NEXT: (export "%table" (table $0)) +;; KEEP-BOTH-PRIMARY-NEXT: (func $0 (param $0 i32) (result i32) +;; KEEP-BOTH-PRIMARY-NEXT: (call $1 ;; KEEP-BOTH-PRIMARY-NEXT: (i32.const 0) ;; KEEP-BOTH-PRIMARY-NEXT: ) ;; KEEP-BOTH-PRIMARY-NEXT: ) -;; KEEP-BOTH-PRIMARY-NEXT: (func $bar (param $0 i32) (result i32) -;; KEEP-BOTH-PRIMARY-NEXT: (call $foo +;; KEEP-BOTH-PRIMARY-NEXT: (func $1 (param $0 i32) (result i32) +;; KEEP-BOTH-PRIMARY-NEXT: (call $0 ;; KEEP-BOTH-PRIMARY-NEXT: (i32.const 1) ;; KEEP-BOTH-PRIMARY-NEXT: ) ;; KEEP-BOTH-PRIMARY-NEXT: ) ;; KEEP-BOTH-PRIMARY-NEXT: ) ;; KEEP-BOTH-SECONDARY: (module -;; KEEP-BOTH-SECONDARY-NEXT: (import "primary" "%table" (table $table 1 1 funcref)) +;; KEEP-BOTH-SECONDARY-NEXT: (import "primary" "%table" (table $timport$0 1 1 funcref)) ;; KEEP-BOTH-SECONDARY-NEXT: ) diff -Nru binaryen-108/test/lit/wasm-split/both.txt binaryen-99/test/lit/wasm-split/both.txt --- binaryen-108/test/lit/wasm-split/both.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/both.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -foo -bar diff -Nru binaryen-108/test/lit/wasm-split/call_exports.mjs binaryen-99/test/lit/wasm-split/call_exports.mjs --- binaryen-108/test/lit/wasm-split/call_exports.mjs 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/call_exports.mjs 2021-01-07 20:01:06.000000000 +0000 @@ -20,6 +20,6 @@ } // Create and read the profile -let profileSize = instance.exports['__write_profile'](1024, 2**32 - 1024); -let profileData = Buffer.from(instance.exports.memory.buffer, 1024, profileSize); +let profileSize = instance.exports['__write_profile'](0, 2**32 - 1); +let profileData = Buffer.from(instance.exports.memory.buffer, 0, profileSize); fs.writeFileSync(outFile, profileData); diff -Nru binaryen-108/test/lit/wasm-split/foo.txt binaryen-99/test/lit/wasm-split/foo.txt --- binaryen-108/test/lit/wasm-split/foo.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/foo.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -foo diff -Nru binaryen-108/test/lit/wasm-split/imported-memory.wast binaryen-99/test/lit/wasm-split/imported-memory.wast --- binaryen-108/test/lit/wasm-split/imported-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/imported-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -;; RUN: wasm-split --instrument %s -all -S -o - | filecheck %s - -;; Check that an imported memory is not exported as "profile-memory" - -(module - (import "env" "mem" (memory $mem 1 1)) -) - -;; CHECK: (import "env" "mem" (memory $mem 1 1)) -;; CHECK: (export "__write_profile" (func $__write_profile)) - -;; CHECK-NOT: (export "profile-memory" (memory $mem)) diff -Nru binaryen-108/test/lit/wasm-split/instrument-funcs.wast binaryen-99/test/lit/wasm-split/instrument-funcs.wast --- binaryen-108/test/lit/wasm-split/instrument-funcs.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/instrument-funcs.wast 2021-01-07 20:01:06.000000000 +0000 @@ -15,20 +15,17 @@ ) ) +;; Check that a memory has been added +;; CHECK: (memory $0 1 1) + ;; Check that the counter and timestamps have been added ;; CHECK: (global $monotonic_counter (mut i32) (i32.const 0)) ;; CHECK: (global $bar_timestamp (mut i32) (i32.const 0)) ;; CHECK: (global $baz_timestamp (mut i32) (i32.const 0)) -;; Check that a memory has been added -;; CHECK: (memory $0 1 1) - -;; And the profiling function is exported +;; And the profiling function exported ;; CHECK: (export "__write_profile" (func $__write_profile)) -;; And the memory has been exported -;; CHECK: (export "profile-memory" (memory $0)) - ;; Check that the function instrumentation is correct ;; CHECK: (func $baz (param $0 i32) (result i32) diff -Nru binaryen-108/test/lit/wasm-split/instrument-in-memory.wast binaryen-99/test/lit/wasm-split/instrument-in-memory.wast --- binaryen-108/test/lit/wasm-split/instrument-in-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/instrument-in-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -;; RUN: wasm-split %s --instrument --in-memory -all -S -o - | filecheck %s - -;; Check that the output round trips and validates as well -;; RUN: wasm-split %s --instrument --in-memory -all -g -o %t.wasm -;; RUN: wasm-opt -all %t.wasm -S -o - - -(module - (import "env" "foo" (func $foo)) - (export "bar" (func $bar)) - (func $bar - (call $foo) - ) - (func $baz (param i32) (result i32) - (local.get 0) - ) -) - -;; Check that a memory has been added -;; CHECK: (memory $0 1 1) - -;; And the profiling function exported -;; CHECK: (export "__write_profile" (func $__write_profile)) - -;; Check that the function instrumentation is correct - -;; CHECK: (func $bar -;; CHECK-NEXT: (i32.atomic.store8 -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (call $foo) -;; CHECK-NEXT: ) - -;; CHECK-NEXT: (func $baz (param $0 i32) (result i32) -;; CHECK-NEXT: (i32.atomic.store8 offset=1 -;; CHECK-NEXT: (i32.const 0) -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) - -;; Check that the profiling function is correct. - -;; CHECK: (func $__write_profile (param $addr i32) (param $size i32) (result i32) -;; CHECK-NEXT: (local $funcIdx i32) -;; CHECK-NEXT: (if -;; CHECK-NEXT: (i32.ge_u -;; CHECK-NEXT: (local.get $size) -;; CHECK-NEXT: (i32.const 16) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block -;; CHECK-NEXT: (i64.store align=1 -;; CHECK-NEXT: (local.get $addr) -;; CHECK-NEXT: (i64.const {{.*}}) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (block $outer -;; CHECK-NEXT: (loop $l -;; CHECK-NEXT: (br_if $outer -;; CHECK-NEXT: (i32.eq -;; CHECK-NEXT: (local.get $funcIdx) -;; CHECK-NEXT: (i32.const 2) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.store offset=8 -;; CHECK-NEXT: (i32.add -;; CHECK-NEXT: (local.get $addr) -;; CHECK-NEXT: (i32.mul -;; CHECK-NEXT: (local.get $funcIdx) -;; CHECK-NEXT: (i32.const 4) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.atomic.load8_u -;; CHECK-NEXT: (local.get $funcIdx) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (local.set $funcIdx -;; CHECK-NEXT: (i32.add -;; CHECK-NEXT: (local.get $funcIdx) -;; CHECK-NEXT: (i32.const 1) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (br $l) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: ) -;; CHECK-NEXT: (i32.const 16) -;; CHECK-NEXT: ) diff -Nru binaryen-108/test/lit/wasm-split/invalid-options.wast binaryen-99/test/lit/wasm-split/invalid-options.wast --- binaryen-108/test/lit/wasm-split/invalid-options.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/invalid-options.wast 2021-01-07 20:01:06.000000000 +0000 @@ -13,10 +13,6 @@ ;; RUN: not wasm-split %s --instrument -o2 %t 2>&1 \ ;; RUN: | filecheck %s --check-prefix INSTRUMENT-OUT2 -;; --instrument cannot be used with --symbolmap -;; RUN: not wasm-split %s --instrument --symbolmap 2>&1 \ -;; RUN: | filecheck %s --check-prefix INSTRUMENT-SYMBOLMAP - ;; --instrument cannot be used with --import-namespace ;; RUN: not wasm-split %s --instrument --import-namespace=foo 2>&1 \ ;; RUN: | filecheck %s --check-prefix INSTRUMENT-IMPORT-NS @@ -39,62 +35,30 @@ ;; Split mode requires -o1 and -o2 rather than -o ;; RUN: not wasm-split %s -o %t 2>&1 \ -;; RUN: | filecheck %s --check-prefix SPLIT-OUT +;; RUN: | filecheck %s --check-prefix NO-INSTRUMENT-OUT ;; --instrument is required to use --profile-export ;; RUN: not wasm-split %s --profile-export=foo 2>&1 \ -;; RUN: | filecheck %s --check-prefix SPLIT-PROFILE-EXPORT - -;; -S cannot be used with --merge-profiles -;; RUN: not wasm-split %s --merge-profiles -S 2>&1 \ -;; RUN: | filecheck %s --check-prefix MERGE-EMIT-TEXT - -;; -g cannot be used with --merge-profiles -;; RUN: not wasm-split %s --merge-profiles -g 2>&1 \ -;; RUN: | filecheck %s --check-prefix MERGE-DEBUGINFO - -;; --profile cannot be used with --keep-funcs -;; RUN: not wasm-split %s --profile=foo --keep-funcs=foo 2>&1 \ -;; RUN: | filecheck %s --check-prefix PROFILE-KEEP - -;; --profile cannot be used with --split-funcs -;; RUN: not wasm-split %s --profile=foo --split-funcs=foo 2>&1 \ -;; RUN: | filecheck %s --check-prefix PROFILE-SPLIT - -;; --keep-funcs cannot be used with --split-funcs -;; RUN: not wasm-split %s --keep-funcs=foo --split-funcs=foo 2>&1 \ -;; RUN: | filecheck %s --check-prefix KEEP-SPLIT - -;; INSTRUMENT-PROFILE: error: Option --profile cannot be used in instrument mode. - -;; INSTRUMENT-OUT1: error: Option --primary-output cannot be used in instrument mode. - -;; INSTRUMENT-OUT2: error: Option --secondary-output cannot be used in instrument mode. - -;; INSTRUMENT-SYMBOLMAP: error: Option --symbolmap cannot be used in instrument mode. - -;; INSTRUMENT-IMPORT-NS: error: Option --import-namespace cannot be used in instrument mode. - -;; INSTRUMENT-PLACEHOLDER-NS: error: Option --placeholder-namespace cannot be used in instrument mode. +;; RUN: | filecheck %s --check-prefix NO-INSTRUMENT-PROFILE-EXPORT -;; INSTRUMENT-EXPORT-PREFIX: error: Option --export-prefix cannot be used in instrument mode. +;; INSTRUMENT-PROFILE: error: --profile cannot be used with --instrument -;; INSTRUMENT-KEEP-FUNCS: error: Option --keep-funcs cannot be used in instrument mode. +;; INSTRUMENT-OUT1: error: primary output cannot be used with --instrument -;; INSTRUMENT-SPLIT-FUNCS: error: Option --split-funcs cannot be used in instrument mode. +;; INSTRUMENT-OUT2: error: secondary output cannot be used with --instrument -;; SPLIT-OUT: error: Option --output cannot be used in split mode. +;; INSTRUMENT-IMPORT-NS: error: --import-namespace cannot be used with --instrument -;; SPLIT-PROFILE-EXPORT: error: Option --profile-export cannot be used in split mode. +;; INSTRUMENT-PLACEHOLDER-NS: error: --placeholder-namespace cannot be used with --instrument -;; MERGE-EMIT-TEXT: error: Option --emit-text cannot be used in merge-profiles mode. +;; INSTRUMENT-EXPORT-PREFIX: error: --export-prefix cannot be used with --instrument -;; MERGE-DEBUGINFO: error: Option --debuginfo cannot be used in merge-profiles mode. +;; INSTRUMENT-KEEP-FUNCS: error: --keep-funcs cannot be used with --instrument -;; PROFILE-KEEP: error: Cannot use both --profile and --keep-funcs. +;; INSTRUMENT-SPLIT-FUNCS: error: --split-funcs cannot be used with --instrument -;; PROFILE-SPLIT: error: Cannot use both --profile and --split-funcs. +;; NO-INSTRUMENT-OUT: error: must provide separate primary and secondary output with -o1 and -o2 -;; KEEP-SPLIT: error: Cannot use both --keep-funcs and --split-funcs. +;; NO-INSTRUMENT-PROFILE-EXPORT: error: --profile-export must be used with --instrument (module) diff -Nru binaryen-108/test/lit/wasm-split/merge-profiles.wast binaryen-99/test/lit/wasm-split/merge-profiles.wast --- binaryen-108/test/lit/wasm-split/merge-profiles.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/merge-profiles.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -;; Instrument the module -;; RUN: wasm-split --instrument %s -o %t.instrumented.wasm -g - -;; Generate profiles -;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.foo.prof foo -;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.foo.bar.prof foo bar -;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.bar.baz.prof bar baz - -;; Merge profiles -;; RUN: wasm-split --merge-profiles -v %t.foo.prof %t.foo.bar.prof %t.bar.baz.prof -o %t.merged.prof 2>&1 \ -;; RUN: | filecheck %s --check-prefix MERGE - -;; Split the module -;; RUN: wasm-split %s --profile %t.merged.prof -o1 %t.1.wasm -o2 %t.2.wasm -g -v \ -;; RUN: | filecheck %s --check-prefix SPLIT - -;; MERGE: Profile {{.*}}foo.prof only includes functions included in other profiles. -;; MERGE: Profile {{.*}}foo.bar.prof only includes functions included in other profiles. -;; MERGE-NOT: Profile {{.*}}bar.baz.prof only includes functions included in other profiles. - -;; SPLIT: Keeping functions: bar, baz, foo{{$}} -;; SPLIT-NEXT: Splitting out functions: qux{{$}} - -(module - (export "memory" (memory 0 0)) - (export "foo" (func $foo)) - (export "bar" (func $bar)) - (export "baz" (func $baz)) - (export "qux" (func $qux)) - (func $foo - (nop) - ) - (func $bar - (nop) - ) - (func $baz - (nop) - ) - (func $qux - (nop) - ) -) diff -Nru binaryen-108/test/lit/wasm-split/minimized-exports.wast binaryen-99/test/lit/wasm-split/minimized-exports.wast --- binaryen-108/test/lit/wasm-split/minimized-exports.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/minimized-exports.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -;; RUN: wasm-split %s --keep-funcs=foo,bar --export-prefix='%' -o1 %t.1.wasm -o2 %t.2.wasm -;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY -;; RUN: wasm-dis %t.2.wasm | filecheck %s --check-prefix SECONDARY - -;; PRIMARY: (module -;; PRIMARY-NEXT: (type $none_=>_none (func)) -;; PRIMARY-NEXT: (export "%a" (func $1)) -;; PRIMARY-NEXT: (export "%b" (func $0)) -;; PRIMARY-NEXT: (func $0 -;; PRIMARY-NEXT: (nop) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: (func $1 -;; PRIMARY-NEXT: (nop) -;; PRIMARY-NEXT: ) -;; PRIMARY-NEXT: ) - -;; SECONDARY: (module -;; SECONDARY-NEXT: (type $none_=>_none (func)) -;; SECONDARY-NEXT: (import "primary" "%a" (func $fimport$0)) -;; SECONDARY-NEXT: (import "primary" "%b" (func $fimport$1)) -;; SECONDARY-NEXT: (func $0 -;; SECONDARY-NEXT: (call $fimport$1) -;; SECONDARY-NEXT: (call $fimport$0) -;; SECONDARY-NEXT: ) -;; SECONDARY-NEXT: ) - -(module - (func $foo - (nop) - ) - (func $bar - (nop) - ) - (func $baz - (call $foo) - (call $bar) - ) -) diff -Nru binaryen-108/test/lit/wasm-split/module-names.wast binaryen-99/test/lit/wasm-split/module-names.wast --- binaryen-108/test/lit/wasm-split/module-names.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/module-names.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -;; Check that --emit-module-names without -g strips function names but generates -;; and keeps the module names. - -;; RUN: wasm-split %s --keep-funcs=foo -o1 %t.primary.wasm -o2 %t.secondary.wasm --emit-module-names - -;; RUN: wasm-dis %t.primary.wasm -o - | filecheck %s --check-prefix=PRIMARY -;; RUN: wasm-dis %t.secondary.wasm -o - | filecheck %s --check-prefix=SECONDARY - -;; PRIMARY: (module $module-names.wast.tmp.primary.wasm -;; PRIMARY: (func $0 -;; PRIMARY-NOT: $foo - -;; SECONDARY: (module $module-names.wast.tmp.secondary.wasm -;; SECONDARY: (func $0 -;; SECONDARY-NOT: $bar - -(module - (func $foo - (nop) - ) - (func $bar - (nop) - ) -) diff -Nru binaryen-108/test/lit/wasm-split/none.txt binaryen-99/test/lit/wasm-split/none.txt --- binaryen-108/test/lit/wasm-split/none.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/none.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru binaryen-108/test/lit/wasm-split/placeholdermap.wast binaryen-99/test/lit/wasm-split/placeholdermap.wast --- binaryen-108/test/lit/wasm-split/placeholdermap.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/placeholdermap.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -;; RUN: wasm-split %s --keep-funcs=bar -o1 %t.1.wasm -o2 %t.2.wasm --placeholdermap -;; RUN: filecheck %s --check-prefix MAP < %t.1.wasm.placeholders -;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY - -;; MAP: 0:foo -;; MAP-NEXT: 2:baz -;; MAP-NOT: bar - -;; Check that the names have been stripped. -;; PRIMARY: (func $0 - -(module - (table $table 3 3 funcref) - (elem $table (i32.const 0) $foo $bar $baz) - (func $foo - (nop) - ) - (func $bar - (nop) - ) - (func $baz - (nop) - ) -) diff -Nru binaryen-108/test/lit/wasm-split/profile-guided.wast binaryen-99/test/lit/wasm-split/profile-guided.wast --- binaryen-108/test/lit/wasm-split/profile-guided.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/profile-guided.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,75 +1,43 @@ -;; ===================== ;; Instrument the binary -;; ===================== -;; RUN: wasm-split -all --instrument %s -o %t.instrumented.wasm +;; RUN: wasm-split --instrument %s -o %t.instrumented.wasm ;; Create profiles -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.foo.prof foo -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.bar.prof bar -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.both.prof foo bar -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.none.prof +;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.foo.prof foo +;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.bar.prof bar +;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.both.prof foo bar +;; RUN: node %S/call_exports.mjs %t.instrumented.wasm %t.none.prof ;; Create profile-guided splits -;; RUN: wasm-split -all %s --profile=%t.foo.prof -v -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm \ +;; RUN: wasm-split %s --profile=%t.foo.prof -v -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm \ ;; RUN: | filecheck %s --check-prefix FOO -;; RUN: wasm-split -all %s --profile=%t.bar.prof -v -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm \ -;; RUN: | filecheck %s --check-prefix BAR - -;; RUN: wasm-split -all %s --profile=%t.both.prof -v -o1 %t.both.1.wasm -o2 %t.both.2.wasm \ -;; RUN: | filecheck %s --check-prefix BOTH - -;; RUN: wasm-split -all %s --profile=%t.none.prof -v -o1 %t.none.1.wasm -o2 %t.none.2.wasm \ -;; RUN: | filecheck %s --check-prefix NONE - -;; ================================= -;; Do it all again using --in-memory -;; ================================= - -;; RUN: wasm-split -all --instrument --in-memory %s -o %t.instrumented.wasm - -;; Create profiles - -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.foo.prof foo -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.bar.prof bar -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.both.prof foo bar -;; RUN: node --experimental-wasm-threads %S/call_exports.mjs %t.instrumented.wasm %t.none.prof - -;; Create profile-guided splits - -;; RUN: wasm-split -all %s --profile=%t.foo.prof -v -o1 %t.foo.1.wasm -o2 %t.foo.2.wasm \ -;; RUN: | filecheck %s --check-prefix FOO - -;; RUN: wasm-split -all %s --profile=%t.bar.prof -v -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm \ -;; RUN: | filecheck %s --check-prefix BAR - -;; RUN: wasm-split -all %s --profile=%t.both.prof -v -o1 %t.both.1.wasm -o2 %t.both.2.wasm \ -;; RUN: | filecheck %s --check-prefix BOTH - -;; RUN: wasm-split -all %s --profile=%t.none.prof -v -o1 %t.none.1.wasm -o2 %t.none.2.wasm \ -;; RUN: | filecheck %s --check-prefix NONE - -;; ======= -;; Results -;; ======= - ;; FOO: Keeping functions: deep_foo_callee, foo, foo_callee, shared_callee ;; FOO: Splitting out functions: bar, bar_callee, uncalled +;; RUN: wasm-split %s --profile=%t.bar.prof -v -o1 %t.bar.1.wasm -o2 %t.bar.2.wasm \ +;; RUN: | filecheck %s --check-prefix BAR + ;; BAR: Keeping functions: bar, bar_callee, shared_callee ;; BAR: Splitting out functions: deep_foo_callee, foo, foo_callee, uncalled +;; RUN: wasm-split %s --profile=%t.both.prof -v -o1 %t.both.1.wasm -o2 %t.both.2.wasm \ +;; RUN: | filecheck %s --check-prefix BOTH + ;; BOTH: Keeping functions: bar, bar_callee, deep_foo_callee, foo, foo_callee, shared_callee ;; BOTH: Splitting out functions: uncalled +;; RUN: wasm-split %s --profile=%t.none.prof -v -o1 %t.none.1.wasm -o2 %t.none.2.wasm \ +;; RUN: | filecheck %s --check-prefix NONE + ;; NONE: Keeping functions: ;; NONE: Splitting out functions: bar, bar_callee, deep_foo_callee, foo, foo_callee, shared_callee, uncalled + (module - (memory $mem (shared 1 1)) + (memory $mem 1 1) (export "memory" (memory $mem)) (export "foo" (func $foo)) (export "bar" (func $bar)) diff -Nru binaryen-108/test/lit/wasm-split/symbolmap.wast binaryen-99/test/lit/wasm-split/symbolmap.wast --- binaryen-108/test/lit/wasm-split/symbolmap.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/symbolmap.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -;; RUN: wasm-split %s --keep-funcs=bar -o1 %t.1.wasm -o2 %t.2.wasm --symbolmap -;; RUN: filecheck %s --check-prefix PRIMARY-MAP < %t.1.wasm.symbols -;; RUN: filecheck %s --check-prefix SECONDARY-MAP < %t.2.wasm.symbols -;; RUN: wasm-dis %t.1.wasm | filecheck %s --check-prefix PRIMARY - -;; PRIMARY-MAP: 0:placeholder_0 -;; PRIMARY-MAP: 1:placeholder_2 -;; PRIMARY-MAP: 2:bar - -;; SECONDARY-MAP: 0:baz -;; SECONDARY-MAP: 1:foo - -;; Check that the names have been stripped. -;; PRIMARY: (func $0 - -(module - (table $table 3 3 funcref) - (elem $table (i32.const 0) $foo $bar $baz) - (func $foo - (nop) - ) - (func $bar - (nop) - ) - (func $baz - (nop) - ) -) diff -Nru binaryen-108/test/lit/wasm-split/verbose.wast binaryen-99/test/lit/wasm-split/verbose.wast --- binaryen-108/test/lit/wasm-split/verbose.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lit/wasm-split/verbose.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ ;; Test that --verbose mode correctly prints the kept and split funcs -;; RUN: wasm-split %s --keep-funcs=foo,bar --verbose \ +;; RUN: wasm-split %s --keep-funcs=foo,bar --split-funcs=baz --verbose \ ;; RUN: -o1 %t1.wasm -o2 %t2.wasm | filecheck %s ;; CHECK: Keeping functions: bar, foo{{$}} diff -Nru binaryen-108/test/lld/basic_safe_stack.s binaryen-99/test/lld/basic_safe_stack.s --- binaryen-108/test/lld/basic_safe_stack.s 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/basic_safe_stack.s 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ # Test that wasm-binaryen-finalize --check-stack-overflow correctly -# inserts stack check handlers. +# inserts stack chekc handlers. .globl stackRestore .globl stackAlloc diff -Nru binaryen-108/test/lld/basic_safe_stack.wat binaryen-99/test/lld/basic_safe_stack.wat --- binaryen-108/test/lld/basic_safe_stack.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/basic_safe_stack.wat 2021-01-07 20:01:06.000000000 +0000 @@ -3,7 +3,8 @@ (type $i32_=>_none (func (param i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 2) - (global $__stack_pointer (mut i32) (i32.const 66112)) + (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "stackRestore" (func $stackRestore)) @@ -12,18 +13,18 @@ (func $__wasm_call_ctors ) (func $stackRestore (param $0 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.get $0) ) ) (func $stackAlloc (param $0 i32) (result i32) (local $1 i32) (local $2 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $1 (i32.and (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (local.get $0) ) (i32.const -16) diff -Nru binaryen-108/test/lld/basic_safe_stack.wat.out binaryen-99/test/lld/basic_safe_stack.wat.out --- binaryen-108/test/lld/basic_safe_stack.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/basic_safe_stack.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,13 +1,14 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_none (func (param i32 i32))) - (import "env" "__handle_stack_overflow" (func $__handle_stack_overflow (param i32))) - (global $__stack_pointer (mut i32) (i32.const 66112)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "__handle_stack_overflow" (func $__handle_stack_overflow)) + (memory $0 2) + (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66112)) (global $__stack_base (mut i32) (i32.const 0)) (global $__stack_limit (mut i32) (i32.const 0)) - (memory $0 2) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "stackRestore" (func $stackRestore)) @@ -32,11 +33,9 @@ (global.get $__stack_limit) ) ) - (call $__handle_stack_overflow - (local.get $1) - ) + (call $__handle_stack_overflow) ) - (global.set $__stack_pointer + (global.set $global$0 (local.get $1) ) ) @@ -52,7 +51,7 @@ (local.tee $1 (i32.and (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (local.get $0) ) (i32.const -16) @@ -66,11 +65,9 @@ (global.get $__stack_limit) ) ) - (call $__handle_stack_overflow - (local.get $3) - ) + (call $__handle_stack_overflow) ) - (global.set $__stack_pointer + (global.set $global$0 (local.get $3) ) ) @@ -91,10 +88,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "__handle_stack_overflow" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/duplicate_imports.wat.out binaryen-99/test/lld/duplicate_imports.wat.out --- binaryen-108/test/lld/duplicate_imports.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/duplicate_imports.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,23 +1,23 @@ (module (type $i32_f32_f64_=>_f32 (func (param i32 f32 f64) (result f32))) (type $i32_f64_f64_=>_f32 (func (param i32 f64 f64) (result f32))) - (type $0 (func (param i32) (result i32))) - (type $1 (func (result i32))) - (type $2 (func)) - (type $f32_f64_=>_f32 (func (param f32 f64) (result f32))) - (type $f64_f64_=>_f32 (func (param f64 f64) (result f32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i64_=>_i32 (func (param i64) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $f32_f64_=>_f32 (func (param f32 f64) (result f32))) + (type $f64_f64_=>_f32 (func (param f64 f64) (result f32))) (import "env" "puts" (func $puts1 (param i32) (result i32))) (import "env" "invoke_ffd" (func $invoke_ffd (param i32 f32 f64) (result f32))) (import "env" "invoke_ffd" (func $invoke_ffd2 (param i32 f64 f64) (result f32))) (import "env" "puts" (func $legalimport$puts2 (param i32 i32) (result i32))) - (global $global$0 (mut i32) (i32.const 66128)) - (global $global$1 i32 (i32.const 66128)) - (global $global$2 i32 (i32.const 581)) (memory $0 2) (data (i32.const 568) "Hello, world\00") (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66128)) + (global $global$1 i32 (i32.const 66128)) + (global $global$2 i32 (i32.const 581)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -67,10 +67,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "puts" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/em_asm64.wat binaryen-99/test/lld/em_asm64.wat --- binaryen-108/test/lld/em_asm64.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm64.wat 2021-01-07 20:01:06.000000000 +0000 @@ -5,17 +5,12 @@ (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i64 i64 i64) (result i32))) (memory $0 i64 2) - (data $.rodata (i64.const 568) "\00ii\00i\00") - (data $em_asm (i64.const 574) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00\00{ return $0 + $1; }\00ii\00{ Module.print(\"Got \" + $0); }\00i\00") (table $0 1 1 funcref) (global $__stack_pointer (mut i64) (i64.const 66208)) - (global $global$1 i64 (i64.const 574)) - (global $global$2 i64 (i64.const 658)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) - (export "__start_em_asm" (global $global$1)) - (export "__stop_em_asm" (global $global$2)) (func $__wasm_call_ctors ) (func $__original_main (result i32) @@ -30,8 +25,8 @@ ) (drop (call $emscripten_asm_const_int - (i64.const 574) (i64.const 568) + (i64.const 601) (i64.const 0) ) ) @@ -42,8 +37,8 @@ (i32.store (local.get $0) (call $emscripten_asm_const_int - (i64.const 607) - (i64.const 569) + (i64.const 602) + (i64.const 622) (i64.add (local.get $0) (i64.const 16) @@ -52,8 +47,8 @@ ) (drop (call $emscripten_asm_const_int - (i64.const 627) - (i64.const 572) + (i64.const 625) + (i64.const 656) (local.get $0) ) ) @@ -69,6 +64,5 @@ (call $__original_main) ) ;; custom section "producers", size 112 - ;; features section: memory64 ) diff -Nru binaryen-108/test/lld/em_asm64.wat.out binaryen-99/test/lld/em_asm64.wat.out --- binaryen-108/test/lld/em_asm64.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm64.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,16 +1,13 @@ (module - (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (type $i32_i64_=>_i32 (func (param i32 i64) (result i32))) + (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i64 i64 i64) (result i32))) - (global $__stack_pointer (mut i64) (i64.const 66208)) - (global $global$1 i64 (i64.const 574)) - (global $global$2 i64 (i64.const 658)) (memory $0 i64 2) - (data $.rodata (i64.const 568) "\00ii\00i\00") - (data $em_asm (i64.const 574) "") + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00\00{ return $0 + $1; }\00ii\00{ Module.print(\"Got \" + $0); }\00i\00") (table $0 1 1 funcref) + (global $__stack_pointer (mut i64) (i64.const 66208)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -29,8 +26,8 @@ ) (drop (call $emscripten_asm_const_int - (i64.const 574) (i64.const 568) + (i64.const 601) (i64.const 0) ) ) @@ -41,8 +38,8 @@ (i32.store (local.get $0) (call $emscripten_asm_const_int - (i64.const 607) - (i64.const 569) + (i64.const 602) + (i64.const 622) (i64.add (local.get $0) (i64.const 16) @@ -51,8 +48,8 @@ ) (drop (call $emscripten_asm_const_int - (i64.const 627) - (i64.const 572) + (i64.const 625) + (i64.const 656) (local.get $0) ) ) @@ -72,14 +69,18 @@ --BEGIN METADATA -- { "asmConsts": { - "574": "{ Module.print(\"Hello world\"); }", - "607": "{ return $0 + $1; }", - "627": "{ Module.print(\"Got \" + $0); }" + "568": ["{ Module.print(\"Hello world\"); }", ["ijj"], [""]], + "602": ["{ return $0 + $1; }", ["ijj"], [""]], + "625": ["{ Module.print(\"Got \" + $0); }", ["ijj"], [""]] }, + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "emscripten_asm_const_int" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/em_asm.cpp binaryen-99/test/lld/em_asm.cpp --- binaryen-108/test/lld/em_asm.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ #include int main() { - EM_ASM({ Module.print("Hello \\ world\t\n"); }); + EM_ASM({ Module.print("Hello world"); }); int x = EM_ASM_INT({ return $0 + $1; }, 13, 27); EM_ASM_({ Module.print("Got " + $0); }, x); return 0; diff -Nru binaryen-108/test/lld/em_asm_main_thread.wat binaryen-99/test/lld/em_asm_main_thread.wat --- binaryen-108/test/lld/em_asm_main_thread.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_main_thread.wat 2021-01-07 20:01:06.000000000 +0000 @@ -12,8 +12,6 @@ (import "env" "emscripten_asm_const_int_sync_on_main_thread" (func $emscripten_asm_const_int_sync_on_main_thread (param i32 i32 i32) (result i32))) (memory $0 2) (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") - (global (export "__start_em_asm") i32 (i32.const 568)) - (global (export "__stop_em_asm") i32 (i32.const 652)) (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 66192)) (global $global$1 i32 (i32.const 66192)) diff -Nru binaryen-108/test/lld/em_asm_main_thread.wat.out binaryen-99/test/lld/em_asm_main_thread.wat.out --- binaryen-108/test/lld/em_asm_main_thread.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_main_thread.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,20 +1,18 @@ (module - (type $2 (func (result i32))) - (type $0 (func (param i32 i32 i32) (result i32))) - (type $1 (func)) - (type $3 (func (param i32 i32 i32))) - (type $4 (func (param i32 i32))) - (type $5 (func (param i32) (result i32))) - (type $6 (func (param i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "emscripten_asm_const_int_sync_on_main_thread" (func $emscripten_asm_const_int_sync_on_main_thread (param i32 i32 i32) (result i32))) - (global $0 i32 (i32.const 568)) - (global $1 i32 (i32.const 652)) + (memory $0 2) + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") + (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 66192)) (global $global$1 i32 (i32.const 66192)) (global $global$2 i32 (i32.const 652)) - (memory $0 2) - (data (i32.const 568) "") - (table $0 1 1 funcref) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "__heap_base" (global $global$1)) @@ -196,14 +194,18 @@ --BEGIN METADATA -- { "asmConsts": { - "568": "{ Module.print(\"Hello world\"); }", - "601": "{ return $0 + $1; }", - "621": "{ Module.print(\"Got \" + $0); }" + "568": ["{ Module.print(\"Hello world\"); }", ["iii"], ["sync_on_main_thread_"]], + "601": ["{ return $0 + $1; }", ["iii"], ["sync_on_main_thread_"]], + "621": ["{ Module.print(\"Got \" + $0); }", ["iii"], ["sync_on_main_thread_"]] }, + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "emscripten_asm_const_int_sync_on_main_thread" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/em_asm_O0.c binaryen-99/test/lld/em_asm_O0.c --- binaryen-108/test/lld/em_asm_O0.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_O0.c 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ #include -int main(int argc, char** argv) { +int main(int argc, char **argv) { EM_ASM({ Module.print("Hello world"); }); int ret = EM_ASM_INT({ return $0 + $1; }, 20, 30); EM_ASM({ Module.print("Got " + $0); }, 42); diff -Nru binaryen-108/test/lld/em_asm_O0.wat binaryen-99/test/lld/em_asm_O0.wat --- binaryen-108/test/lld/em_asm_O0.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_O0.wat 2021-01-07 20:01:06.000000000 +0000 @@ -4,24 +4,21 @@ (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) (memory $0 2) - (data $em_asm (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") - (global $__stack_pointer (mut i32) (i32.const 66192)) - (global $global$1 i32 (i32.const 568)) - (global $global$2 i32 (i32.const 652)) + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") + (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66192)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) - (export "__start_em_asm" (global $global$1)) - (export "__stop_em_asm" (global $global$2)) (func $__wasm_call_ctors ) (func $main (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $2 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 32) ) ) @@ -83,7 +80,7 @@ (local.get $2) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $2) (i32.const 32) diff -Nru binaryen-108/test/lld/em_asm_O0.wat.out binaryen-99/test/lld/em_asm_O0.wat.out --- binaryen-108/test/lld/em_asm_O0.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_O0.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,13 +1,12 @@ (module - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $none_=>_none (func)) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66192)) - (global $global$1 i32 (i32.const 568)) - (global $global$2 i32 (i32.const 652)) (memory $0 2) - (data $em_asm (i32.const 568) "") + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") + (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66192)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -17,10 +16,10 @@ (func $main (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $2 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 32) ) ) @@ -82,7 +81,7 @@ (local.get $2) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $2) (i32.const 32) @@ -95,14 +94,18 @@ --BEGIN METADATA -- { "asmConsts": { - "568": "{ Module.print(\"Hello world\"); }", - "601": "{ return $0 + $1; }", - "621": "{ Module.print(\"Got \" + $0); }" + "568": ["{ Module.print(\"Hello world\"); }", ["iii"], [""]], + "601": ["{ return $0 + $1; }", ["iii"], [""]], + "621": ["{ Module.print(\"Got \" + $0); }", ["iii"], [""]] }, + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "emscripten_asm_const_int" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/em_asm_pthread.cpp binaryen-99/test/lld/em_asm_pthread.cpp --- binaryen-108/test/lld/em_asm_pthread.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_pthread.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -// Build with -// -// emcc a.cpp -pthread -s WASM_BIGINT -// - -#include - -EM_JS(void, world, (), { console.log("World."); }); - -int main() { - EM_ASM({ console.log("Hello."); }); - world(); -} Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lld/em_asm_pthread.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lld/em_asm_pthread.wasm differ diff -Nru binaryen-108/test/lld/em_asm_pthread.wasm.out binaryen-99/test/lld/em_asm_pthread.wasm.out --- binaryen-108/test/lld/em_asm_pthread.wasm.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_pthread.wasm.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,12921 +0,0 @@ -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $i32_=>_none (func (param i32))) - (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (type $i32_i32_=>_none (func (param i32 i32))) - (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) - (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - (type $i32_i64_i32_=>_i64 (func (param i32 i64 i32) (result i64))) - (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) - (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32) (result i32))) - (type $none_=>_f64 (func (result f64))) - (type $i32_i32_f64_=>_i32 (func (param i32 i32 f64) (result i32))) - (type $i32_i32_i32_=>_f64 (func (param i32 i32 i32) (result f64))) - (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) - (type $i32_i32_f32_i32_=>_none (func (param i32 i32 f32 i32))) - (type $i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) - (type $f32_=>_none (func (param f32))) - (type $i32_f32_=>_none (func (param i32 f32))) - (type $f32_f32_=>_none (func (param f32 f32))) - (type $i32_f32_f32_=>_none (func (param i32 f32 f32))) - (type $f32_f32_f32_=>_none (func (param f32 f32 f32))) - (type $i32_f32_f32_f32_=>_none (func (param i32 f32 f32 f32))) - (type $f32_f32_f32_f32_=>_none (func (param f32 f32 f32 f32))) - (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) - (type $i32_f32_f32_f32_f32_=>_none (func (param i32 f32 f32 f32 f32))) - (type $i32_i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32))) - (type $i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32))) - (type $i32_i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32))) - (type $i32_f64_=>_i32 (func (param i32 f64) (result i32))) - (type $i32_i32_i32_i32_=>_f64 (func (param i32 i32 i32 i32) (result f64))) - (type $i32_i32_i64_i32_=>_i64 (func (param i32 i32 i64 i32) (result i64))) - (import "env" "memory" (memory $mimport$0 (shared 256 256))) - (data "\00/home/azakai/Dev/emscripten/system/lib/pthread/library_pthread.c\00call\00_emscripten_do_dispatch_to_thread\00target_thread\00num_args+1 <= EM_QUEUED_JS_CALL_MAX_ARGS\00emscripten_run_in_main_runtime_thread_js\00q\00_emscripten_call_on_thread\00EM_FUNC_SIG_NUM_FUNC_ARGUMENTS(q->functionEnum) <= EM_QUEUED_CALL_MAX_ARGS\00_do_call\000 && \"Invalid Emscripten pthread _do_call opcode!\"\00target\00GetQueue\00em_queued_call_malloc\00") - (data "\01\00\00\00\d0\0fP\00\05\00\00\00\00\00\00\00\00\00\00\00\02\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\03\00\00\00\04\00\00\00x\t\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\a0\05\00\00") - (data "") - (data "") - (data "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") - (import "env" "emscripten_asm_const_int" (func $fimport$0 (param i32 i32 i32) (result i32))) - (import "env" "world" (func $fimport$1)) - (import "env" "__cxa_thread_atexit" (func $fimport$2 (param i32 i32 i32) (result i32))) - (import "env" "__clock_gettime" (func $fimport$3 (param i32 i32) (result i32))) - (import "env" "emscripten_get_now" (func $fimport$4 (result f64))) - (import "env" "emscripten_conditional_set_current_thread_status" (func $fimport$5 (param i32 i32))) - (import "env" "emscripten_futex_wait" (func $fimport$6 (param i32 i32 f64) (result i32))) - (import "env" "emscripten_futex_wake" (func $fimport$7 (param i32 i32) (result i32))) - (import "env" "__assert_fail" (func $fimport$8 (param i32 i32 i32 i32))) - (import "env" "emscripten_set_current_thread_status" (func $fimport$9 (param i32))) - (import "env" "_emscripten_notify_thread_queue" (func $fimport$10 (param i32 i32) (result i32))) - (import "env" "emscripten_webgl_create_context" (func $fimport$11 (param i32 i32) (result i32))) - (import "env" "emscripten_set_canvas_element_size" (func $fimport$12 (param i32 i32 i32) (result i32))) - (import "env" "pthread_create" (func $fimport$13 (param i32 i32 i32 i32) (result i32))) - (import "env" "emscripten_receive_on_main_thread_js" (func $fimport$14 (param i32 i32 i32) (result f64))) - (import "env" "emscripten_resize_heap" (func $fimport$15 (param i32) (result i32))) - (import "wasi_snapshot_preview1" "fd_write" (func $fimport$16 (param i32 i32 i32 i32) (result i32))) - (import "env" "initPthreadsJS" (func $fimport$17)) - (import "env" "setTempRet0" (func $setTempRet0 (param i32))) - (global $global$0 (mut i32) (i32.const 5246928)) - (global $global$1 i32 (i32.const 0)) - (global $global$2 i32 (i32.const 0)) - (global $global$3 (mut i32) (i32.const 0)) - (global $global$4 (mut i32) (i32.const 0)) - (global $global$5 (mut i32) (i32.const 0)) - (global $global$6 (mut i32) (i32.const 0)) - (global $global$7 (mut i32) (i32.const 0)) - (global $global$10 i32 (i32.const 1432)) - (global $global$11 i32 (i32.const 1836)) - (global $global$12 i32 (i32.const 1658)) - (global $global$13 i32 (i32.const 1782)) - (table $0 5 5 funcref) - (elem (i32.const 1) $6 $73 $72 $74) - (export "__wasm_call_ctors" (func $0)) - (export "main" (func $4)) - (export "__indirect_function_table" (table $0)) - (export "emscripten_tls_init" (func $5)) - (export "emscripten_get_global_libc" (func $82)) - (export "__errno_location" (func $25)) - (export "fflush" (func $80)) - (export "__emscripten_pthread_data_constructor" (func $83)) - (export "pthread_self" (func $14)) - (export "__pthread_tsd_run_dtors" (func $84)) - (export "emscripten_current_thread_process_queued_calls" (func $31)) - (export "emscripten_register_main_browser_thread_id" (func $36)) - (export "emscripten_main_browser_thread_id" (func $37)) - (export "_emscripten_do_dispatch_to_thread" (func $38)) - (export "emscripten_sync_run_in_main_thread_2" (func $42)) - (export "emscripten_sync_run_in_main_thread_4" (func $43)) - (export "emscripten_main_thread_process_queued_calls" (func $44)) - (export "_emscripten_allow_main_runtime_queued_calls" (global $global$10)) - (export "emscripten_run_in_main_runtime_thread_js" (func $45)) - (export "_emscripten_call_on_thread" (func $47)) - (export "_emscripten_main_thread_futex" (global $global$11)) - (export "_emscripten_thread_init" (func $8)) - (export "stackSave" (func $77)) - (export "stackRestore" (func $78)) - (export "stackAlloc" (func $79)) - (export "emscripten_stack_init" (func $26)) - (export "emscripten_stack_set_limits" (func $27)) - (export "emscripten_stack_get_free" (func $28)) - (export "emscripten_stack_get_end" (func $29)) - (export "malloc" (func $60)) - (export "free" (func $62)) - (export "memalign" (func $63)) - (export "dynCall_vi" (func $dynCall_vi)) - (export "dynCall_ii" (func $dynCall_ii)) - (export "dynCall_iiii" (func $dynCall_iiii)) - (export "dynCall_jiji" (func $legalstub$dynCall_jiji)) - (start $2) - (func $0 - (call $26) - (call $83) - (call $5) - ) - (func $1 (param $0 i32) - ) - (func $2 - (if - (i32.atomic.rmw.cmpxchg - (i32.const 4032) - (i32.const 0) - (i32.const 1) - ) - (drop - (memory.atomic.wait32 - (i32.const 4032) - (i32.const 1) - (i64.const -1) - ) - ) - (block - (memory.init 0 - (i32.const 1024) - (i32.const 0) - (i32.const 403) - ) - (memory.init 1 - (i32.const 1432) - (i32.const 0) - (i32.const 156) - ) - (block - (drop - (i32.const 1588) - ) - (drop - (i32.const 0) - ) - (drop - (i32.const 70) - ) - ) - (block - (drop - (i32.const 1658) - ) - (drop - (i32.const 0) - ) - (drop - (i32.const 124) - ) - ) - (memory.init 4 - (i32.const 1792) - (i32.const 0) - (i32.const 2240) - ) - (i32.atomic.store - (i32.const 4032) - (i32.const 2) - ) - (drop - (memory.atomic.notify - (i32.const 4032) - (i32.const -1) - ) - ) - ) - ) - (data.drop 0) - (data.drop 1) - (nop) - (nop) - (data.drop 4) - ) - (func $3 (result i32) - (local $0 i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local.set $0 - (global.get $global$0) - ) - (local.set $1 - (i32.const 16) - ) - (local.set $2 - (i32.sub - (local.get $0) - (local.get $1) - ) - ) - (global.set $global$0 - (local.get $2) - ) - (local.set $3 - (i32.const 1658) - ) - (i32.store offset=12 - (local.get $2) - (local.get $3) - ) - (local.set $4 - (i32.load offset=12 - (local.get $2) - ) - ) - (local.set $5 - (i32.const 1024) - ) - (local.set $6 - (i32.const 0) - ) - (drop - (call $fimport$0 - (local.get $4) - (local.get $5) - (local.get $6) - ) - ) - (call $fimport$1) - (local.set $7 - (i32.const 0) - ) - (local.set $8 - (i32.const 16) - ) - (local.set $9 - (i32.add - (local.get $2) - (local.get $8) - ) - ) - (global.set $global$0 - (local.get $9) - ) - (return - (local.get $7) - ) - ) - (func $4 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local.set $2 - (call $3) - ) - (return - (local.get $2) - ) - ) - (func $5 - (local $0 i32) - (block $label$1 - (br_if $label$1 - (i32.eqz - (local.tee $0 - (global.get $global$1) - ) - ) - ) - (call $1 - (local.tee $0 - (call $63 - (global.get $global$2) - (local.get $0) - ) - ) - ) - (drop - (call $fimport$2 - (i32.const 1) - (local.get $0) - (i32.const 1024) - ) - ) - ) - ) - (func $6 (param $0 i32) - (call $62 - (local.get $0) - ) - ) - (func $7 (result i32) - (global.get $global$3) - ) - (func $8 (param $0 i32) (param $1 i32) (param $2 i32) - (global.set $global$3 - (local.get $0) - ) - (global.set $global$4 - (local.get $1) - ) - (global.set $global$5 - (local.get $2) - ) - ) - (func $9 (result i32) - (global.get $global$5) - ) - (func $10 (result i32) - (global.get $global$4) - ) - (func $11 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local.set $1 - (i32.load - (local.get $0) - ) - ) - (local.set $3 - (i32.load offset=40 - (local.tee $2 - (call $7) - ) - ) - ) - (local.set $5 - (i32.and - (local.tee $4 - (i32.load offset=4 - (local.get $0) - ) - ) - (i32.const 2147483647) - ) - ) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.ne - (i32.and - (local.get $1) - (i32.const 3) - ) - (i32.const 1) - ) - ) - (br_if $label$2 - (i32.ne - (local.get $5) - (local.get $3) - ) - ) - (local.set $6 - (i32.const 6) - ) - (br_if $label$1 - (i32.gt_u - (local.tee $5 - (i32.load offset=20 - (local.get $0) - ) - ) - (i32.const 2147483646) - ) - ) - (i32.store offset=20 - (local.get $0) - (i32.add - (local.get $5) - (i32.const 1) - ) - ) - (return - (i32.const 0) - ) - ) - (local.set $6 - (i32.const 56) - ) - (br_if $label$1 - (i32.eq - (local.get $5) - (i32.const 2147483647) - ) - ) - (block $label$3 - (br_if $label$3 - (i32.eqz - (i32.and - (i32.load8_u - (local.get $0) - ) - (i32.const 128) - ) - ) - ) - (block $label$4 - (br_if $label$4 - (i32.load - (i32.add - (local.get $2) - (i32.const 156) - ) - ) - ) - (i32.store offset=156 - (local.get $2) - (i32.const -12) - ) - ) - (local.set $6 - (i32.load offset=8 - (local.get $0) - ) - ) - (i32.store - (i32.add - (local.get $2) - (i32.const 160) - ) - (i32.add - (local.get $0) - (i32.const 16) - ) - ) - (local.set $3 - (select - (i32.or - (local.get $3) - (i32.const -2147483648) - ) - (local.get $3) - (local.get $6) - ) - ) - ) - (block $label$5 - (block $label$6 - (block $label$7 - (br_if $label$7 - (i32.eqz - (local.get $5) - ) - ) - (br_if $label$6 - (i32.eqz - (i32.and - (local.get $1) - (i32.const 4) - ) - ) - ) - (br_if $label$6 - (i32.eqz - (i32.and - (local.get $4) - (i32.const 1073741824) - ) - ) - ) - ) - (br_if $label$5 - (i32.eq - (call $12 - (i32.add - (local.get $0) - (i32.const 4) - ) - (local.get $4) - (local.get $3) - ) - (local.get $4) - ) - ) - ) - (i32.store - (i32.add - (local.get $2) - (i32.const 160) - ) - (i32.const 0) - ) - (return - (i32.const 10) - ) - ) - (local.set $3 - (i32.load offset=152 - (local.get $2) - ) - ) - (i32.store offset=12 - (local.get $0) - (local.tee $6 - (i32.add - (local.get $2) - (i32.const 152) - ) - ) - ) - (i32.store offset=16 - (local.get $0) - (local.get $3) - ) - (local.set $1 - (i32.add - (local.get $0) - (i32.const 16) - ) - ) - (block $label$8 - (br_if $label$8 - (i32.eq - (local.get $3) - (local.get $6) - ) - ) - (i32.store - (i32.add - (local.get $3) - (i32.const -4) - ) - (local.get $1) - ) - ) - (i32.store offset=152 - (local.get $2) - (local.get $1) - ) - (local.set $6 - (i32.const 0) - ) - (i32.store - (i32.add - (local.get $2) - (i32.const 160) - ) - (i32.const 0) - ) - (br_if $label$1 - (i32.eqz - (local.get $5) - ) - ) - (i32.store offset=20 - (local.get $0) - (i32.const 0) - ) - (i32.store - (local.get $0) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 8) - ) - ) - (local.set $6 - (i32.const 62) - ) - ) - (local.get $6) - ) - (func $12 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (i32.atomic.rmw.cmpxchg - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - (func $13 (param $0 i32) (result i32) - (block $label$1 - (br_if $label$1 - (i32.and - (i32.load8_u - (local.get $0) - ) - (i32.const 15) - ) - ) - (return - (i32.and - (call $12 - (i32.add - (local.get $0) - (i32.const 4) - ) - (i32.const 0) - (i32.const 10) - ) - (i32.const 10) - ) - ) - ) - (call $11 - (local.get $0) - ) - ) - (func $14 (result i32) - (call $7) - ) - (func $15 - (call $16) - ) - (func $16 - (drop - (i32.atomic.rmw.add offset=1792 - (i32.const 0) - (i32.const 1) - ) - ) - ) - (func $17 - (block $label$1 - (br_if $label$1 - (i32.ne - (call $18) - (i32.const 1) - ) - ) - (br_if $label$1 - (i32.eqz - (i32.load offset=1796 - (i32.const 0) - ) - ) - ) - (call $19) - ) - ) - (func $18 (result i32) - (i32.atomic.rmw.add offset=1792 - (i32.const 0) - (i32.const -1) - ) - ) - (func $19 - (drop - (call $fimport$7 - (i32.const 1792) - (i32.const 2147483647) - ) - ) - ) - (func $20 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local.set $2 - (i32.and - (i32.xor - (local.tee $1 - (i32.load - (local.get $0) - ) - ) - (i32.const -1) - ) - (i32.const 128) - ) - ) - (local.set $3 - (i32.load offset=8 - (local.get $0) - ) - ) - (block $label$1 - (block $label$2 - (block $label$3 - (br_if $label$3 - (local.tee $4 - (i32.and - (local.get $1) - (i32.const 15) - ) - ) - ) - (br $label$2) - ) - (local.set $5 - (call $7) - ) - (local.set $6 - (i32.const 63) - ) - (br_if $label$1 - (i32.ne - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const 2147483647) - ) - (i32.load offset=40 - (local.get $5) - ) - ) - ) - (block $label$4 - (br_if $label$4 - (i32.ne - (i32.and - (local.get $1) - (i32.const 3) - ) - (i32.const 1) - ) - ) - (br_if $label$4 - (i32.eqz - (local.tee $6 - (i32.load offset=20 - (local.get $0) - ) - ) - ) - ) - (i32.store offset=20 - (local.get $0) - (i32.add - (local.get $6) - (i32.const -1) - ) - ) - (return - (i32.const 0) - ) - ) - (block $label$5 - (br_if $label$5 - (local.get $2) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 160) - ) - (i32.add - (local.get $0) - (i32.const 16) - ) - ) - (call $15) - ) - (i32.store - (local.tee $7 - (i32.load offset=12 - (local.get $0) - ) - ) - (local.tee $6 - (i32.load offset=16 - (local.get $0) - ) - ) - ) - (br_if $label$2 - (i32.eq - (local.get $6) - (i32.add - (local.get $5) - (i32.const 152) - ) - ) - ) - (i32.store - (i32.add - (local.get $6) - (i32.const -4) - ) - (local.get $7) - ) - ) - (local.set $0 - (call $21 - (local.tee $7 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - (i32.and - (i32.shr_s - (i32.shl - (local.get $1) - (i32.const 28) - ) - (i32.const 31) - ) - (i32.const 2147483647) - ) - ) - ) - (block $label$6 - (br_if $label$6 - (i32.eqz - (local.get $4) - ) - ) - (br_if $label$6 - (local.get $2) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 160) - ) - (i32.const 0) - ) - (call $17) - ) - (local.set $6 - (i32.const 0) - ) - (block $label$7 - (br_if $label$7 - (local.get $3) - ) - (br_if $label$1 - (i32.gt_s - (local.get $0) - (i32.const -1) - ) - ) - ) - (call $22 - (local.get $7) - (local.get $2) - ) - ) - (local.get $6) - ) - (func $21 (param $0 i32) (param $1 i32) (result i32) - (i32.atomic.rmw.xchg - (local.get $0) - (local.get $1) - ) - ) - (func $22 (param $0 i32) (param $1 i32) - (drop - (call $fimport$7 - (local.get $0) - (i32.const 1) - ) - ) - ) - (func $23 (param $0 i32) (result i32) - (i32.atomic.load - (local.get $0) - ) - ) - (func $24 (param $0 i32) (param $1 i32) (result i32) - (i32.atomic.store - (local.get $0) - (local.get $1) - ) - (local.get $1) - ) - (func $25 (result i32) - (i32.add - (call $7) - (i32.const 48) - ) - ) - (func $26 - (global.set $global$7 - (i32.const 5246928) - ) - (global.set $global$6 - (i32.and - (i32.add - (i32.const 4036) - (i32.const 15) - ) - (i32.const -16) - ) - ) - ) - (func $27 (param $0 i32) (param $1 i32) - (global.set $global$7 - (local.get $0) - ) - (global.set $global$6 - (local.get $1) - ) - ) - (func $28 (result i32) - (i32.sub - (global.get $global$0) - (global.get $global$6) - ) - ) - (func $29 (result i32) - (global.get $global$6) - ) - (func $30 (param $0 i32) (result i32) - (i32.eq - (i32.load - (local.get $0) - ) - (i32.const 2) - ) - ) - (func $31 - (local $0 i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.eqz - (call $10) - ) - ) - (br_if $label$1 - (i32.load8_u offset=1832 - (i32.const 0) - ) - ) - (i32.store8 offset=1832 - (i32.const 0) - (i32.const 1) - ) - ) - (drop - (call $55 - (i32.const 1804) - ) - ) - (block $label$3 - (br_if $label$3 - (local.tee $0 - (call $32 - (call $14) - ) - ) - ) - (drop - (call $20 - (i32.const 1804) - ) - ) - (br_if $label$1 - (i32.eqz - (call $10) - ) - ) - (i32.store8 offset=1832 - (i32.const 0) - (i32.const 0) - ) - (return) - ) - (block $label$4 - (br_if $label$4 - (i32.eq - (local.tee $2 - (call $23 - (local.tee $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - (call $23 - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 12) - ) - ) - ) - ) - ) - (loop $label$5 - (drop - (call $20 - (i32.const 1804) - ) - ) - (call $33 - (i32.load - (i32.add - (i32.load offset=4 - (local.get $0) - ) - (i32.shl - (local.get $2) - (i32.const 2) - ) - ) - ) - ) - (drop - (call $55 - (i32.const 1804) - ) - ) - (drop - (call $24 - (local.get $1) - (local.tee $2 - (i32.rem_s - (i32.add - (local.get $2) - (i32.const 1) - ) - (i32.const 128) - ) - ) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $2) - (call $23 - (local.get $3) - ) - ) - ) - ) - ) - (drop - (call $20 - (i32.const 1804) - ) - ) - (drop - (call $fimport$7 - (local.get $1) - (i32.const 2147483647) - ) - ) - (br_if $label$1 - (i32.eqz - (call $10) - ) - ) - (i32.store8 offset=1832 - (i32.const 0) - (i32.const 0) - ) - ) - ) - (func $32 (param $0 i32) (result i32) - (local $1 i32) - (block $label$1 - (br_if $label$1 - (i32.eqz - (local.get $0) - ) - ) - (block $label$2 - (br_if $label$2 - (i32.eqz - (local.tee $1 - (i32.load offset=1840 - (i32.const 0) - ) - ) - ) - ) - (loop $label$3 - (block $label$4 - (br_if $label$4 - (i32.ne - (i32.load - (local.get $1) - ) - (local.get $0) - ) - ) - (return - (local.get $1) - ) - ) - (br_if $label$3 - (local.tee $1 - (i32.load offset=16 - (local.get $1) - ) - ) - ) - ) - ) - (return - (i32.const 0) - ) - ) - (call $fimport$8 - (i32.const 1389) - (i32.const 1025) - (i32.const 385) - (i32.const 1396) - ) - (unreachable) - ) - (func $33 (param $0 i32) - (local $1 i32) - (block $label$1 - (block $label$2 - (block $label$3 - (br_if $label$3 - (i32.eq - (i32.and - (local.tee $1 - (i32.load - (local.get $0) - ) - ) - (i32.const 402653184) - ) - (i32.const 402653184) - ) - ) - (block $label$4 - (block $label$5 - (block $label$6 - (block $label$7 - (block $label$8 - (block $label$9 - (block $label$10 - (block $label$11 - (block $label$12 - (block $label$13 - (block $label$14 - (block $label$15 - (block $label$16 - (block $label$17 - (block $label$18 - (block $label$19 - (block $label$20 - (block $label$21 - (block $label$22 - (block $label$23 - (block $label$24 - (block $label$25 - (block $label$26 - (block $label$27 - (block $label$28 - (block $label$29 - (br_if $label$29 - (i32.gt_s - (local.get $1) - (i32.const 234881023) - ) - ) - (block $label$30 - (br_if $label$30 - (i32.gt_s - (local.get $1) - (i32.const 100663335) - ) - ) - (block $label$31 - (br_if $label$31 - (i32.gt_s - (local.get $1) - (i32.const 67108863) - ) - ) - (block $label$32 - (br_table $label$28 $label$5 $label$27 $label$32 - (i32.add - (local.get $1) - (i32.const -33554432) - ) - ) - ) - (br_if $label$4 - (i32.eq - (local.get $1) - (i32.const -2126512128) - ) - ) - (br_if $label$5 - (local.get $1) - ) - (call_indirect (type $none_=>_none) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (block $label$33 - (br_if $label$33 - (i32.gt_s - (local.get $1) - (i32.const 100663295) - ) - ) - (br_table $label$26 $label$5 $label$25 $label$6 - (i32.add - (local.get $1) - (i32.const -67108872) - ) - ) - ) - (br_if $label$24 - (i32.eq - (local.get $1) - (i32.const 100663296) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 100663328) - ) - ) - (call_indirect (type $i32_i32_f32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (block $label$34 - (br_if $label$34 - (i32.gt_s - (local.get $1) - (i32.const 134217895) - ) - ) - (block $label$35 - (br_table $label$23 $label$5 $label$22 $label$35 - (i32.add - (local.get $1) - (i32.const -100663336) - ) - ) - ) - (br_if $label$21 - (i32.eq - (local.get $1) - (i32.const 134217728) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 134217760) - ) - ) - (call_indirect (type $i32_i32_f32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (block $label$36 - (br_if $label$36 - (i32.gt_s - (local.get $1) - (i32.const 167772839) - ) - ) - (br_table $label$20 $label$5 $label$19 $label$18 - (i32.add - (local.get $1) - (i32.const -134217896) - ) - ) - ) - (br_if $label$17 - (i32.eq - (local.get $1) - (i32.const 167772840) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 201326592) - ) - ) - (call_indirect (type $i32_i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (block $label$37 - (br_if $label$37 - (i32.gt_s - (local.get $1) - (i32.const 637534207) - ) - ) - (block $label$38 - (br_if $label$38 - (i32.gt_s - (local.get $1) - (i32.const 369098751) - ) - ) - (block $label$39 - (br_if $label$39 - (i32.gt_s - (local.get $1) - (i32.const 301989887) - ) - ) - (br_if $label$16 - (i32.eq - (local.get $1) - (i32.const 234881024) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 268435456) - ) - ) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 72) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (br_if $label$15 - (i32.eq - (local.get $1) - (i32.const 301989888) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 335544320) - ) - ) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 72) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 80) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 88) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (block $label$40 - (br_if $label$40 - (i32.gt_s - (local.get $1) - (i32.const 570425343) - ) - ) - (br_if $label$14 - (i32.eq - (local.get $1) - (i32.const 369098752) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 536870912) - ) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $none_=>_i32) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (br_if $label$13 - (i32.eq - (local.get $1) - (i32.const 570425344) - ) - ) - (br_if $label$12 - (i32.eq - (local.get $1) - (i32.const 603979776) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 622854144) - ) - ) - (i32.store offset=176 - (local.get $0) - (call $fimport$11 - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - ) - ) - (br $label$1) - ) - (block $label$41 - (br_if $label$41 - (i32.gt_s - (local.get $1) - (i32.const 704643071) - ) - ) - (block $label$42 - (br_if $label$42 - (i32.gt_s - (local.get $1) - (i32.const 671088639) - ) - ) - (br_if $label$11 - (i32.eq - (local.get $1) - (i32.const 637534208) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 657457152) - ) - ) - (i32.store offset=176 - (local.get $0) - (call $fimport$12 - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - ) - ) - (br $label$1) - ) - (br_if $label$10 - (i32.eq - (local.get $1) - (i32.const 671088640) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 687865856) - ) - ) - (i32.store offset=176 - (local.get $0) - (call $fimport$13 - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - ) - ) - (br $label$1) - ) - (block $label$43 - (br_if $label$43 - (i32.gt_s - (local.get $1) - (i32.const 771751935) - ) - ) - (br_if $label$9 - (i32.eq - (local.get $1) - (i32.const 704643072) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 738197504) - ) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (br_if $label$8 - (i32.eq - (local.get $1) - (i32.const 771751936) - ) - ) - (br_if $label$7 - (i32.eq - (local.get $1) - (i32.const 805306368) - ) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 838860800) - ) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 72) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 80) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $f32_=>_none) - (f32.load offset=16 - (local.get $0) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_f32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $f32_f32_=>_none) - (f32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_f32_f32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $f32_f32_f32_=>_none) - (f32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_f32_f32_f32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $f32_f32_f32_f32_=>_none) - (f32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (br_if $label$5 - (i32.ne - (local.get $1) - (i32.const 167772160) - ) - ) - (call_indirect (type $i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_f32_f32_f32_f32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (f32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 72) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 80) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 72) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 80) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 88) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 96) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (i32.store offset=176 - (local.get $0) - (call_indirect (type $i32_i32_i32_i32_i32_i32_i32_i32_=>_i32) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 40) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 48) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 56) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 64) - ) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 72) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (br $label$1) - ) - (br_if $label$2 - (i32.eq - (local.get $1) - (i32.const 67108864) - ) - ) - ) - (call $fimport$8 - (i32.const 1338) - (i32.const 1025) - (i32.const 351) - (i32.const 1329) - ) - (unreachable) - ) - (f64.store offset=176 - (local.get $0) - (call $fimport$14 - (i32.load offset=4 - (local.get $0) - ) - (i32.load offset=16 - (local.get $0) - ) - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - ) - (br $label$1) - ) - (call $fimport$8 - (i32.const 1254) - (i32.const 1025) - (i32.const 207) - (i32.const 1329) - ) - (unreachable) - ) - (call_indirect (type $i32_i32_=>_none) - (i32.load offset=16 - (local.get $0) - ) - (i32.load - (i32.add - (local.get $0) - (i32.const 24) - ) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (block $label$44 - (br_if $label$44 - (i32.eqz - (i32.load offset=188 - (local.get $0) - ) - ) - ) - (call $34 - (local.get $0) - ) - (return) - ) - (i32.store offset=8 - (local.get $0) - (i32.const 1) - ) - (drop - (call $fimport$7 - (i32.add - (local.get $0) - (i32.const 8) - ) - (i32.const 2147483647) - ) - ) - ) - (func $34 (param $0 i32) - (block $label$1 - (br_if $label$1 - (i32.eqz - (local.get $0) - ) - ) - (call $62 - (i32.load offset=184 - (local.get $0) - ) - ) - ) - (call $62 - (local.get $0) - ) - ) - (func $35 (param $0 i32) (param $1 f64) (result i32) - (local $2 i32) - (local $3 f64) - (block $label$1 - (br_if $label$1 - (local.tee $0 - (call $23 - (local.tee $2 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - ) - (local.set $3 - (call $fimport$4) - ) - (call $fimport$9 - (i32.const 5) - ) - (local.set $0 - (i32.const 0) - ) - (block $label$2 - (br_if $label$2 - (i32.xor - (f64.lt - (local.get $3) - (local.tee $1 - (f64.add - (local.get $3) - (local.get $1) - ) - ) - ) - (i32.const 1) - ) - ) - (loop $label$3 - (drop - (call $fimport$6 - (local.get $2) - (i32.const 0) - (f64.sub - (local.get $1) - (local.get $3) - ) - ) - ) - (local.set $0 - (call $23 - (local.get $2) - ) - ) - (local.set $3 - (call $fimport$4) - ) - (br_if $label$2 - (local.get $0) - ) - (br_if $label$3 - (f64.lt - (local.get $3) - (local.get $1) - ) - ) - ) - ) - (call $fimport$9 - (i32.const 1) - ) - ) - (select - (i32.const 0) - (i32.const -8) - (local.get $0) - ) - ) - (func $36 (param $0 i32) - (i32.store offset=1800 - (i32.const 0) - (local.get $0) - ) - ) - (func $37 (result i32) - (i32.load offset=1800 - (i32.const 0) - ) - ) - (func $38 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (block $label$1 - (block $label$2 - (block $label$3 - (br_if $label$3 - (i32.eqz - (local.get $1) - ) - ) - (block $label$4 - (block $label$5 - (block $label$6 - (br_table $label$6 $label$5 $label$4 - (local.get $0) - ) - ) - (call $fimport$8 - (i32.const 1129) - (i32.const 1025) - (i32.const 468) - (i32.const 1095) - ) - (unreachable) - ) - (local.set $0 - (call $37) - ) - ) - (block $label$7 - (block $label$8 - (br_if $label$8 - (i32.eq - (local.get $0) - (i32.const 2) - ) - ) - (br_if $label$7 - (i32.ne - (local.get $0) - (call $14) - ) - ) - ) - (call $33 - (local.get $1) - ) - (return - (i32.const 1) - ) - ) - (drop - (call $55 - (i32.const 1804) - ) - ) - (block $label$9 - (br_if $label$9 - (i32.load offset=4 - (local.tee $2 - (call $39 - (local.get $0) - ) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (call $60 - (i32.const 512) - ) - ) - ) - (block $label$10 - (br_if $label$10 - (i32.ne - (local.tee $4 - (call $23 - (local.tee $3 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - ) - ) - (local.tee $7 - (i32.rem_s - (i32.add - (local.tee $6 - (call $23 - (local.tee $5 - (i32.add - (local.get $2) - (i32.const 12) - ) - ) - ) - ) - (i32.const 1) - ) - (i32.const 128) - ) - ) - ) - ) - (loop $label$11 - (drop - (call $20 - (i32.const 1804) - ) - ) - (br_if $label$2 - (i32.ne - (local.get $0) - (call $37) - ) - ) - (drop - (call $fimport$6 - (local.get $3) - (local.get $4) - (f64.const inf) - ) - ) - (drop - (call $55 - (i32.const 1804) - ) - ) - (br_if $label$11 - (i32.eq - (local.tee $4 - (call $23 - (local.get $3) - ) - ) - (local.tee $7 - (i32.rem_s - (i32.add - (local.tee $6 - (call $23 - (local.get $5) - ) - ) - (i32.const 1) - ) - (i32.const 128) - ) - ) - ) - ) - ) - ) - (i32.store - (i32.add - (i32.load offset=4 - (local.get $2) - ) - (i32.shl - (local.get $6) - (i32.const 2) - ) - ) - (local.get $1) - ) - (block $label$12 - (br_if $label$12 - (i32.ne - (local.get $4) - (local.get $6) - ) - ) - (br_if $label$12 - (call $fimport$10 - (local.get $0) - (call $37) - ) - ) - (call $34 - (local.get $1) - ) - (drop - (call $20 - (i32.const 1804) - ) - ) - (br $label$1) - ) - (drop - (call $24 - (local.get $5) - (local.get $7) - ) - ) - (drop - (call $20 - (i32.const 1804) - ) - ) - (br $label$1) - ) - (call $fimport$8 - (i32.const 1090) - (i32.const 1025) - (i32.const 458) - (i32.const 1095) - ) - (unreachable) - ) - (call $34 - (local.get $1) - ) - ) - (i32.const 0) - ) - (func $39 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (block $label$1 - (br_if $label$1 - (local.tee $1 - (call $32 - (local.get $0) - ) - ) - ) - (i64.store offset=12 align=4 - (local.tee $1 - (call $60 - (i32.const 20) - ) - ) - (i64.const 0) - ) - (i64.store offset=4 align=4 - (local.get $1) - (i64.const 0) - ) - (i32.store - (local.get $1) - (local.get $0) - ) - (block $label$2 - (block $label$3 - (br_if $label$3 - (local.tee $0 - (i32.load offset=1840 - (i32.const 0) - ) - ) - ) - (local.set $0 - (i32.const 1840) - ) - (br $label$2) - ) - (loop $label$4 - (br_if $label$4 - (local.tee $0 - (i32.load offset=16 - (local.tee $2 - (local.get $0) - ) - ) - ) - ) - ) - (local.set $0 - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - ) - (i32.store - (local.get $0) - (local.get $1) - ) - ) - (local.get $1) - ) - (func $40 (param $0 i32) - (drop - (call $38 - (call $37) - (local.get $0) - ) - ) - ) - (func $41 (param $0 i32) - (call $40 - (local.get $0) - ) - (drop - (call $35 - (local.get $0) - (f64.const inf) - ) - ) - ) - (func $42 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (global.set $global$0 - (local.tee $3 - (i32.sub - (global.get $global$0) - (i32.const 192) - ) - ) - ) - (memory.fill - (local.get $3) - (i32.const 0) - (i32.const 192) - ) - (i32.store - (i32.add - (local.get $3) - (i32.const 24) - ) - (local.get $2) - ) - (i32.store offset=176 - (local.get $3) - (i32.const 0) - ) - (i32.store offset=16 - (local.get $3) - (local.get $1) - ) - (i32.store - (local.get $3) - (local.get $0) - ) - (call $41 - (local.get $3) - ) - (local.set $0 - (i32.load offset=176 - (local.get $3) - ) - ) - (global.set $global$0 - (i32.add - (local.get $3) - (i32.const 192) - ) - ) - (local.get $0) - ) - (func $43 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) - (local $5 i32) - (global.set $global$0 - (local.tee $5 - (i32.sub - (global.get $global$0) - (i32.const 192) - ) - ) - ) - (memory.fill - (local.get $5) - (i32.const 0) - (i32.const 192) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 40) - ) - (local.get $4) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 32) - ) - (local.get $3) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 24) - ) - (local.get $2) - ) - (i32.store offset=176 - (local.get $5) - (i32.const 0) - ) - (i32.store offset=16 - (local.get $5) - (local.get $1) - ) - (i32.store - (local.get $5) - (local.get $0) - ) - (call $41 - (local.get $5) - ) - (local.set $0 - (i32.load offset=176 - (local.get $5) - ) - ) - (global.set $global$0 - (i32.add - (local.get $5) - (i32.const 192) - ) - ) - (local.get $0) - ) - (func $44 - (block $label$1 - (br_if $label$1 - (i32.eqz - (call $9) - ) - ) - (br_if $label$1 - (i32.eqz - (i32.load offset=1432 - (i32.const 0) - ) - ) - ) - (call $31) - ) - ) - (func $45 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result f64) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 f64) - (global.set $global$0 - (local.tee $4 - (i32.sub - (global.get $global$0) - (i32.const 192) - ) - ) - ) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.eqz - (local.get $3) - ) - ) - (i32.store offset=184 - (local.get $4) - (i32.const 0) - ) - (i32.store offset=8 - (local.get $4) - (i32.const 0) - ) - (local.set $5 - (local.get $4) - ) - (br $label$1) - ) - (local.set $5 - (call $46) - ) - ) - (i32.store offset=4 - (local.get $5) - (local.get $0) - ) - (i32.store - (local.get $5) - (i32.const -2126512128) - ) - (i32.store offset=188 - (local.get $5) - (i32.sub - (i32.const 1) - (local.get $3) - ) - ) - (block $label$3 - (br_if $label$3 - (i32.ge_s - (local.get $1) - (i32.const 20) - ) - ) - (i32.store offset=16 - (local.get $5) - (local.get $1) - ) - (local.set $0 - (i32.const 0) - ) - (block $label$4 - (br_if $label$4 - (i32.le_s - (local.get $1) - (i32.const 0) - ) - ) - (loop $label$5 - (i64.store - (i32.add - (i32.add - (local.get $5) - (i32.shl - (local.tee $6 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (i32.const 3) - ) - ) - (i32.const 16) - ) - (i64.load - (i32.add - (local.get $2) - (i32.shl - (local.get $0) - (i32.const 3) - ) - ) - ) - ) - (local.set $0 - (local.get $6) - ) - (br_if $label$5 - (i32.ne - (local.get $6) - (local.get $1) - ) - ) - ) - ) - (block $label$6 - (block $label$7 - (br_if $label$7 - (i32.eqz - (local.get $3) - ) - ) - (call $41 - (local.get $4) - ) - (local.set $7 - (f64.load offset=176 - (local.get $4) - ) - ) - (br $label$6) - ) - (call $40 - (local.get $5) - ) - (local.set $7 - (f64.const 0) - ) - ) - (global.set $global$0 - (i32.add - (local.get $4) - (i32.const 192) - ) - ) - (return - (local.get $7) - ) - ) - (call $fimport$8 - (i32.const 1143) - (i32.const 1025) - (i32.const 766) - (i32.const 1184) - ) - (unreachable) - ) - (func $46 (result i32) - (local $0 i32) - (block $label$1 - (br_if $label$1 - (local.tee $0 - (call $60 - (i32.const 192) - ) - ) - ) - (call $fimport$8 - (i32.const 1090) - (i32.const 1025) - (i32.const 173) - (i32.const 1405) - ) - (unreachable) - ) - (i32.store offset=184 - (local.get $0) - (i32.const 0) - ) - (i64.store offset=4 align=4 - (local.get $0) - (i64.const 0) - ) - (local.get $0) - ) - (func $47 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (result i32) - (local $6 i32) - (local $7 i32) - (global.set $global$0 - (local.tee $6 - (i32.sub - (global.get $global$0) - (i32.const 16) - ) - ) - ) - (block $label$1 - (br_if $label$1 - (i32.eqz - (local.tee $7 - (call $46) - ) - ) - ) - (i32.store offset=184 - (local.get $7) - (local.get $4) - ) - (i32.store offset=4 - (local.get $7) - (local.get $3) - ) - (i32.store - (local.get $7) - (local.get $2) - ) - (i32.store offset=12 - (local.get $6) - (local.get $5) - ) - (block $label$2 - (br_if $label$2 - (i32.eqz - (local.tee $4 - (i32.and - (i32.shr_u - (local.get $2) - (i32.const 25) - ) - (i32.const 15) - ) - ) - ) - ) - (local.set $2 - (i32.and - (local.get $2) - (i32.const 33554431) - ) - ) - (local.set $3 - (i32.const 0) - ) - (loop $label$3 - (block $label$4 - (block $label$5 - (block $label$6 - (block $label$7 - (block $label$8 - (br_table $label$8 $label$7 $label$6 $label$5 $label$8 - (i32.and - (local.get $2) - (i32.const 3) - ) - ) - ) - (i32.store offset=12 - (local.get $6) - (i32.add - (local.tee $5 - (i32.load offset=12 - (local.get $6) - ) - ) - (i32.const 4) - ) - ) - (i32.store - (i32.add - (i32.add - (local.get $7) - (i32.shl - (local.get $3) - (i32.const 3) - ) - ) - (i32.const 16) - ) - (i32.load - (local.get $5) - ) - ) - (br $label$4) - ) - (i32.store offset=12 - (local.get $6) - (i32.add - (local.tee $5 - (i32.and - (i32.add - (i32.load offset=12 - (local.get $6) - ) - (i32.const 7) - ) - (i32.const -8) - ) - ) - (i32.const 8) - ) - ) - (i64.store - (i32.add - (i32.add - (local.get $7) - (i32.shl - (local.get $3) - (i32.const 3) - ) - ) - (i32.const 16) - ) - (i64.load - (local.get $5) - ) - ) - (br $label$4) - ) - (i32.store offset=12 - (local.get $6) - (i32.add - (local.tee $5 - (i32.and - (i32.add - (i32.load offset=12 - (local.get $6) - ) - (i32.const 7) - ) - (i32.const -8) - ) - ) - (i32.const 8) - ) - ) - (f32.store - (i32.add - (i32.add - (local.get $7) - (i32.shl - (local.get $3) - (i32.const 3) - ) - ) - (i32.const 16) - ) - (f32.demote_f64 - (f64.load - (local.get $5) - ) - ) - ) - (br $label$4) - ) - (i32.store offset=12 - (local.get $6) - (i32.add - (local.tee $5 - (i32.and - (i32.add - (i32.load offset=12 - (local.get $6) - ) - (i32.const 7) - ) - (i32.const -8) - ) - ) - (i32.const 8) - ) - ) - (f64.store - (i32.add - (i32.add - (local.get $7) - (i32.shl - (local.get $3) - (i32.const 3) - ) - ) - (i32.const 16) - ) - (f64.load - (local.get $5) - ) - ) - ) - (local.set $2 - (i32.shr_u - (local.get $2) - (i32.const 2) - ) - ) - (br_if $label$3 - (i32.ne - (local.tee $3 - (i32.add - (local.get $3) - (i32.const 1) - ) - ) - (local.get $4) - ) - ) - ) - ) - (i32.store offset=188 - (local.get $7) - (i32.const 1) - ) - (block $label$9 - (block $label$10 - (br_if $label$10 - (i32.eqz - (local.get $0) - ) - ) - (local.set $2 - (i32.const 0) - ) - (i32.store8 offset=11 - (local.get $6) - (i32.const 0) - ) - (i32.store16 offset=9 align=1 - (local.get $6) - (i32.const 26985) - ) - (i32.store - (local.get $6) - (local.get $1) - ) - (i32.store offset=4 - (local.get $6) - (local.get $7) - ) - (drop - (call $fimport$0 - (i32.const 1703) - (i32.add - (local.get $6) - (i32.const 9) - ) - (local.get $6) - ) - ) - (br $label$9) - ) - (local.set $2 - (call $38 - (local.get $1) - (local.get $7) - ) - ) - ) - (global.set $global$0 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - (return - (local.get $2) - ) - ) - (call $fimport$8 - (i32.const 1225) - (i32.const 1025) - (i32.const 868) - (i32.const 1227) - ) - (unreachable) - ) - (func $48 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local.set $2 - (i32.const 28) - ) - (block $label$1 - (br_if $label$1 - (i32.gt_u - (local.get $0) - (i32.const 2) - ) - ) - (local.set $2 - (call $7) - ) - (block $label$2 - (br_if $label$2 - (i32.eqz - (local.get $1) - ) - ) - (i32.store - (local.get $1) - (i32.load offset=56 - (local.get $2) - ) - ) - ) - (i32.store offset=56 - (local.get $2) - (local.get $0) - ) - (local.set $2 - (i32.const 0) - ) - ) - (local.get $2) - ) - (func $49 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) - (local $5 i32) - (local $6 f64) - (local $7 i32) - (local $8 f64) - (global.set $global$0 - (local.tee $5 - (i32.sub - (global.get $global$0) - (i32.const 16) - ) - ) - ) - (block $label$1 - (block $label$2 - (block $label$3 - (block $label$4 - (br_if $label$4 - (local.get $3) - ) - (local.set $6 - (f64.const inf) - ) - (br $label$3) - ) - (local.set $7 - (i32.const 28) - ) - (br_if $label$1 - (i32.gt_u - (i32.load offset=4 - (local.get $3) - ) - (i32.const 999999999) - ) - ) - (br_if $label$1 - (call $fimport$3 - (local.get $2) - (i32.add - (local.get $5) - (i32.const 8) - ) - ) - ) - (i32.store offset=8 - (local.get $5) - (local.tee $7 - (i32.sub - (i32.load - (local.get $3) - ) - (i32.load offset=8 - (local.get $5) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $5) - (local.tee $3 - (i32.sub - (i32.load offset=4 - (local.get $3) - ) - (i32.load offset=12 - (local.get $5) - ) - ) - ) - ) - (block $label$5 - (br_if $label$5 - (i32.gt_s - (local.get $3) - (i32.const -1) - ) - ) - (i32.store offset=12 - (local.get $5) - (local.tee $3 - (i32.add - (local.get $3) - (i32.const 1000000000) - ) - ) - ) - (i32.store offset=8 - (local.get $5) - (local.tee $7 - (i32.add - (local.get $7) - (i32.const -1) - ) - ) - ) - ) - (br_if $label$2 - (i32.lt_s - (local.get $7) - (i32.const 0) - ) - ) - (local.set $6 - (f64.add - (f64.div - (f64.convert_i32_s - (local.get $3) - ) - (f64.const 1e6) - ) - (f64.convert_i32_s - (i32.mul - (local.get $7) - (i32.const 1000) - ) - ) - ) - ) - ) - (block $label$6 - (block $label$7 - (block $label$8 - (br_if $label$8 - (local.tee $3 - (call $10) - ) - ) - (br_if $label$8 - (i32.ne - (i32.load offset=56 - (call $14) - ) - (i32.const 1) - ) - ) - (br_if $label$7 - (i32.ne - (i32.load offset=60 - (call $14) - ) - (i32.const 1) - ) - ) - ) - (local.set $8 - (f64.add - (local.get $6) - (call $fimport$4) - ) - ) - (loop $label$9 - (block $label$10 - (br_if $label$10 - (i32.eqz - (call $30 - (call $14) - ) - ) - ) - (local.set $7 - (i32.const 11) - ) - (br $label$1) - ) - (block $label$11 - (br_if $label$11 - (i32.eqz - (local.get $3) - ) - ) - (call $44) - ) - (br_if $label$2 - (f64.le - (local.tee $6 - (f64.sub - (local.get $8) - (call $fimport$4) - ) - ) - (f64.const 0) - ) - ) - (br_if $label$9 - (i32.eq - (local.tee $7 - (i32.sub - (i32.const 0) - (call $fimport$6 - (local.get $0) - (local.get $1) - (select - (select - (f64.const 1) - (local.tee $6 - (f64.min - (local.get $6) - (f64.const 100) - ) - ) - (f64.gt - (local.get $6) - (f64.const 1) - ) - ) - (local.get $6) - (local.get $3) - ) - ) - ) - ) - (i32.const 73) - ) - ) - (br $label$6) - ) - ) - (local.set $7 - (i32.sub - (i32.const 0) - (call $fimport$6 - (local.get $0) - (local.get $1) - (local.get $6) - ) - ) - ) - ) - (br_if $label$1 - (i32.eq - (local.get $7) - (i32.const 11) - ) - ) - (br_if $label$1 - (i32.eq - (local.get $7) - (i32.const 27) - ) - ) - (br_if $label$1 - (i32.eq - (local.get $7) - (i32.const 73) - ) - ) - (local.set $7 - (i32.const 0) - ) - (br $label$1) - ) - (local.set $7 - (i32.const 73) - ) - ) - (global.set $global$0 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - (local.get $7) - ) - (func $50 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) - (local $5 i32) - (global.set $global$0 - (local.tee $5 - (i32.sub - (global.get $global$0) - (i32.const 16) - ) - ) - ) - (drop - (call $48 - (i32.const 1) - (i32.add - (local.get $5) - (i32.const 12) - ) - ) - ) - (call $fimport$5 - (i32.const 1) - (i32.const 4) - ) - (local.set $0 - (call $49 - (local.get $0) - (local.get $1) - (local.get $2) - (local.get $3) - (local.get $4) - ) - ) - (call $fimport$5 - (i32.const 4) - (i32.const 1) - ) - (drop - (call $48 - (i32.load offset=12 - (local.get $5) - ) - (i32.const 0) - ) - ) - (global.set $global$0 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - (local.get $0) - ) - (func $51 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.and - (local.tee $2 - (i32.load - (local.get $0) - ) - ) - (i32.const 15) - ) - ) - (local.set $3 - (i32.const 0) - ) - (br_if $label$1 - (i32.eqz - (call $52 - (i32.add - (local.get $0) - (i32.const 4) - ) - (i32.const 0) - (i32.const 10) - ) - ) - ) - (local.set $2 - (i32.load - (local.get $0) - ) - ) - ) - (br_if $label$1 - (i32.ne - (local.tee $3 - (call $13 - (local.get $0) - ) - ) - (i32.const 10) - ) - ) - (local.set $4 - (i32.and - (i32.xor - (local.get $2) - (i32.const -1) - ) - (i32.const 128) - ) - ) - (local.set $5 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - (local.set $2 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - (local.set $3 - (i32.const 100) - ) - (block $label$3 - (loop $label$4 - (br_if $label$3 - (i32.eqz - (local.get $3) - ) - ) - (br_if $label$3 - (i32.eqz - (i32.load - (local.get $2) - ) - ) - ) - (local.set $3 - (i32.add - (local.get $3) - (i32.const -1) - ) - ) - (br_if $label$4 - (i32.eqz - (i32.load - (local.get $5) - ) - ) - ) - ) - ) - (br_if $label$1 - (i32.ne - (local.tee $3 - (call $13 - (local.get $0) - ) - ) - (i32.const 10) - ) - ) - (loop $label$5 - (block $label$6 - (br_if $label$6 - (i32.eqz - (local.tee $3 - (i32.load - (local.get $2) - ) - ) - ) - ) - (local.set $6 - (i32.load - (local.get $0) - ) - ) - (block $label$7 - (br_if $label$7 - (i32.eqz - (i32.and - (local.get $3) - (i32.const 1073741824) - ) - ) - ) - (br_if $label$6 - (i32.and - (local.get $6) - (i32.const 4) - ) - ) - ) - (block $label$8 - (br_if $label$8 - (i32.ne - (i32.and - (local.get $6) - (i32.const 3) - ) - (i32.const 2) - ) - ) - (br_if $label$8 - (i32.ne - (i32.and - (local.get $3) - (i32.const 2147483647) - ) - (i32.load offset=40 - (call $7) - ) - ) - ) - (return - (i32.const 16) - ) - ) - (call $53 - (local.get $5) - ) - (drop - (call $52 - (local.get $2) - (local.get $3) - (local.tee $6 - (i32.or - (local.get $3) - (i32.const -2147483648) - ) - ) - ) - ) - (local.set $3 - (call $50 - (local.get $2) - (local.get $6) - (i32.const 0) - (local.get $1) - (local.get $4) - ) - ) - (call $54 - (local.get $5) - ) - (br_if $label$6 - (i32.eqz - (local.get $3) - ) - ) - (br_if $label$1 - (i32.ne - (local.get $3) - (i32.const 27) - ) - ) - ) - (br_if $label$5 - (i32.eq - (local.tee $3 - (call $13 - (local.get $0) - ) - ) - (i32.const 10) - ) - ) - ) - ) - (local.get $3) - ) - (func $52 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (i32.atomic.rmw.cmpxchg - (local.get $0) - (local.get $1) - (local.get $2) - ) - ) - (func $53 (param $0 i32) - (drop - (i32.atomic.rmw.add - (local.get $0) - (i32.const 1) - ) - ) - ) - (func $54 (param $0 i32) - (drop - (i32.atomic.rmw.sub - (local.get $0) - (i32.const 1) - ) - ) - ) - (func $55 (param $0 i32) (result i32) - (block $label$1 - (br_if $label$1 - (i32.and - (i32.load8_u - (local.get $0) - ) - (i32.const 15) - ) - ) - (br_if $label$1 - (call $56 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - ) - (return - (i32.const 0) - ) - ) - (call $51 - (local.get $0) - (i32.const 0) - ) - ) - (func $56 (param $0 i32) (result i32) - (i32.atomic.rmw.cmpxchg - (local.get $0) - (i32.const 0) - (i32.const 10) - ) - ) - (func $57 (param $0 i32) (result i32) - (i32.store - (local.get $0) - (i32.const 0) - ) - (i32.const 0) - ) - (func $58 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (i32.store - (local.tee $3 - (i32.add - (local.tee $2 - (i32.sub - (global.get $global$0) - (i32.const 32) - ) - ) - (i32.const 24) - ) - ) - (i32.const 0) - ) - (i64.store - (local.tee $4 - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (i64.const 0) - ) - (i64.store - (local.tee $5 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - (i64.const 0) - ) - (i64.store - (local.get $2) - (i64.const 0) - ) - (i64.store align=4 - (local.get $0) - (i64.load - (local.get $2) - ) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 24) - ) - (i32.load - (local.get $3) - ) - ) - (i64.store align=4 - (i32.add - (local.get $0) - (i32.const 16) - ) - (i64.load - (local.get $4) - ) - ) - (i64.store align=4 - (i32.add - (local.get $0) - (i32.const 8) - ) - (i64.load - (local.get $5) - ) - ) - (block $label$1 - (br_if $label$1 - (i32.eqz - (local.get $1) - ) - ) - (i32.store - (local.get $0) - (i32.load - (local.get $1) - ) - ) - ) - (i32.const 0) - ) - (func $59 (param $0 i32) (result i32) - (i32.const 0) - ) - (func $60 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (local $10 i32) - (local $11 i32) - (block $label$1 - (br_if $label$1 - (i32.load offset=1844 - (i32.const 0) - ) - ) - (call $61) - ) - (block $label$2 - (block $label$3 - (br_if $label$3 - (i32.eqz - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 2) - ) - ) - ) - (local.set $1 - (i32.const 0) - ) - (br_if $label$2 - (call $55 - (i32.const 2316) - ) - ) - ) - (block $label$4 - (block $label$5 - (block $label$6 - (block $label$7 - (block $label$8 - (block $label$9 - (block $label$10 - (block $label$11 - (block $label$12 - (block $label$13 - (block $label$14 - (block $label$15 - (br_if $label$15 - (i32.gt_u - (local.get $0) - (i32.const 244) - ) - ) - (block $label$16 - (br_if $label$16 - (i32.eqz - (i32.and - (local.tee $0 - (i32.shr_u - (local.tee $2 - (i32.load offset=1868 - (i32.const 0) - ) - ) - (local.tee $1 - (i32.shr_u - (local.tee $3 - (select - (i32.const 16) - (i32.and - (i32.add - (local.get $0) - (i32.const 11) - ) - (i32.const -8) - ) - (i32.lt_u - (local.get $0) - (i32.const 11) - ) - ) - ) - (i32.const 3) - ) - ) - ) - ) - (i32.const 3) - ) - ) - ) - (local.set $1 - (i32.add - (local.tee $0 - (i32.load - (i32.add - (local.tee $5 - (i32.shl - (local.tee $4 - (i32.add - (i32.and - (i32.xor - (local.get $0) - (i32.const -1) - ) - (i32.const 1) - ) - (local.get $1) - ) - ) - (i32.const 3) - ) - ) - (i32.const 1916) - ) - ) - ) - (i32.const 8) - ) - ) - (block $label$17 - (block $label$18 - (br_if $label$18 - (i32.ne - (local.tee $3 - (i32.load offset=8 - (local.get $0) - ) - ) - (local.tee $5 - (i32.add - (local.get $5) - (i32.const 1908) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.and - (local.get $2) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - (br $label$17) - ) - (i32.store offset=12 - (local.get $3) - (local.get $5) - ) - (i32.store offset=8 - (local.get $5) - (local.get $3) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.tee $4 - (i32.shl - (local.get $4) - (i32.const 3) - ) - ) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $0) - (local.get $4) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $0) - ) - (i32.const 1) - ) - ) - (br $label$4) - ) - (br_if $label$14 - (i32.le_u - (local.get $3) - (local.tee $6 - (i32.load offset=1876 - (i32.const 0) - ) - ) - ) - ) - (block $label$19 - (br_if $label$19 - (i32.eqz - (local.get $0) - ) - ) - (block $label$20 - (block $label$21 - (br_if $label$21 - (i32.ne - (local.tee $1 - (i32.load offset=8 - (local.tee $0 - (i32.load - (i32.add - (local.tee $5 - (i32.shl - (local.tee $4 - (i32.add - (i32.or - (i32.or - (i32.or - (i32.or - (local.tee $4 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.shr_u - (local.tee $0 - (i32.add - (i32.and - (local.tee $0 - (i32.and - (i32.shl - (local.get $0) - (local.get $1) - ) - (i32.or - (local.tee $0 - (i32.shl - (i32.const 2) - (local.get $1) - ) - ) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - ) - ) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - (i32.const -1) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (local.get $0) - (i32.const 12) - ) - (i32.const 16) - ) - ) - ) - ) - (i32.const 5) - ) - (i32.const 8) - ) - ) - (local.get $0) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $1) - (local.get $4) - ) - ) - (i32.const 2) - ) - (i32.const 4) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $0) - (local.get $1) - ) - ) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $0) - (local.get $1) - ) - ) - (i32.const 1) - ) - (i32.const 1) - ) - ) - ) - (i32.shr_u - (local.get $0) - (local.get $1) - ) - ) - ) - (i32.const 3) - ) - ) - (i32.const 1916) - ) - ) - ) - ) - ) - (local.tee $5 - (i32.add - (local.get $5) - (i32.const 1908) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (local.tee $2 - (i32.and - (local.get $2) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - ) - (br $label$20) - ) - (i32.store offset=12 - (local.get $1) - (local.get $5) - ) - (i32.store offset=8 - (local.get $5) - (local.get $1) - ) - ) - (local.set $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $5 - (i32.add - (local.get $0) - (local.get $3) - ) - ) - (i32.or - (local.tee $4 - (i32.sub - (local.tee $7 - (i32.shl - (local.get $4) - (i32.const 3) - ) - ) - (local.get $3) - ) - ) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $0) - (local.get $7) - ) - (local.get $4) - ) - (block $label$22 - (br_if $label$22 - (i32.eqz - (local.get $6) - ) - ) - (local.set $3 - (i32.add - (i32.shl - (local.tee $7 - (i32.shr_u - (local.get $6) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (local.set $0 - (i32.load offset=1888 - (i32.const 0) - ) - ) - (block $label$23 - (block $label$24 - (br_if $label$24 - (i32.and - (local.get $2) - (local.tee $7 - (i32.shl - (i32.const 1) - (local.get $7) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $2) - (local.get $7) - ) - ) - (local.set $7 - (local.get $3) - ) - (br $label$23) - ) - (local.set $7 - (i32.load offset=8 - (local.get $3) - ) - ) - ) - (i32.store offset=8 - (local.get $3) - (local.get $0) - ) - (i32.store offset=12 - (local.get $7) - (local.get $0) - ) - (i32.store offset=12 - (local.get $0) - (local.get $3) - ) - (i32.store offset=8 - (local.get $0) - (local.get $7) - ) - ) - (i32.store offset=1888 - (i32.const 0) - (local.get $5) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $4) - ) - (br $label$4) - ) - (br_if $label$14 - (i32.eqz - (local.tee $8 - (i32.load offset=1872 - (i32.const 0) - ) - ) - ) - ) - (local.set $1 - (i32.sub - (i32.and - (i32.load offset=4 - (local.tee $5 - (i32.load - (i32.add - (i32.shl - (i32.add - (i32.or - (i32.or - (i32.or - (i32.or - (local.tee $4 - (i32.and - (i32.shr_u - (local.tee $1 - (i32.shr_u - (local.tee $0 - (i32.add - (i32.and - (local.get $8) - (i32.sub - (i32.const 0) - (local.get $8) - ) - ) - (i32.const -1) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (local.get $0) - (i32.const 12) - ) - (i32.const 16) - ) - ) - ) - ) - (i32.const 5) - ) - (i32.const 8) - ) - ) - (local.get $0) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $1) - (local.get $4) - ) - ) - (i32.const 2) - ) - (i32.const 4) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $0) - (local.get $1) - ) - ) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $0) - (local.get $1) - ) - ) - (i32.const 1) - ) - (i32.const 1) - ) - ) - ) - (i32.shr_u - (local.get $0) - (local.get $1) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - ) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.set $4 - (local.get $5) - ) - (block $label$25 - (loop $label$26 - (block $label$27 - (br_if $label$27 - (local.tee $0 - (i32.load offset=16 - (local.get $4) - ) - ) - ) - (br_if $label$25 - (i32.eqz - (local.tee $0 - (i32.load - (i32.add - (local.get $4) - (i32.const 20) - ) - ) - ) - ) - ) - ) - (local.set $1 - (select - (local.tee $4 - (i32.sub - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.get $1) - (local.tee $4 - (i32.lt_u - (local.get $4) - (local.get $1) - ) - ) - ) - ) - (local.set $5 - (select - (local.get $0) - (local.get $5) - (local.get $4) - ) - ) - (local.set $4 - (local.get $0) - ) - (br $label$26) - ) - ) - (br_if $label$13 - (i32.le_u - (local.tee $9 - (i32.add - (local.get $5) - (local.get $3) - ) - ) - (local.get $5) - ) - ) - (local.set $10 - (i32.load offset=24 - (local.get $5) - ) - ) - (block $label$28 - (br_if $label$28 - (i32.eq - (local.tee $7 - (i32.load offset=12 - (local.get $5) - ) - ) - (local.get $5) - ) - ) - (drop - (i32.gt_u - (i32.load offset=1884 - (i32.const 0) - ) - (local.tee $0 - (i32.load offset=8 - (local.get $5) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $0) - (local.get $7) - ) - (i32.store offset=8 - (local.get $7) - (local.get $0) - ) - (br $label$5) - ) - (block $label$29 - (br_if $label$29 - (local.tee $0 - (i32.load - (local.tee $4 - (i32.add - (local.get $5) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$12 - (i32.eqz - (local.tee $0 - (i32.load offset=16 - (local.get $5) - ) - ) - ) - ) - (local.set $4 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - ) - (loop $label$30 - (local.set $11 - (local.get $4) - ) - (br_if $label$30 - (local.tee $0 - (i32.load - (local.tee $4 - (i32.add - (local.tee $7 - (local.get $0) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $4 - (i32.add - (local.get $7) - (i32.const 16) - ) - ) - (br_if $label$30 - (local.tee $0 - (i32.load offset=16 - (local.get $7) - ) - ) - ) - ) - (i32.store - (local.get $11) - (i32.const 0) - ) - (br $label$5) - ) - (local.set $3 - (i32.const -1) - ) - (br_if $label$14 - (i32.gt_u - (local.get $0) - (i32.const -65) - ) - ) - (local.set $3 - (i32.and - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 11) - ) - ) - (i32.const -8) - ) - ) - (br_if $label$14 - (i32.eqz - (local.tee $6 - (i32.load offset=1872 - (i32.const 0) - ) - ) - ) - ) - (local.set $11 - (i32.const 31) - ) - (block $label$31 - (br_if $label$31 - (i32.gt_u - (local.get $3) - (i32.const 16777215) - ) - ) - (local.set $11 - (i32.add - (i32.or - (i32.shl - (local.tee $0 - (i32.sub - (i32.shr_u - (i32.shl - (local.tee $4 - (i32.shl - (local.tee $1 - (i32.shl - (local.tee $0 - (i32.shr_u - (local.get $0) - (i32.const 8) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (i32.add - (local.get $1) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (i32.add - (local.get $4) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - (i32.const 15) - ) - (i32.or - (i32.or - (local.get $0) - (local.get $1) - ) - (local.get $4) - ) - ) - ) - (i32.const 1) - ) - (i32.and - (i32.shr_u - (local.get $3) - (i32.add - (local.get $0) - (i32.const 21) - ) - ) - (i32.const 1) - ) - ) - (i32.const 28) - ) - ) - ) - (local.set $1 - (i32.sub - (i32.const 0) - (local.get $3) - ) - ) - (block $label$32 - (block $label$33 - (block $label$34 - (block $label$35 - (br_if $label$35 - (local.tee $4 - (i32.load - (i32.add - (i32.shl - (local.get $11) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - ) - (local.set $0 - (i32.const 0) - ) - (local.set $7 - (i32.const 0) - ) - (br $label$34) - ) - (local.set $0 - (i32.const 0) - ) - (local.set $5 - (i32.shl - (local.get $3) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $11) - (i32.const 1) - ) - ) - (i32.eq - (local.get $11) - (i32.const 31) - ) - ) - ) - ) - (local.set $7 - (i32.const 0) - ) - (loop $label$36 - (block $label$37 - (br_if $label$37 - (i32.ge_u - (local.tee $2 - (i32.sub - (i32.and - (i32.load offset=4 - (local.get $4) - ) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.get $1) - ) - ) - (local.set $1 - (local.get $2) - ) - (local.set $7 - (local.get $4) - ) - (br_if $label$37 - (local.get $2) - ) - (local.set $1 - (i32.const 0) - ) - (local.set $7 - (local.get $4) - ) - (local.set $0 - (local.get $4) - ) - (br $label$33) - ) - (local.set $0 - (select - (select - (local.get $0) - (local.tee $2 - (i32.load - (i32.add - (local.get $4) - (i32.const 20) - ) - ) - ) - (i32.eq - (local.get $2) - (local.tee $4 - (i32.load - (i32.add - (i32.add - (local.get $4) - (i32.and - (i32.shr_u - (local.get $5) - (i32.const 29) - ) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ) - ) - (local.get $0) - (local.get $2) - ) - ) - (local.set $5 - (i32.shl - (local.get $5) - (i32.const 1) - ) - ) - (br_if $label$36 - (local.get $4) - ) - ) - ) - (block $label$38 - (br_if $label$38 - (i32.or - (local.get $0) - (local.get $7) - ) - ) - (br_if $label$14 - (i32.eqz - (local.tee $0 - (i32.and - (i32.or - (local.tee $0 - (i32.shl - (i32.const 2) - (local.get $11) - ) - ) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - (local.get $6) - ) - ) - ) - ) - (local.set $0 - (i32.load - (i32.add - (i32.shl - (i32.add - (i32.or - (i32.or - (i32.or - (i32.or - (local.tee $5 - (i32.and - (i32.shr_u - (local.tee $4 - (i32.shr_u - (local.tee $0 - (i32.add - (i32.and - (local.get $0) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - (i32.const -1) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (local.get $0) - (i32.const 12) - ) - (i32.const 16) - ) - ) - ) - ) - (i32.const 5) - ) - (i32.const 8) - ) - ) - (local.get $0) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $4) - (local.get $5) - ) - ) - (i32.const 2) - ) - (i32.const 4) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $0) - (local.get $4) - ) - ) - (i32.const 1) - ) - (i32.const 2) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (local.tee $0 - (i32.shr_u - (local.get $0) - (local.get $4) - ) - ) - (i32.const 1) - ) - (i32.const 1) - ) - ) - ) - (i32.shr_u - (local.get $0) - (local.get $4) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - ) - (br_if $label$32 - (i32.eqz - (local.get $0) - ) - ) - ) - (loop $label$39 - (local.set $5 - (i32.lt_u - (local.tee $2 - (i32.sub - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const -8) - ) - (local.get $3) - ) - ) - (local.get $1) - ) - ) - (block $label$40 - (br_if $label$40 - (local.tee $4 - (i32.load offset=16 - (local.get $0) - ) - ) - ) - (local.set $4 - (i32.load - (i32.add - (local.get $0) - (i32.const 20) - ) - ) - ) - ) - (local.set $1 - (select - (local.get $2) - (local.get $1) - (local.get $5) - ) - ) - (local.set $7 - (select - (local.get $0) - (local.get $7) - (local.get $5) - ) - ) - (local.set $0 - (local.get $4) - ) - (br_if $label$39 - (local.get $4) - ) - ) - ) - (br_if $label$14 - (i32.eqz - (local.get $7) - ) - ) - (br_if $label$14 - (i32.ge_u - (local.get $1) - (i32.sub - (i32.load offset=1876 - (i32.const 0) - ) - (local.get $3) - ) - ) - ) - (br_if $label$13 - (i32.le_u - (local.tee $11 - (i32.add - (local.get $7) - (local.get $3) - ) - ) - (local.get $7) - ) - ) - (local.set $8 - (i32.load offset=24 - (local.get $7) - ) - ) - (block $label$41 - (br_if $label$41 - (i32.eq - (local.tee $5 - (i32.load offset=12 - (local.get $7) - ) - ) - (local.get $7) - ) - ) - (drop - (i32.gt_u - (i32.load offset=1884 - (i32.const 0) - ) - (local.tee $0 - (i32.load offset=8 - (local.get $7) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $0) - (local.get $5) - ) - (i32.store offset=8 - (local.get $5) - (local.get $0) - ) - (br $label$6) - ) - (block $label$42 - (br_if $label$42 - (local.tee $0 - (i32.load - (local.tee $4 - (i32.add - (local.get $7) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$11 - (i32.eqz - (local.tee $0 - (i32.load offset=16 - (local.get $7) - ) - ) - ) - ) - (local.set $4 - (i32.add - (local.get $7) - (i32.const 16) - ) - ) - ) - (loop $label$43 - (local.set $2 - (local.get $4) - ) - (br_if $label$43 - (local.tee $0 - (i32.load - (local.tee $4 - (i32.add - (local.tee $5 - (local.get $0) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $4 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - (br_if $label$43 - (local.tee $0 - (i32.load offset=16 - (local.get $5) - ) - ) - ) - ) - (i32.store - (local.get $2) - (i32.const 0) - ) - (br $label$6) - ) - (block $label$44 - (br_if $label$44 - (i32.lt_u - (local.tee $0 - (i32.load offset=1876 - (i32.const 0) - ) - ) - (local.get $3) - ) - ) - (local.set $1 - (i32.load offset=1888 - (i32.const 0) - ) - ) - (block $label$45 - (block $label$46 - (br_if $label$46 - (i32.lt_u - (local.tee $4 - (i32.sub - (local.get $0) - (local.get $3) - ) - ) - (i32.const 16) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $4) - ) - (i32.store offset=1888 - (i32.const 0) - (local.tee $5 - (i32.add - (local.get $1) - (local.get $3) - ) - ) - ) - (i32.store offset=4 - (local.get $5) - (i32.or - (local.get $4) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $0) - ) - (local.get $4) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (br $label$45) - ) - (i32.store offset=1888 - (i32.const 0) - (i32.const 0) - ) - (i32.store offset=1876 - (i32.const 0) - (i32.const 0) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $1) - (local.get $0) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $0) - ) - (i32.const 1) - ) - ) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 8) - ) - ) - (br $label$4) - ) - (block $label$47 - (br_if $label$47 - (i32.le_u - (local.tee $0 - (i32.load offset=1880 - (i32.const 0) - ) - ) - (local.get $3) - ) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $1 - (i32.sub - (local.get $0) - (local.get $3) - ) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.tee $4 - (i32.add - (local.tee $0 - (i32.load offset=1892 - (i32.const 0) - ) - ) - (local.get $3) - ) - ) - ) - (i32.store offset=4 - (local.get $4) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (local.set $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - (br $label$4) - ) - (local.set $1 - (i32.const 0) - ) - (block $label$48 - (br_if $label$48 - (i32.load offset=1844 - (i32.const 0) - ) - ) - (call $61) - ) - (br_if $label$4 - (i32.le_u - (local.tee $7 - (i32.and - (i32.add - (local.tee $0 - (i32.load offset=1852 - (i32.const 0) - ) - ) - (local.tee $11 - (i32.add - (local.get $3) - (i32.const 47) - ) - ) - ) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - ) - (local.get $3) - ) - ) - (local.set $1 - (i32.const 0) - ) - (block $label$49 - (br_if $label$49 - (i32.eqz - (local.tee $0 - (i32.load offset=2308 - (i32.const 0) - ) - ) - ) - ) - (br_if $label$4 - (i32.le_u - (local.tee $5 - (i32.add - (local.tee $4 - (i32.load offset=2300 - (i32.const 0) - ) - ) - (local.get $7) - ) - ) - (local.get $4) - ) - ) - (br_if $label$4 - (i32.gt_u - (local.get $5) - (local.get $0) - ) - ) - ) - (local.set $2 - (i32.const 0) - ) - (local.set $5 - (i32.const -1) - ) - (br_if $label$7 - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 4) - ) - ) - (local.set $6 - (i32.const 0) - ) - (block $label$50 - (block $label$51 - (block $label$52 - (br_if $label$52 - (i32.eqz - (local.tee $1 - (i32.load offset=1892 - (i32.const 0) - ) - ) - ) - ) - (local.set $0 - (i32.const 2344) - ) - (loop $label$53 - (block $label$54 - (br_if $label$54 - (i32.gt_u - (local.tee $4 - (i32.load - (local.get $0) - ) - ) - (local.get $1) - ) - ) - (br_if $label$51 - (i32.gt_u - (i32.add - (local.get $4) - (i32.load offset=4 - (local.get $0) - ) - ) - (local.get $1) - ) - ) - ) - (br_if $label$53 - (local.tee $0 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - ) - ) - (drop - (call $55 - (i32.const 2368) - ) - ) - (br_if $label$9 - (i32.eq - (local.tee $5 - (call $66 - (i32.const 0) - ) - ) - (i32.const -1) - ) - ) - (local.set $2 - (local.get $7) - ) - (block $label$55 - (br_if $label$55 - (i32.eqz - (i32.and - (local.tee $1 - (i32.add - (local.tee $0 - (i32.load offset=1848 - (i32.const 0) - ) - ) - (i32.const -1) - ) - ) - (local.get $5) - ) - ) - ) - (local.set $2 - (i32.add - (i32.sub - (local.get $7) - (local.get $5) - ) - (i32.and - (i32.add - (local.get $1) - (local.get $5) - ) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - ) - ) - ) - (block $label$56 - (br_if $label$56 - (i32.gt_u - (local.get $2) - (local.get $3) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$9) - ) - (block $label$57 - (br_if $label$57 - (i32.le_u - (local.get $2) - (i32.const 2147483646) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$9) - ) - (local.set $6 - (i32.const 0) - ) - (block $label$58 - (br_if $label$58 - (i32.eqz - (local.tee $0 - (i32.load offset=2308 - (i32.const 0) - ) - ) - ) - ) - (br_if $label$9 - (i32.le_u - (local.tee $4 - (i32.add - (local.tee $1 - (i32.load offset=2300 - (i32.const 0) - ) - ) - (local.get $2) - ) - ) - (local.get $1) - ) - ) - (br_if $label$9 - (i32.gt_u - (local.get $4) - (local.get $0) - ) - ) - ) - (br_if $label$50 - (i32.ne - (local.tee $0 - (call $66 - (local.get $2) - ) - ) - (local.get $5) - ) - ) - (br $label$8) - ) - (drop - (call $55 - (i32.const 2368) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br_if $label$9 - (i32.gt_u - (local.tee $2 - (i32.and - (i32.add - (i32.sub - (local.get $11) - (i32.load offset=1880 - (i32.const 0) - ) - ) - (local.tee $1 - (i32.load offset=1852 - (i32.const 0) - ) - ) - ) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - (i32.const 2147483646) - ) - ) - (br_if $label$10 - (i32.eq - (local.tee $5 - (call $66 - (local.get $2) - ) - ) - (i32.add - (i32.load - (local.get $0) - ) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - ) - (local.set $0 - (local.get $5) - ) - ) - (local.set $6 - (i32.const 0) - ) - (block $label$59 - (br_if $label$59 - (i32.le_u - (i32.add - (local.get $3) - (i32.const 48) - ) - (local.get $2) - ) - ) - (br_if $label$59 - (i32.eq - (local.get $0) - (i32.const -1) - ) - ) - (block $label$60 - (br_if $label$60 - (i32.le_u - (local.tee $1 - (i32.and - (i32.add - (i32.sub - (local.get $11) - (local.get $2) - ) - (local.tee $1 - (i32.load offset=1852 - (i32.const 0) - ) - ) - ) - (i32.sub - (i32.const 0) - (local.get $1) - ) - ) - ) - (i32.const 2147483646) - ) - ) - (local.set $5 - (local.get $0) - ) - (br $label$8) - ) - (block $label$61 - (br_if $label$61 - (i32.eq - (call $66 - (local.get $1) - ) - (i32.const -1) - ) - ) - (local.set $2 - (i32.add - (local.get $1) - (local.get $2) - ) - ) - (local.set $5 - (local.get $0) - ) - (br $label$8) - ) - (drop - (call $66 - (i32.sub - (i32.const 0) - (local.get $2) - ) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$9) - ) - (local.set $5 - (local.get $0) - ) - (br_if $label$8 - (i32.ne - (local.get $0) - (i32.const -1) - ) - ) - (br $label$9) - ) - (unreachable) - ) - (local.set $7 - (i32.const 0) - ) - (br $label$5) - ) - (local.set $5 - (i32.const 0) - ) - (br $label$6) - ) - (local.set $6 - (local.get $2) - ) - (br_if $label$8 - (i32.ne - (local.get $5) - (i32.const -1) - ) - ) - ) - (i32.store offset=2312 - (i32.const 0) - (i32.or - (i32.load offset=2312 - (i32.const 0) - ) - (i32.const 4) - ) - ) - (local.set $5 - (i32.const -1) - ) - (local.set $2 - (local.get $6) - ) - ) - (drop - (call $20 - (i32.const 2368) - ) - ) - ) - (block $label$62 - (block $label$63 - (block $label$64 - (br_if $label$64 - (i32.gt_u - (local.get $7) - (i32.const 2147483646) - ) - ) - (br_if $label$64 - (i32.ne - (local.get $5) - (i32.const -1) - ) - ) - (drop - (call $55 - (i32.const 2368) - ) - ) - (local.set $5 - (call $66 - (local.get $7) - ) - ) - (local.set $0 - (call $66 - (i32.const 0) - ) - ) - (drop - (call $20 - (i32.const 2368) - ) - ) - (br_if $label$62 - (i32.ge_u - (local.get $5) - (local.get $0) - ) - ) - (br_if $label$62 - (i32.eq - (local.get $5) - (i32.const -1) - ) - ) - (br_if $label$62 - (i32.eq - (local.get $0) - (i32.const -1) - ) - ) - (br_if $label$63 - (i32.gt_u - (local.tee $2 - (i32.sub - (local.get $0) - (local.get $5) - ) - ) - (i32.add - (local.get $3) - (i32.const 40) - ) - ) - ) - (br $label$62) - ) - (br_if $label$62 - (i32.eq - (local.get $5) - (i32.const -1) - ) - ) - ) - (i32.store offset=2300 - (i32.const 0) - (local.tee $0 - (i32.add - (i32.load offset=2300 - (i32.const 0) - ) - (local.get $2) - ) - ) - ) - (block $label$65 - (br_if $label$65 - (i32.le_u - (local.get $0) - (i32.load offset=2304 - (i32.const 0) - ) - ) - ) - (i32.store offset=2304 - (i32.const 0) - (local.get $0) - ) - ) - (block $label$66 - (block $label$67 - (block $label$68 - (block $label$69 - (br_if $label$69 - (i32.eqz - (local.tee $1 - (i32.load offset=1892 - (i32.const 0) - ) - ) - ) - ) - (local.set $0 - (i32.const 2344) - ) - (loop $label$70 - (br_if $label$68 - (i32.eq - (local.get $5) - (i32.add - (local.tee $4 - (i32.load - (local.get $0) - ) - ) - (local.tee $7 - (i32.load offset=4 - (local.get $0) - ) - ) - ) - ) - ) - (br_if $label$70 - (local.tee $0 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - (br $label$67) - ) - ) - (block $label$71 - (block $label$72 - (br_if $label$72 - (i32.eqz - (local.tee $0 - (i32.load offset=1884 - (i32.const 0) - ) - ) - ) - ) - (br_if $label$71 - (i32.ge_u - (local.get $5) - (local.get $0) - ) - ) - ) - (i32.store offset=1884 - (i32.const 0) - (local.get $5) - ) - ) - (local.set $0 - (i32.const 0) - ) - (i32.store offset=2348 - (i32.const 0) - (local.get $2) - ) - (i32.store offset=2344 - (i32.const 0) - (local.get $5) - ) - (i32.store offset=1900 - (i32.const 0) - (i32.const -1) - ) - (i32.store offset=1904 - (i32.const 0) - (i32.load offset=1844 - (i32.const 0) - ) - ) - (i32.store offset=2356 - (i32.const 0) - (i32.const 0) - ) - (loop $label$73 - (i32.store - (i32.add - (local.tee $1 - (i32.shl - (local.get $0) - (i32.const 3) - ) - ) - (i32.const 1916) - ) - (local.tee $4 - (i32.add - (local.get $1) - (i32.const 1908) - ) - ) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 1920) - ) - (local.get $4) - ) - (br_if $label$73 - (i32.ne - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - (i32.const 32) - ) - ) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $4 - (i32.sub - (local.tee $0 - (i32.add - (local.get $2) - (i32.const -40) - ) - ) - (local.tee $1 - (select - (i32.and - (i32.sub - (i32.const -8) - (local.get $5) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (i32.add - (local.get $5) - (i32.const 8) - ) - (i32.const 7) - ) - ) - ) - ) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.tee $1 - (i32.add - (local.get $5) - (local.get $1) - ) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $4) - (i32.const 1) - ) - ) - (i32.store offset=4 - (i32.add - (local.get $5) - (local.get $0) - ) - (i32.const 40) - ) - (i32.store offset=1896 - (i32.const 0) - (i32.load offset=1860 - (i32.const 0) - ) - ) - (br $label$66) - ) - (br_if $label$67 - (i32.le_u - (local.get $5) - (local.get $1) - ) - ) - (br_if $label$67 - (i32.gt_u - (local.get $4) - (local.get $1) - ) - ) - (br_if $label$67 - (i32.and - (i32.load offset=12 - (local.get $0) - ) - (i32.const 8) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.add - (local.get $7) - (local.get $2) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.tee $4 - (i32.add - (local.get $1) - (local.tee $0 - (select - (i32.and - (i32.sub - (i32.const -8) - (local.get $1) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (i32.add - (local.get $1) - (i32.const 8) - ) - (i32.const 7) - ) - ) - ) - ) - ) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $0 - (i32.sub - (local.tee $5 - (i32.add - (i32.load offset=1880 - (i32.const 0) - ) - (local.get $2) - ) - ) - (local.get $0) - ) - ) - ) - (i32.store offset=4 - (local.get $4) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store offset=4 - (i32.add - (local.get $1) - (local.get $5) - ) - (i32.const 40) - ) - (i32.store offset=1896 - (i32.const 0) - (i32.load offset=1860 - (i32.const 0) - ) - ) - (br $label$66) - ) - (block $label$74 - (br_if $label$74 - (i32.ge_u - (local.get $5) - (local.tee $7 - (i32.load offset=1884 - (i32.const 0) - ) - ) - ) - ) - (i32.store offset=1884 - (i32.const 0) - (local.get $5) - ) - (local.set $7 - (local.get $5) - ) - ) - (local.set $4 - (i32.add - (local.get $5) - (local.get $2) - ) - ) - (local.set $0 - (i32.const 2344) - ) - (block $label$75 - (block $label$76 - (block $label$77 - (block $label$78 - (block $label$79 - (block $label$80 - (block $label$81 - (loop $label$82 - (br_if $label$81 - (i32.eq - (i32.load - (local.get $0) - ) - (local.get $4) - ) - ) - (br_if $label$82 - (local.tee $0 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - (br $label$80) - ) - ) - (br_if $label$79 - (i32.eqz - (i32.and - (i32.load8_u offset=12 - (local.get $0) - ) - (i32.const 8) - ) - ) - ) - ) - (local.set $0 - (i32.const 2344) - ) - (loop $label$83 - (block $label$84 - (br_if $label$84 - (i32.gt_u - (local.tee $4 - (i32.load - (local.get $0) - ) - ) - (local.get $1) - ) - ) - (br_if $label$78 - (i32.gt_u - (local.tee $4 - (i32.add - (local.get $4) - (i32.load offset=4 - (local.get $0) - ) - ) - ) - (local.get $1) - ) - ) - ) - (local.set $0 - (i32.load offset=8 - (local.get $0) - ) - ) - (br $label$83) - ) - ) - (i32.store - (local.get $0) - (local.get $5) - ) - (i32.store offset=4 - (local.get $0) - (i32.add - (i32.load offset=4 - (local.get $0) - ) - (local.get $2) - ) - ) - (i32.store offset=4 - (local.tee $11 - (i32.add - (local.get $5) - (select - (i32.and - (i32.sub - (i32.const -8) - (local.get $5) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (i32.add - (local.get $5) - (i32.const 8) - ) - (i32.const 7) - ) - ) - ) - ) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (local.set $4 - (i32.sub - (i32.sub - (local.tee $2 - (i32.add - (local.get $4) - (select - (i32.and - (i32.sub - (i32.const -8) - (local.get $4) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (i32.add - (local.get $4) - (i32.const 8) - ) - (i32.const 7) - ) - ) - ) - ) - (local.get $11) - ) - (local.get $3) - ) - ) - (local.set $3 - (i32.add - (local.get $11) - (local.get $3) - ) - ) - (block $label$85 - (br_if $label$85 - (i32.ne - (local.get $1) - (local.get $2) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.get $3) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $0 - (i32.add - (i32.load offset=1880 - (i32.const 0) - ) - (local.get $4) - ) - ) - ) - (i32.store offset=4 - (local.get $3) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (br $label$76) - ) - (block $label$86 - (br_if $label$86 - (i32.ne - (i32.load offset=1888 - (i32.const 0) - ) - (local.get $2) - ) - ) - (i32.store offset=1888 - (i32.const 0) - (local.get $3) - ) - (i32.store offset=1876 - (i32.const 0) - (local.tee $0 - (i32.add - (i32.load offset=1876 - (i32.const 0) - ) - (local.get $4) - ) - ) - ) - (i32.store offset=4 - (local.get $3) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $3) - (local.get $0) - ) - (local.get $0) - ) - (br $label$76) - ) - (block $label$87 - (br_if $label$87 - (i32.ne - (i32.and - (local.tee $0 - (i32.load offset=4 - (local.get $2) - ) - ) - (i32.const 3) - ) - (i32.const 1) - ) - ) - (local.set $6 - (i32.and - (local.get $0) - (i32.const -8) - ) - ) - (block $label$88 - (block $label$89 - (br_if $label$89 - (i32.gt_u - (local.get $0) - (i32.const 255) - ) - ) - (drop - (i32.eq - (local.tee $1 - (i32.load offset=8 - (local.get $2) - ) - ) - (local.tee $5 - (i32.add - (i32.shl - (local.tee $7 - (i32.shr_u - (local.get $0) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - ) - ) - (block $label$90 - (br_if $label$90 - (i32.ne - (local.tee $0 - (i32.load offset=12 - (local.get $2) - ) - ) - (local.get $1) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.and - (i32.load offset=1868 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $7) - ) - ) - ) - (br $label$88) - ) - (drop - (i32.eq - (local.get $0) - (local.get $5) - ) - ) - (i32.store offset=12 - (local.get $1) - (local.get $0) - ) - (i32.store offset=8 - (local.get $0) - (local.get $1) - ) - (br $label$88) - ) - (local.set $8 - (i32.load offset=24 - (local.get $2) - ) - ) - (block $label$91 - (block $label$92 - (br_if $label$92 - (i32.eq - (local.tee $5 - (i32.load offset=12 - (local.get $2) - ) - ) - (local.get $2) - ) - ) - (drop - (i32.gt_u - (local.get $7) - (local.tee $0 - (i32.load offset=8 - (local.get $2) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $0) - (local.get $5) - ) - (i32.store offset=8 - (local.get $5) - (local.get $0) - ) - (br $label$91) - ) - (block $label$93 - (br_if $label$93 - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $2) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$93 - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - ) - ) - ) - (local.set $5 - (i32.const 0) - ) - (br $label$91) - ) - (loop $label$94 - (local.set $7 - (local.get $0) - ) - (br_if $label$94 - (local.tee $1 - (i32.load - (local.tee $0 - (i32.add - (local.tee $5 - (local.get $1) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $0 - (i32.add - (local.get $5) - (i32.const 16) - ) - ) - (br_if $label$94 - (local.tee $1 - (i32.load offset=16 - (local.get $5) - ) - ) - ) - ) - (i32.store - (local.get $7) - (i32.const 0) - ) - ) - (br_if $label$88 - (i32.eqz - (local.get $8) - ) - ) - (block $label$95 - (block $label$96 - (br_if $label$96 - (i32.ne - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $1 - (i32.load offset=28 - (local.get $2) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - (local.get $2) - ) - ) - (i32.store - (local.get $0) - (local.get $5) - ) - (br_if $label$95 - (local.get $5) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.and - (i32.load offset=1872 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $1) - ) - ) - ) - (br $label$88) - ) - (i32.store - (i32.add - (local.get $8) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $8) - ) - (local.get $2) - ) - ) - ) - (local.get $5) - ) - (br_if $label$88 - (i32.eqz - (local.get $5) - ) - ) - ) - (i32.store offset=24 - (local.get $5) - (local.get $8) - ) - (block $label$97 - (br_if $label$97 - (i32.eqz - (local.tee $0 - (i32.load offset=16 - (local.get $2) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $5) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $5) - ) - ) - (br_if $label$88 - (i32.eqz - (local.tee $0 - (i32.load offset=20 - (local.get $2) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 20) - ) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $5) - ) - ) - (local.set $4 - (i32.add - (local.get $6) - (local.get $4) - ) - ) - (local.set $2 - (i32.add - (local.get $2) - (local.get $6) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (i32.and - (i32.load offset=4 - (local.get $2) - ) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $3) - (i32.or - (local.get $4) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $3) - (local.get $4) - ) - (local.get $4) - ) - (block $label$98 - (br_if $label$98 - (i32.gt_u - (local.get $4) - (i32.const 255) - ) - ) - (local.set $0 - (i32.add - (i32.shl - (local.tee $1 - (i32.shr_u - (local.get $4) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (block $label$99 - (block $label$100 - (br_if $label$100 - (i32.and - (local.tee $4 - (i32.load offset=1868 - (i32.const 0) - ) - ) - (local.tee $1 - (i32.shl - (i32.const 1) - (local.get $1) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $4) - (local.get $1) - ) - ) - (local.set $1 - (local.get $0) - ) - (br $label$99) - ) - (local.set $1 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - (i32.store offset=8 - (local.get $0) - (local.get $3) - ) - (i32.store offset=12 - (local.get $1) - (local.get $3) - ) - (i32.store offset=12 - (local.get $3) - (local.get $0) - ) - (i32.store offset=8 - (local.get $3) - (local.get $1) - ) - (br $label$76) - ) - (local.set $0 - (i32.const 31) - ) - (block $label$101 - (br_if $label$101 - (i32.gt_u - (local.get $4) - (i32.const 16777215) - ) - ) - (local.set $0 - (i32.add - (i32.or - (i32.shl - (local.tee $0 - (i32.sub - (i32.shr_u - (i32.shl - (local.tee $5 - (i32.shl - (local.tee $1 - (i32.shl - (local.tee $0 - (i32.shr_u - (local.get $4) - (i32.const 8) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (local.tee $1 - (i32.and - (i32.shr_u - (i32.add - (local.get $1) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - ) - ) - (local.tee $5 - (i32.and - (i32.shr_u - (i32.add - (local.get $5) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - (i32.const 15) - ) - (i32.or - (i32.or - (local.get $0) - (local.get $1) - ) - (local.get $5) - ) - ) - ) - (i32.const 1) - ) - (i32.and - (i32.shr_u - (local.get $4) - (i32.add - (local.get $0) - (i32.const 21) - ) - ) - (i32.const 1) - ) - ) - (i32.const 28) - ) - ) - ) - (i32.store offset=28 - (local.get $3) - (local.get $0) - ) - (i64.store offset=16 align=4 - (local.get $3) - (i64.const 0) - ) - (local.set $1 - (i32.add - (i32.shl - (local.get $0) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - (block $label$102 - (block $label$103 - (br_if $label$103 - (i32.and - (local.tee $5 - (i32.load offset=1872 - (i32.const 0) - ) - ) - (local.tee $7 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.or - (local.get $5) - (local.get $7) - ) - ) - (i32.store - (local.get $1) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $1) - ) - (br $label$102) - ) - (local.set $0 - (i32.shl - (local.get $4) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $0) - (i32.const 1) - ) - ) - (i32.eq - (local.get $0) - (i32.const 31) - ) - ) - ) - ) - (local.set $5 - (i32.load - (local.get $1) - ) - ) - (loop $label$104 - (br_if $label$77 - (i32.eq - (i32.and - (i32.load offset=4 - (local.tee $1 - (local.get $5) - ) - ) - (i32.const -8) - ) - (local.get $4) - ) - ) - (local.set $5 - (i32.shr_u - (local.get $0) - (i32.const 29) - ) - ) - (local.set $0 - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - (br_if $label$104 - (local.tee $5 - (i32.load - (local.tee $7 - (i32.add - (i32.add - (local.get $1) - (i32.and - (local.get $5) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ) - ) - ) - (i32.store - (local.get $7) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $1) - ) - ) - (i32.store offset=12 - (local.get $3) - (local.get $3) - ) - (i32.store offset=8 - (local.get $3) - (local.get $3) - ) - (br $label$76) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $11 - (i32.sub - (local.tee $0 - (i32.add - (local.get $2) - (i32.const -40) - ) - ) - (local.tee $7 - (select - (i32.and - (i32.sub - (i32.const -8) - (local.get $5) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (i32.add - (local.get $5) - (i32.const 8) - ) - (i32.const 7) - ) - ) - ) - ) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.tee $7 - (i32.add - (local.get $5) - (local.get $7) - ) - ) - ) - (i32.store offset=4 - (local.get $7) - (i32.or - (local.get $11) - (i32.const 1) - ) - ) - (i32.store offset=4 - (i32.add - (local.get $5) - (local.get $0) - ) - (i32.const 40) - ) - (i32.store offset=1896 - (i32.const 0) - (i32.load offset=1860 - (i32.const 0) - ) - ) - (i32.store offset=4 - (local.tee $7 - (select - (local.get $1) - (local.tee $0 - (i32.add - (i32.add - (local.get $4) - (select - (i32.and - (i32.sub - (i32.const 39) - (local.get $4) - ) - (i32.const 7) - ) - (i32.const 0) - (i32.and - (i32.add - (local.get $4) - (i32.const -39) - ) - (i32.const 7) - ) - ) - ) - (i32.const -47) - ) - ) - (i32.lt_u - (local.get $0) - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - ) - (i32.const 27) - ) - (i64.store align=4 - (i32.add - (local.get $7) - (i32.const 16) - ) - (i64.load offset=2352 align=4 - (i32.const 0) - ) - ) - (i64.store offset=8 align=4 - (local.get $7) - (i64.load offset=2344 align=4 - (i32.const 0) - ) - ) - (i32.store offset=2352 - (i32.const 0) - (i32.add - (local.get $7) - (i32.const 8) - ) - ) - (i32.store offset=2348 - (i32.const 0) - (local.get $2) - ) - (i32.store offset=2344 - (i32.const 0) - (local.get $5) - ) - (i32.store offset=2356 - (i32.const 0) - (i32.const 0) - ) - (local.set $0 - (i32.add - (local.get $7) - (i32.const 24) - ) - ) - (loop $label$105 - (i32.store offset=4 - (local.get $0) - (i32.const 7) - ) - (local.set $5 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - (local.set $0 - (i32.add - (local.get $0) - (i32.const 4) - ) - ) - (br_if $label$105 - (i32.gt_u - (local.get $4) - (local.get $5) - ) - ) - ) - (br_if $label$66 - (i32.eq - (local.get $7) - (local.get $1) - ) - ) - (i32.store offset=4 - (local.get $7) - (i32.and - (i32.load offset=4 - (local.get $7) - ) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.tee $2 - (i32.sub - (local.get $7) - (local.get $1) - ) - ) - (i32.const 1) - ) - ) - (i32.store - (local.get $7) - (local.get $2) - ) - (block $label$106 - (br_if $label$106 - (i32.gt_u - (local.get $2) - (i32.const 255) - ) - ) - (local.set $0 - (i32.add - (i32.shl - (local.tee $4 - (i32.shr_u - (local.get $2) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (block $label$107 - (block $label$108 - (br_if $label$108 - (i32.and - (local.tee $5 - (i32.load offset=1868 - (i32.const 0) - ) - ) - (local.tee $4 - (i32.shl - (i32.const 1) - (local.get $4) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $5) - (local.get $4) - ) - ) - (local.set $4 - (local.get $0) - ) - (br $label$107) - ) - (local.set $4 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - (i32.store offset=8 - (local.get $0) - (local.get $1) - ) - (i32.store offset=12 - (local.get $4) - (local.get $1) - ) - (i32.store offset=12 - (local.get $1) - (local.get $0) - ) - (i32.store offset=8 - (local.get $1) - (local.get $4) - ) - (br $label$66) - ) - (local.set $0 - (i32.const 31) - ) - (block $label$109 - (br_if $label$109 - (i32.gt_u - (local.get $2) - (i32.const 16777215) - ) - ) - (local.set $0 - (i32.add - (i32.or - (i32.shl - (local.tee $0 - (i32.sub - (i32.shr_u - (i32.shl - (local.tee $5 - (i32.shl - (local.tee $4 - (i32.shl - (local.tee $0 - (i32.shr_u - (local.get $2) - (i32.const 8) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (i32.add - (local.get $4) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - ) - ) - (local.tee $5 - (i32.and - (i32.shr_u - (i32.add - (local.get $5) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - (i32.const 15) - ) - (i32.or - (i32.or - (local.get $0) - (local.get $4) - ) - (local.get $5) - ) - ) - ) - (i32.const 1) - ) - (i32.and - (i32.shr_u - (local.get $2) - (i32.add - (local.get $0) - (i32.const 21) - ) - ) - (i32.const 1) - ) - ) - (i32.const 28) - ) - ) - ) - (i64.store offset=16 align=4 - (local.get $1) - (i64.const 0) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 28) - ) - (local.get $0) - ) - (local.set $4 - (i32.add - (i32.shl - (local.get $0) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - (block $label$110 - (block $label$111 - (br_if $label$111 - (i32.and - (local.tee $5 - (i32.load offset=1872 - (i32.const 0) - ) - ) - (local.tee $7 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.or - (local.get $5) - (local.get $7) - ) - ) - (i32.store - (local.get $4) - (local.get $1) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 24) - ) - (local.get $4) - ) - (br $label$110) - ) - (local.set $0 - (i32.shl - (local.get $2) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $0) - (i32.const 1) - ) - ) - (i32.eq - (local.get $0) - (i32.const 31) - ) - ) - ) - ) - (local.set $5 - (i32.load - (local.get $4) - ) - ) - (loop $label$112 - (br_if $label$75 - (i32.eq - (i32.and - (i32.load offset=4 - (local.tee $4 - (local.get $5) - ) - ) - (i32.const -8) - ) - (local.get $2) - ) - ) - (local.set $5 - (i32.shr_u - (local.get $0) - (i32.const 29) - ) - ) - (local.set $0 - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - (br_if $label$112 - (local.tee $5 - (i32.load - (local.tee $7 - (i32.add - (i32.add - (local.get $4) - (i32.and - (local.get $5) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ) - ) - ) - (i32.store - (local.get $7) - (local.get $1) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 24) - ) - (local.get $4) - ) - ) - (i32.store offset=12 - (local.get $1) - (local.get $1) - ) - (i32.store offset=8 - (local.get $1) - (local.get $1) - ) - (br $label$66) - ) - (i32.store offset=12 - (local.tee $0 - (i32.load offset=8 - (local.get $1) - ) - ) - (local.get $3) - ) - (i32.store offset=8 - (local.get $1) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (i32.const 0) - ) - (i32.store offset=12 - (local.get $3) - (local.get $1) - ) - (i32.store offset=8 - (local.get $3) - (local.get $0) - ) - ) - (local.set $1 - (i32.add - (local.get $11) - (i32.const 8) - ) - ) - (br $label$4) - ) - (i32.store offset=12 - (local.tee $0 - (i32.load offset=8 - (local.get $4) - ) - ) - (local.get $1) - ) - (i32.store offset=8 - (local.get $4) - (local.get $1) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 24) - ) - (i32.const 0) - ) - (i32.store offset=12 - (local.get $1) - (local.get $4) - ) - (i32.store offset=8 - (local.get $1) - (local.get $0) - ) - ) - (br_if $label$62 - (i32.le_u - (local.tee $0 - (i32.load offset=1880 - (i32.const 0) - ) - ) - (local.get $3) - ) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $1 - (i32.sub - (local.get $0) - (local.get $3) - ) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.tee $4 - (i32.add - (local.tee $0 - (i32.load offset=1892 - (i32.const 0) - ) - ) - (local.get $3) - ) - ) - ) - (i32.store offset=4 - (local.get $4) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (local.set $1 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - (br $label$4) - ) - (i32.store - (call $25) - (i32.const 48) - ) - (local.set $1 - (i32.const 0) - ) - (br $label$4) - ) - (block $label$113 - (br_if $label$113 - (i32.eqz - (local.get $8) - ) - ) - (block $label$114 - (block $label$115 - (br_if $label$115 - (i32.ne - (local.get $7) - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $4 - (i32.load offset=28 - (local.get $7) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - ) - ) - (i32.store - (local.get $0) - (local.get $5) - ) - (br_if $label$114 - (local.get $5) - ) - (i32.store offset=1872 - (i32.const 0) - (local.tee $6 - (i32.and - (local.get $6) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - ) - (br $label$113) - ) - (i32.store - (i32.add - (local.get $8) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $8) - ) - (local.get $7) - ) - ) - ) - (local.get $5) - ) - (br_if $label$113 - (i32.eqz - (local.get $5) - ) - ) - ) - (i32.store offset=24 - (local.get $5) - (local.get $8) - ) - (block $label$116 - (br_if $label$116 - (i32.eqz - (local.tee $0 - (i32.load offset=16 - (local.get $7) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $5) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $5) - ) - ) - (br_if $label$113 - (i32.eqz - (local.tee $0 - (i32.load - (i32.add - (local.get $7) - (i32.const 20) - ) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $5) - (i32.const 20) - ) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $5) - ) - ) - (block $label$117 - (block $label$118 - (br_if $label$118 - (i32.gt_u - (local.get $1) - (i32.const 15) - ) - ) - (i32.store offset=4 - (local.get $7) - (i32.or - (local.tee $0 - (i32.add - (local.get $1) - (local.get $3) - ) - ) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $7) - (local.get $0) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $0) - ) - (i32.const 1) - ) - ) - (br $label$117) - ) - (i32.store offset=4 - (local.get $7) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.get $11) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $11) - (local.get $1) - ) - (local.get $1) - ) - (block $label$119 - (br_if $label$119 - (i32.gt_u - (local.get $1) - (i32.const 255) - ) - ) - (local.set $0 - (i32.add - (i32.shl - (local.tee $1 - (i32.shr_u - (local.get $1) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (block $label$120 - (block $label$121 - (br_if $label$121 - (i32.and - (local.tee $4 - (i32.load offset=1868 - (i32.const 0) - ) - ) - (local.tee $1 - (i32.shl - (i32.const 1) - (local.get $1) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $4) - (local.get $1) - ) - ) - (local.set $1 - (local.get $0) - ) - (br $label$120) - ) - (local.set $1 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - (i32.store offset=8 - (local.get $0) - (local.get $11) - ) - (i32.store offset=12 - (local.get $1) - (local.get $11) - ) - (i32.store offset=12 - (local.get $11) - (local.get $0) - ) - (i32.store offset=8 - (local.get $11) - (local.get $1) - ) - (br $label$117) - ) - (local.set $0 - (i32.const 31) - ) - (block $label$122 - (br_if $label$122 - (i32.gt_u - (local.get $1) - (i32.const 16777215) - ) - ) - (local.set $0 - (i32.add - (i32.or - (i32.shl - (local.tee $0 - (i32.sub - (i32.shr_u - (i32.shl - (local.tee $3 - (i32.shl - (local.tee $4 - (i32.shl - (local.tee $0 - (i32.shr_u - (local.get $1) - (i32.const 8) - ) - ) - (local.tee $0 - (i32.and - (i32.shr_u - (i32.add - (local.get $0) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (i32.add - (local.get $4) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - ) - ) - (local.tee $3 - (i32.and - (i32.shr_u - (i32.add - (local.get $3) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - (i32.const 15) - ) - (i32.or - (i32.or - (local.get $0) - (local.get $4) - ) - (local.get $3) - ) - ) - ) - (i32.const 1) - ) - (i32.and - (i32.shr_u - (local.get $1) - (i32.add - (local.get $0) - (i32.const 21) - ) - ) - (i32.const 1) - ) - ) - (i32.const 28) - ) - ) - ) - (i32.store offset=28 - (local.get $11) - (local.get $0) - ) - (i64.store offset=16 align=4 - (local.get $11) - (i64.const 0) - ) - (local.set $4 - (i32.add - (i32.shl - (local.get $0) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - (block $label$123 - (block $label$124 - (block $label$125 - (br_if $label$125 - (i32.and - (local.get $6) - (local.tee $3 - (i32.shl - (i32.const 1) - (local.get $0) - ) - ) - ) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.or - (local.get $6) - (local.get $3) - ) - ) - (i32.store - (local.get $4) - (local.get $11) - ) - (i32.store offset=24 - (local.get $11) - (local.get $4) - ) - (br $label$124) - ) - (local.set $0 - (i32.shl - (local.get $1) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $0) - (i32.const 1) - ) - ) - (i32.eq - (local.get $0) - (i32.const 31) - ) - ) - ) - ) - (local.set $3 - (i32.load - (local.get $4) - ) - ) - (loop $label$126 - (br_if $label$123 - (i32.eq - (i32.and - (i32.load offset=4 - (local.tee $4 - (local.get $3) - ) - ) - (i32.const -8) - ) - (local.get $1) - ) - ) - (local.set $3 - (i32.shr_u - (local.get $0) - (i32.const 29) - ) - ) - (local.set $0 - (i32.shl - (local.get $0) - (i32.const 1) - ) - ) - (br_if $label$126 - (local.tee $3 - (i32.load - (local.tee $5 - (i32.add - (i32.add - (local.get $4) - (i32.and - (local.get $3) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ) - ) - ) - (i32.store - (local.get $5) - (local.get $11) - ) - (i32.store offset=24 - (local.get $11) - (local.get $4) - ) - ) - (i32.store offset=12 - (local.get $11) - (local.get $11) - ) - (i32.store offset=8 - (local.get $11) - (local.get $11) - ) - (br $label$117) - ) - (i32.store offset=12 - (local.tee $0 - (i32.load offset=8 - (local.get $4) - ) - ) - (local.get $11) - ) - (i32.store offset=8 - (local.get $4) - (local.get $11) - ) - (i32.store offset=24 - (local.get $11) - (i32.const 0) - ) - (i32.store offset=12 - (local.get $11) - (local.get $4) - ) - (i32.store offset=8 - (local.get $11) - (local.get $0) - ) - ) - (local.set $1 - (i32.add - (local.get $7) - (i32.const 8) - ) - ) - (br $label$4) - ) - (block $label$127 - (br_if $label$127 - (i32.eqz - (local.get $10) - ) - ) - (block $label$128 - (block $label$129 - (br_if $label$129 - (i32.ne - (local.get $5) - (i32.load - (local.tee $0 - (i32.add - (i32.shl - (local.tee $4 - (i32.load offset=28 - (local.get $5) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - ) - ) - (i32.store - (local.get $0) - (local.get $7) - ) - (br_if $label$128 - (local.get $7) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.and - (local.get $8) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - (br $label$127) - ) - (i32.store - (i32.add - (local.get $10) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $10) - ) - (local.get $5) - ) - ) - ) - (local.get $7) - ) - (br_if $label$127 - (i32.eqz - (local.get $7) - ) - ) - ) - (i32.store offset=24 - (local.get $7) - (local.get $10) - ) - (block $label$130 - (br_if $label$130 - (i32.eqz - (local.tee $0 - (i32.load offset=16 - (local.get $5) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $7) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $7) - ) - ) - (br_if $label$127 - (i32.eqz - (local.tee $0 - (i32.load - (i32.add - (local.get $5) - (i32.const 20) - ) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $7) - (i32.const 20) - ) - (local.get $0) - ) - (i32.store offset=24 - (local.get $0) - (local.get $7) - ) - ) - (block $label$131 - (block $label$132 - (br_if $label$132 - (i32.gt_u - (local.get $1) - (i32.const 15) - ) - ) - (i32.store offset=4 - (local.get $5) - (i32.or - (local.tee $0 - (i32.add - (local.get $1) - (local.get $3) - ) - ) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $5) - (local.get $0) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $0) - ) - (i32.const 1) - ) - ) - (br $label$131) - ) - (i32.store offset=4 - (local.get $5) - (i32.or - (local.get $3) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.get $9) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $9) - (local.get $1) - ) - (local.get $1) - ) - (block $label$133 - (br_if $label$133 - (i32.eqz - (local.get $6) - ) - ) - (local.set $4 - (i32.add - (i32.shl - (local.tee $3 - (i32.shr_u - (local.get $6) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (local.set $0 - (i32.load offset=1888 - (i32.const 0) - ) - ) - (block $label$134 - (block $label$135 - (br_if $label$135 - (i32.and - (local.tee $3 - (i32.shl - (i32.const 1) - (local.get $3) - ) - ) - (local.get $2) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $3) - (local.get $2) - ) - ) - (local.set $3 - (local.get $4) - ) - (br $label$134) - ) - (local.set $3 - (i32.load offset=8 - (local.get $4) - ) - ) - ) - (i32.store offset=8 - (local.get $4) - (local.get $0) - ) - (i32.store offset=12 - (local.get $3) - (local.get $0) - ) - (i32.store offset=12 - (local.get $0) - (local.get $4) - ) - (i32.store offset=8 - (local.get $0) - (local.get $3) - ) - ) - (i32.store offset=1888 - (i32.const 0) - (local.get $9) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $1) - ) - ) - (local.set $1 - (i32.add - (local.get $5) - (i32.const 8) - ) - ) - ) - (br_if $label$2 - (i32.eqz - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 2) - ) - ) - ) - (drop - (call $20 - (i32.const 2316) - ) - ) - ) - (local.get $1) - ) - (func $61 - (local $0 i32) - (global.set $global$0 - (local.tee $0 - (i32.sub - (global.get $global$0) - (i32.const 16) - ) - ) - ) - (drop - (call $55 - (i32.const 2368) - ) - ) - (block $label$1 - (br_if $label$1 - (i32.load offset=1844 - (i32.const 0) - ) - ) - (i32.store offset=1864 - (i32.const 0) - (i32.const 2) - ) - (i64.store offset=1856 align=4 - (i32.const 0) - (i64.const -1) - ) - (i64.store offset=1848 align=4 - (i32.const 0) - (i64.const 17592186048512) - ) - (i32.store offset=2312 - (i32.const 0) - (i32.const 2) - ) - (block $label$2 - (br_if $label$2 - (call $57 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - (br_if $label$2 - (call $58 - (i32.const 2316) - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - (drop - (call $59 - (i32.add - (local.get $0) - (i32.const 8) - ) - ) - ) - ) - (i32.store offset=1844 - (i32.const 0) - (i32.xor - (i32.and - (i32.add - (local.get $0) - (i32.const 4) - ) - (i32.const -16) - ) - (i32.const 1431655768) - ) - ) - ) - (drop - (call $20 - (i32.const 2368) - ) - ) - (global.set $global$0 - (i32.add - (local.get $0) - (i32.const 16) - ) - ) - ) - (func $62 (param $0 i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (block $label$1 - (br_if $label$1 - (i32.eqz - (local.get $0) - ) - ) - (block $label$2 - (br_if $label$2 - (i32.eqz - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 2) - ) - ) - ) - (br_if $label$1 - (call $55 - (i32.const 2316) - ) - ) - ) - (local.set $3 - (i32.add - (local.tee $1 - (i32.add - (local.get $0) - (i32.const -8) - ) - ) - (local.tee $0 - (i32.and - (local.tee $2 - (i32.load - (i32.add - (local.get $0) - (i32.const -4) - ) - ) - ) - (i32.const -8) - ) - ) - ) - ) - (block $label$3 - (block $label$4 - (br_if $label$4 - (i32.and - (local.get $2) - (i32.const 1) - ) - ) - (br_if $label$3 - (i32.eqz - (i32.and - (local.get $2) - (i32.const 3) - ) - ) - ) - (br_if $label$3 - (i32.lt_u - (local.tee $1 - (i32.sub - (local.get $1) - (local.tee $2 - (i32.load - (local.get $1) - ) - ) - ) - ) - (local.tee $4 - (i32.load offset=1884 - (i32.const 0) - ) - ) - ) - ) - (local.set $0 - (i32.add - (local.get $2) - (local.get $0) - ) - ) - (block $label$5 - (br_if $label$5 - (i32.eq - (i32.load offset=1888 - (i32.const 0) - ) - (local.get $1) - ) - ) - (block $label$6 - (br_if $label$6 - (i32.gt_u - (local.get $2) - (i32.const 255) - ) - ) - (drop - (i32.eq - (local.tee $4 - (i32.load offset=8 - (local.get $1) - ) - ) - (local.tee $6 - (i32.add - (i32.shl - (local.tee $5 - (i32.shr_u - (local.get $2) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - ) - ) - (block $label$7 - (br_if $label$7 - (i32.ne - (local.tee $2 - (i32.load offset=12 - (local.get $1) - ) - ) - (local.get $4) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.and - (i32.load offset=1868 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $5) - ) - ) - ) - (br $label$4) - ) - (drop - (i32.eq - (local.get $2) - (local.get $6) - ) - ) - (i32.store offset=12 - (local.get $4) - (local.get $2) - ) - (i32.store offset=8 - (local.get $2) - (local.get $4) - ) - (br $label$4) - ) - (local.set $7 - (i32.load offset=24 - (local.get $1) - ) - ) - (block $label$8 - (block $label$9 - (br_if $label$9 - (i32.eq - (local.tee $6 - (i32.load offset=12 - (local.get $1) - ) - ) - (local.get $1) - ) - ) - (drop - (i32.gt_u - (local.get $4) - (local.tee $2 - (i32.load offset=8 - (local.get $1) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $2) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $2) - ) - (br $label$8) - ) - (block $label$10 - (br_if $label$10 - (local.tee $4 - (i32.load - (local.tee $2 - (i32.add - (local.get $1) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$10 - (local.tee $4 - (i32.load - (local.tee $2 - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$8) - ) - (loop $label$11 - (local.set $5 - (local.get $2) - ) - (br_if $label$11 - (local.tee $4 - (i32.load - (local.tee $2 - (i32.add - (local.tee $6 - (local.get $4) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $2 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - (br_if $label$11 - (local.tee $4 - (i32.load offset=16 - (local.get $6) - ) - ) - ) - ) - (i32.store - (local.get $5) - (i32.const 0) - ) - ) - (br_if $label$4 - (i32.eqz - (local.get $7) - ) - ) - (block $label$12 - (block $label$13 - (br_if $label$13 - (i32.ne - (i32.load - (local.tee $2 - (i32.add - (i32.shl - (local.tee $4 - (i32.load offset=28 - (local.get $1) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - (local.get $1) - ) - ) - (i32.store - (local.get $2) - (local.get $6) - ) - (br_if $label$12 - (local.get $6) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.and - (i32.load offset=1872 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - (br $label$4) - ) - (i32.store - (i32.add - (local.get $7) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $7) - ) - (local.get $1) - ) - ) - ) - (local.get $6) - ) - (br_if $label$4 - (i32.eqz - (local.get $6) - ) - ) - ) - (i32.store offset=24 - (local.get $6) - (local.get $7) - ) - (block $label$14 - (br_if $label$14 - (i32.eqz - (local.tee $2 - (i32.load offset=16 - (local.get $1) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $6) - (local.get $2) - ) - (i32.store offset=24 - (local.get $2) - (local.get $6) - ) - ) - (br_if $label$4 - (i32.eqz - (local.tee $2 - (i32.load offset=20 - (local.get $1) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $6) - (i32.const 20) - ) - (local.get $2) - ) - (i32.store offset=24 - (local.get $2) - (local.get $6) - ) - (br $label$4) - ) - (br_if $label$4 - (i32.ne - (i32.and - (local.tee $2 - (i32.load offset=4 - (local.get $3) - ) - ) - (i32.const 3) - ) - (i32.const 3) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $0) - ) - (i32.store offset=4 - (local.get $3) - (i32.and - (local.get $2) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $0) - ) - (local.get $0) - ) - (br $label$3) - ) - (br_if $label$3 - (i32.le_u - (local.get $3) - (local.get $1) - ) - ) - (br_if $label$3 - (i32.eqz - (i32.and - (local.tee $2 - (i32.load offset=4 - (local.get $3) - ) - ) - (i32.const 1) - ) - ) - ) - (block $label$15 - (block $label$16 - (br_if $label$16 - (i32.and - (local.get $2) - (i32.const 2) - ) - ) - (block $label$17 - (br_if $label$17 - (i32.ne - (i32.load offset=1892 - (i32.const 0) - ) - (local.get $3) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.get $1) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $0 - (i32.add - (i32.load offset=1880 - (i32.const 0) - ) - (local.get $0) - ) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (br_if $label$3 - (i32.ne - (local.get $1) - (i32.load offset=1888 - (i32.const 0) - ) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (i32.const 0) - ) - (i32.store offset=1888 - (i32.const 0) - (i32.const 0) - ) - (br $label$3) - ) - (block $label$18 - (br_if $label$18 - (i32.ne - (i32.load offset=1888 - (i32.const 0) - ) - (local.get $3) - ) - ) - (i32.store offset=1888 - (i32.const 0) - (local.get $1) - ) - (i32.store offset=1876 - (i32.const 0) - (local.tee $0 - (i32.add - (i32.load offset=1876 - (i32.const 0) - ) - (local.get $0) - ) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $0) - ) - (local.get $0) - ) - (br $label$3) - ) - (local.set $0 - (i32.add - (i32.and - (local.get $2) - (i32.const -8) - ) - (local.get $0) - ) - ) - (block $label$19 - (block $label$20 - (br_if $label$20 - (i32.gt_u - (local.get $2) - (i32.const 255) - ) - ) - (drop - (i32.eq - (local.tee $4 - (i32.load offset=8 - (local.get $3) - ) - ) - (local.tee $6 - (i32.add - (i32.shl - (local.tee $5 - (i32.shr_u - (local.get $2) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - ) - ) - (block $label$21 - (br_if $label$21 - (i32.ne - (local.tee $2 - (i32.load offset=12 - (local.get $3) - ) - ) - (local.get $4) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.and - (i32.load offset=1868 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $5) - ) - ) - ) - (br $label$19) - ) - (drop - (i32.eq - (local.get $2) - (local.get $6) - ) - ) - (i32.store offset=12 - (local.get $4) - (local.get $2) - ) - (i32.store offset=8 - (local.get $2) - (local.get $4) - ) - (br $label$19) - ) - (local.set $7 - (i32.load offset=24 - (local.get $3) - ) - ) - (block $label$22 - (block $label$23 - (br_if $label$23 - (i32.eq - (local.tee $6 - (i32.load offset=12 - (local.get $3) - ) - ) - (local.get $3) - ) - ) - (drop - (i32.gt_u - (i32.load offset=1884 - (i32.const 0) - ) - (local.tee $2 - (i32.load offset=8 - (local.get $3) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $2) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $2) - ) - (br $label$22) - ) - (block $label$24 - (br_if $label$24 - (local.tee $2 - (i32.load - (local.tee $4 - (i32.add - (local.get $3) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$24 - (local.tee $2 - (i32.load - (local.tee $4 - (i32.add - (local.get $3) - (i32.const 16) - ) - ) - ) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$22) - ) - (loop $label$25 - (local.set $5 - (local.get $4) - ) - (br_if $label$25 - (local.tee $2 - (i32.load - (local.tee $4 - (i32.add - (local.tee $6 - (local.get $2) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $4 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - (br_if $label$25 - (local.tee $2 - (i32.load offset=16 - (local.get $6) - ) - ) - ) - ) - (i32.store - (local.get $5) - (i32.const 0) - ) - ) - (br_if $label$19 - (i32.eqz - (local.get $7) - ) - ) - (block $label$26 - (block $label$27 - (br_if $label$27 - (i32.ne - (i32.load - (local.tee $2 - (i32.add - (i32.shl - (local.tee $4 - (i32.load offset=28 - (local.get $3) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - (local.get $3) - ) - ) - (i32.store - (local.get $2) - (local.get $6) - ) - (br_if $label$26 - (local.get $6) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.and - (i32.load offset=1872 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - (br $label$19) - ) - (i32.store - (i32.add - (local.get $7) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $7) - ) - (local.get $3) - ) - ) - ) - (local.get $6) - ) - (br_if $label$19 - (i32.eqz - (local.get $6) - ) - ) - ) - (i32.store offset=24 - (local.get $6) - (local.get $7) - ) - (block $label$28 - (br_if $label$28 - (i32.eqz - (local.tee $2 - (i32.load offset=16 - (local.get $3) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $6) - (local.get $2) - ) - (i32.store offset=24 - (local.get $2) - (local.get $6) - ) - ) - (br_if $label$19 - (i32.eqz - (local.tee $2 - (i32.load offset=20 - (local.get $3) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $6) - (i32.const 20) - ) - (local.get $2) - ) - (i32.store offset=24 - (local.get $2) - (local.get $6) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $0) - ) - (local.get $0) - ) - (br_if $label$15 - (i32.ne - (local.get $1) - (i32.load offset=1888 - (i32.const 0) - ) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $0) - ) - (br $label$3) - ) - (i32.store offset=4 - (local.get $3) - (i32.and - (local.get $2) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $1) - (i32.or - (local.get $0) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $1) - (local.get $0) - ) - (local.get $0) - ) - ) - (block $label$29 - (br_if $label$29 - (i32.gt_u - (local.get $0) - (i32.const 255) - ) - ) - (local.set $0 - (i32.add - (i32.shl - (local.tee $2 - (i32.shr_u - (local.get $0) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (block $label$30 - (block $label$31 - (br_if $label$31 - (i32.and - (local.tee $4 - (i32.load offset=1868 - (i32.const 0) - ) - ) - (local.tee $2 - (i32.shl - (i32.const 1) - (local.get $2) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $4) - (local.get $2) - ) - ) - (local.set $2 - (local.get $0) - ) - (br $label$30) - ) - (local.set $2 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - (i32.store offset=8 - (local.get $0) - (local.get $1) - ) - (i32.store offset=12 - (local.get $2) - (local.get $1) - ) - (i32.store offset=12 - (local.get $1) - (local.get $0) - ) - (i32.store offset=8 - (local.get $1) - (local.get $2) - ) - (br $label$3) - ) - (local.set $2 - (i32.const 31) - ) - (block $label$32 - (br_if $label$32 - (i32.gt_u - (local.get $0) - (i32.const 16777215) - ) - ) - (local.set $2 - (i32.add - (i32.or - (i32.shl - (local.tee $2 - (i32.sub - (i32.shr_u - (i32.shl - (local.tee $6 - (i32.shl - (local.tee $4 - (i32.shl - (local.tee $2 - (i32.shr_u - (local.get $0) - (i32.const 8) - ) - ) - (local.tee $2 - (i32.and - (i32.shr_u - (i32.add - (local.get $2) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (i32.add - (local.get $4) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - ) - ) - (local.tee $6 - (i32.and - (i32.shr_u - (i32.add - (local.get $6) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - (i32.const 15) - ) - (i32.or - (i32.or - (local.get $2) - (local.get $4) - ) - (local.get $6) - ) - ) - ) - (i32.const 1) - ) - (i32.and - (i32.shr_u - (local.get $0) - (i32.add - (local.get $2) - (i32.const 21) - ) - ) - (i32.const 1) - ) - ) - (i32.const 28) - ) - ) - ) - (i64.store offset=16 align=4 - (local.get $1) - (i64.const 0) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 28) - ) - (local.get $2) - ) - (local.set $4 - (i32.add - (i32.shl - (local.get $2) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - (block $label$33 - (block $label$34 - (block $label$35 - (block $label$36 - (br_if $label$36 - (i32.and - (local.tee $6 - (i32.load offset=1872 - (i32.const 0) - ) - ) - (local.tee $3 - (i32.shl - (i32.const 1) - (local.get $2) - ) - ) - ) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.or - (local.get $6) - (local.get $3) - ) - ) - (i32.store - (local.get $4) - (local.get $1) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 24) - ) - (local.get $4) - ) - (br $label$35) - ) - (local.set $2 - (i32.shl - (local.get $0) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $2) - (i32.const 1) - ) - ) - (i32.eq - (local.get $2) - (i32.const 31) - ) - ) - ) - ) - (local.set $6 - (i32.load - (local.get $4) - ) - ) - (loop $label$37 - (br_if $label$34 - (i32.eq - (i32.and - (i32.load offset=4 - (local.tee $4 - (local.get $6) - ) - ) - (i32.const -8) - ) - (local.get $0) - ) - ) - (local.set $6 - (i32.shr_u - (local.get $2) - (i32.const 29) - ) - ) - (local.set $2 - (i32.shl - (local.get $2) - (i32.const 1) - ) - ) - (br_if $label$37 - (local.tee $6 - (i32.load - (local.tee $3 - (i32.add - (i32.add - (local.get $4) - (i32.and - (local.get $6) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ) - ) - ) - (i32.store - (local.get $3) - (local.get $1) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 24) - ) - (local.get $4) - ) - ) - (i32.store offset=12 - (local.get $1) - (local.get $1) - ) - (i32.store offset=8 - (local.get $1) - (local.get $1) - ) - (br $label$33) - ) - (i32.store offset=12 - (local.tee $0 - (i32.load offset=8 - (local.get $4) - ) - ) - (local.get $1) - ) - (i32.store offset=8 - (local.get $4) - (local.get $1) - ) - (i32.store - (i32.add - (local.get $1) - (i32.const 24) - ) - (i32.const 0) - ) - (i32.store offset=12 - (local.get $1) - (local.get $4) - ) - (i32.store offset=8 - (local.get $1) - (local.get $0) - ) - ) - (i32.store offset=1900 - (i32.const 0) - (select - (local.tee $1 - (i32.add - (i32.load offset=1900 - (i32.const 0) - ) - (i32.const -1) - ) - ) - (i32.const -1) - (local.get $1) - ) - ) - ) - (br_if $label$1 - (i32.eqz - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 2) - ) - ) - ) - (drop - (call $20 - (i32.const 2316) - ) - ) - ) - ) - (func $63 (param $0 i32) (param $1 i32) (result i32) - (block $label$1 - (br_if $label$1 - (i32.gt_u - (local.get $0) - (i32.const 8) - ) - ) - (return - (call $60 - (local.get $1) - ) - ) - ) - (call $64 - (local.get $0) - (local.get $1) - ) - ) - (func $64 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local.set $2 - (i32.const 16) - ) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.and - (local.tee $3 - (select - (local.get $0) - (i32.const 16) - (i32.gt_u - (local.get $0) - (i32.const 16) - ) - ) - ) - (i32.add - (local.get $3) - (i32.const -1) - ) - ) - ) - (local.set $0 - (local.get $3) - ) - (br $label$1) - ) - (loop $label$3 - (local.set $2 - (i32.shl - (local.tee $0 - (local.get $2) - ) - (i32.const 1) - ) - ) - (br_if $label$3 - (i32.lt_u - (local.get $0) - (local.get $3) - ) - ) - ) - ) - (block $label$4 - (br_if $label$4 - (i32.gt_u - (i32.sub - (i32.const -64) - (local.get $0) - ) - (local.get $1) - ) - ) - (i32.store - (call $25) - (i32.const 48) - ) - (return - (i32.const 0) - ) - ) - (block $label$5 - (br_if $label$5 - (local.tee $3 - (call $60 - (i32.add - (i32.add - (local.tee $1 - (select - (i32.const 16) - (i32.and - (i32.add - (local.get $1) - (i32.const 11) - ) - (i32.const -8) - ) - (i32.lt_u - (local.get $1) - (i32.const 11) - ) - ) - ) - (local.get $0) - ) - (i32.const 12) - ) - ) - ) - ) - (return - (i32.const 0) - ) - ) - (local.set $2 - (i32.const 0) - ) - (block $label$6 - (block $label$7 - (br_if $label$7 - (i32.eqz - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 2) - ) - ) - ) - (br_if $label$6 - (call $55 - (i32.const 2316) - ) - ) - ) - (local.set $2 - (i32.add - (local.get $3) - (i32.const -8) - ) - ) - (block $label$8 - (br_if $label$8 - (i32.eqz - (i32.and - (i32.add - (local.get $0) - (i32.const -1) - ) - (local.get $3) - ) - ) - ) - (local.set $6 - (i32.sub - (i32.and - (local.tee $5 - (i32.load - (local.tee $4 - (i32.add - (local.get $3) - (i32.const -4) - ) - ) - ) - ) - (i32.const -8) - ) - (local.tee $3 - (i32.sub - (local.tee $0 - (select - (local.tee $3 - (i32.add - (i32.and - (i32.add - (i32.add - (local.get $3) - (local.get $0) - ) - (i32.const -1) - ) - (i32.sub - (i32.const 0) - (local.get $0) - ) - ) - (i32.const -8) - ) - ) - (i32.add - (local.get $3) - (local.get $0) - ) - (i32.gt_u - (i32.sub - (local.get $3) - (local.get $2) - ) - (i32.const 15) - ) - ) - ) - (local.get $2) - ) - ) - ) - ) - (block $label$9 - (block $label$10 - (br_if $label$10 - (i32.and - (local.get $5) - (i32.const 3) - ) - ) - (local.set $2 - (i32.load - (local.get $2) - ) - ) - (i32.store offset=4 - (local.get $0) - (local.get $6) - ) - (i32.store - (local.get $0) - (i32.add - (local.get $2) - (local.get $3) - ) - ) - (br $label$9) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (i32.or - (local.get $6) - (i32.and - (i32.load offset=4 - (local.get $0) - ) - (i32.const 1) - ) - ) - (i32.const 2) - ) - ) - (i32.store offset=4 - (local.tee $6 - (i32.add - (local.get $0) - (local.get $6) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $6) - ) - (i32.const 1) - ) - ) - (i32.store - (local.get $4) - (i32.or - (i32.or - (local.get $3) - (i32.and - (i32.load - (local.get $4) - ) - (i32.const 1) - ) - ) - (i32.const 2) - ) - ) - (i32.store offset=4 - (local.tee $6 - (i32.add - (local.get $2) - (local.get $3) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $6) - ) - (i32.const 1) - ) - ) - (call $65 - (local.get $2) - (local.get $3) - ) - ) - (local.set $2 - (local.get $0) - ) - ) - (block $label$11 - (br_if $label$11 - (i32.eqz - (i32.and - (local.tee $0 - (i32.load offset=4 - (local.get $2) - ) - ) - (i32.const 3) - ) - ) - ) - (br_if $label$11 - (i32.le_u - (local.tee $3 - (i32.and - (local.get $0) - (i32.const -8) - ) - ) - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (i32.or - (i32.or - (local.get $1) - (i32.and - (local.get $0) - (i32.const 1) - ) - ) - (i32.const 2) - ) - ) - (i32.store offset=4 - (local.tee $0 - (i32.add - (local.get $2) - (local.get $1) - ) - ) - (i32.or - (local.tee $1 - (i32.sub - (local.get $3) - (local.get $1) - ) - ) - (i32.const 3) - ) - ) - (i32.store offset=4 - (local.tee $3 - (i32.add - (local.get $2) - (local.get $3) - ) - ) - (i32.or - (i32.load offset=4 - (local.get $3) - ) - (i32.const 1) - ) - ) - (call $65 - (local.get $0) - (local.get $1) - ) - ) - (local.set $2 - (i32.add - (local.get $2) - (i32.const 8) - ) - ) - (br_if $label$6 - (i32.eqz - (i32.and - (i32.load8_u offset=2312 - (i32.const 0) - ) - (i32.const 2) - ) - ) - ) - (drop - (call $20 - (i32.const 2316) - ) - ) - ) - (local.get $2) - ) - (func $65 (param $0 i32) (param $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local.set $2 - (i32.add - (local.get $0) - (local.get $1) - ) - ) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.and - (local.tee $3 - (i32.load offset=4 - (local.get $0) - ) - ) - (i32.const 1) - ) - ) - (br_if $label$1 - (i32.eqz - (i32.and - (local.get $3) - (i32.const 3) - ) - ) - ) - (local.set $1 - (i32.add - (local.tee $3 - (i32.load - (local.get $0) - ) - ) - (local.get $1) - ) - ) - (block $label$3 - (block $label$4 - (br_if $label$4 - (i32.eq - (i32.load offset=1888 - (i32.const 0) - ) - (local.tee $0 - (i32.sub - (local.get $0) - (local.get $3) - ) - ) - ) - ) - (block $label$5 - (br_if $label$5 - (i32.gt_u - (local.get $3) - (i32.const 255) - ) - ) - (drop - (i32.eq - (local.tee $4 - (i32.load offset=8 - (local.get $0) - ) - ) - (local.tee $6 - (i32.add - (i32.shl - (local.tee $5 - (i32.shr_u - (local.get $3) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - ) - ) - (br_if $label$3 - (i32.ne - (local.tee $3 - (i32.load offset=12 - (local.get $0) - ) - ) - (local.get $4) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.and - (i32.load offset=1868 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $5) - ) - ) - ) - (br $label$2) - ) - (local.set $7 - (i32.load offset=24 - (local.get $0) - ) - ) - (block $label$6 - (block $label$7 - (br_if $label$7 - (i32.eq - (local.tee $6 - (i32.load offset=12 - (local.get $0) - ) - ) - (local.get $0) - ) - ) - (drop - (i32.gt_u - (i32.load offset=1884 - (i32.const 0) - ) - (local.tee $3 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $3) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $3) - ) - (br $label$6) - ) - (block $label$8 - (br_if $label$8 - (local.tee $4 - (i32.load - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$8 - (local.tee $4 - (i32.load - (local.tee $3 - (i32.add - (local.get $0) - (i32.const 16) - ) - ) - ) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$6) - ) - (loop $label$9 - (local.set $5 - (local.get $3) - ) - (br_if $label$9 - (local.tee $4 - (i32.load - (local.tee $3 - (i32.add - (local.tee $6 - (local.get $4) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $3 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - (br_if $label$9 - (local.tee $4 - (i32.load offset=16 - (local.get $6) - ) - ) - ) - ) - (i32.store - (local.get $5) - (i32.const 0) - ) - ) - (br_if $label$2 - (i32.eqz - (local.get $7) - ) - ) - (block $label$10 - (block $label$11 - (br_if $label$11 - (i32.ne - (i32.load - (local.tee $3 - (i32.add - (i32.shl - (local.tee $4 - (i32.load offset=28 - (local.get $0) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - (local.get $0) - ) - ) - (i32.store - (local.get $3) - (local.get $6) - ) - (br_if $label$10 - (local.get $6) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.and - (i32.load offset=1872 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - (br $label$2) - ) - (i32.store - (i32.add - (local.get $7) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $7) - ) - (local.get $0) - ) - ) - ) - (local.get $6) - ) - (br_if $label$2 - (i32.eqz - (local.get $6) - ) - ) - ) - (i32.store offset=24 - (local.get $6) - (local.get $7) - ) - (block $label$12 - (br_if $label$12 - (i32.eqz - (local.tee $3 - (i32.load offset=16 - (local.get $0) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $6) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $6) - ) - ) - (br_if $label$2 - (i32.eqz - (local.tee $3 - (i32.load offset=20 - (local.get $0) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $6) - (i32.const 20) - ) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $6) - ) - (br $label$2) - ) - (br_if $label$2 - (i32.ne - (i32.and - (local.tee $3 - (i32.load offset=4 - (local.get $2) - ) - ) - (i32.const 3) - ) - (i32.const 3) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $1) - ) - (i32.store offset=4 - (local.get $2) - (i32.and - (local.get $3) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store - (local.get $2) - (local.get $1) - ) - (return) - ) - (drop - (i32.eq - (local.get $3) - (local.get $6) - ) - ) - (i32.store offset=12 - (local.get $4) - (local.get $3) - ) - (i32.store offset=8 - (local.get $3) - (local.get $4) - ) - ) - (block $label$13 - (block $label$14 - (br_if $label$14 - (i32.and - (local.tee $3 - (i32.load offset=4 - (local.get $2) - ) - ) - (i32.const 2) - ) - ) - (block $label$15 - (br_if $label$15 - (i32.ne - (i32.load offset=1892 - (i32.const 0) - ) - (local.get $2) - ) - ) - (i32.store offset=1892 - (i32.const 0) - (local.get $0) - ) - (i32.store offset=1880 - (i32.const 0) - (local.tee $1 - (i32.add - (i32.load offset=1880 - (i32.const 0) - ) - (local.get $1) - ) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (br_if $label$1 - (i32.ne - (local.get $0) - (i32.load offset=1888 - (i32.const 0) - ) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (i32.const 0) - ) - (i32.store offset=1888 - (i32.const 0) - (i32.const 0) - ) - (return) - ) - (block $label$16 - (br_if $label$16 - (i32.ne - (i32.load offset=1888 - (i32.const 0) - ) - (local.get $2) - ) - ) - (i32.store offset=1888 - (i32.const 0) - (local.get $0) - ) - (i32.store offset=1876 - (i32.const 0) - (local.tee $1 - (i32.add - (i32.load offset=1876 - (i32.const 0) - ) - (local.get $1) - ) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $0) - (local.get $1) - ) - (local.get $1) - ) - (return) - ) - (local.set $1 - (i32.add - (i32.and - (local.get $3) - (i32.const -8) - ) - (local.get $1) - ) - ) - (block $label$17 - (block $label$18 - (br_if $label$18 - (i32.gt_u - (local.get $3) - (i32.const 255) - ) - ) - (drop - (i32.eq - (local.tee $4 - (i32.load offset=8 - (local.get $2) - ) - ) - (local.tee $6 - (i32.add - (i32.shl - (local.tee $5 - (i32.shr_u - (local.get $3) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - ) - ) - (block $label$19 - (br_if $label$19 - (i32.ne - (local.tee $3 - (i32.load offset=12 - (local.get $2) - ) - ) - (local.get $4) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.and - (i32.load offset=1868 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $5) - ) - ) - ) - (br $label$17) - ) - (drop - (i32.eq - (local.get $3) - (local.get $6) - ) - ) - (i32.store offset=12 - (local.get $4) - (local.get $3) - ) - (i32.store offset=8 - (local.get $3) - (local.get $4) - ) - (br $label$17) - ) - (local.set $7 - (i32.load offset=24 - (local.get $2) - ) - ) - (block $label$20 - (block $label$21 - (br_if $label$21 - (i32.eq - (local.tee $6 - (i32.load offset=12 - (local.get $2) - ) - ) - (local.get $2) - ) - ) - (drop - (i32.gt_u - (i32.load offset=1884 - (i32.const 0) - ) - (local.tee $3 - (i32.load offset=8 - (local.get $2) - ) - ) - ) - ) - (i32.store offset=12 - (local.get $3) - (local.get $6) - ) - (i32.store offset=8 - (local.get $6) - (local.get $3) - ) - (br $label$20) - ) - (block $label$22 - (br_if $label$22 - (local.tee $3 - (i32.load - (local.tee $4 - (i32.add - (local.get $2) - (i32.const 20) - ) - ) - ) - ) - ) - (br_if $label$22 - (local.tee $3 - (i32.load - (local.tee $4 - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - ) - ) - ) - (local.set $6 - (i32.const 0) - ) - (br $label$20) - ) - (loop $label$23 - (local.set $5 - (local.get $4) - ) - (br_if $label$23 - (local.tee $3 - (i32.load - (local.tee $4 - (i32.add - (local.tee $6 - (local.get $3) - ) - (i32.const 20) - ) - ) - ) - ) - ) - (local.set $4 - (i32.add - (local.get $6) - (i32.const 16) - ) - ) - (br_if $label$23 - (local.tee $3 - (i32.load offset=16 - (local.get $6) - ) - ) - ) - ) - (i32.store - (local.get $5) - (i32.const 0) - ) - ) - (br_if $label$17 - (i32.eqz - (local.get $7) - ) - ) - (block $label$24 - (block $label$25 - (br_if $label$25 - (i32.ne - (i32.load - (local.tee $3 - (i32.add - (i32.shl - (local.tee $4 - (i32.load offset=28 - (local.get $2) - ) - ) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - ) - (local.get $2) - ) - ) - (i32.store - (local.get $3) - (local.get $6) - ) - (br_if $label$24 - (local.get $6) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.and - (i32.load offset=1872 - (i32.const 0) - ) - (i32.rotl - (i32.const -2) - (local.get $4) - ) - ) - ) - (br $label$17) - ) - (i32.store - (i32.add - (local.get $7) - (select - (i32.const 16) - (i32.const 20) - (i32.eq - (i32.load offset=16 - (local.get $7) - ) - (local.get $2) - ) - ) - ) - (local.get $6) - ) - (br_if $label$17 - (i32.eqz - (local.get $6) - ) - ) - ) - (i32.store offset=24 - (local.get $6) - (local.get $7) - ) - (block $label$26 - (br_if $label$26 - (i32.eqz - (local.tee $3 - (i32.load offset=16 - (local.get $2) - ) - ) - ) - ) - (i32.store offset=16 - (local.get $6) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $6) - ) - ) - (br_if $label$17 - (i32.eqz - (local.tee $3 - (i32.load offset=20 - (local.get $2) - ) - ) - ) - ) - (i32.store - (i32.add - (local.get $6) - (i32.const 20) - ) - (local.get $3) - ) - (i32.store offset=24 - (local.get $3) - (local.get $6) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $0) - (local.get $1) - ) - (local.get $1) - ) - (br_if $label$13 - (i32.ne - (local.get $0) - (i32.load offset=1888 - (i32.const 0) - ) - ) - ) - (i32.store offset=1876 - (i32.const 0) - (local.get $1) - ) - (return) - ) - (i32.store offset=4 - (local.get $2) - (i32.and - (local.get $3) - (i32.const -2) - ) - ) - (i32.store offset=4 - (local.get $0) - (i32.or - (local.get $1) - (i32.const 1) - ) - ) - (i32.store - (i32.add - (local.get $0) - (local.get $1) - ) - (local.get $1) - ) - ) - (block $label$27 - (br_if $label$27 - (i32.gt_u - (local.get $1) - (i32.const 255) - ) - ) - (local.set $1 - (i32.add - (i32.shl - (local.tee $3 - (i32.shr_u - (local.get $1) - (i32.const 3) - ) - ) - (i32.const 3) - ) - (i32.const 1908) - ) - ) - (block $label$28 - (block $label$29 - (br_if $label$29 - (i32.and - (local.tee $4 - (i32.load offset=1868 - (i32.const 0) - ) - ) - (local.tee $3 - (i32.shl - (i32.const 1) - (local.get $3) - ) - ) - ) - ) - (i32.store offset=1868 - (i32.const 0) - (i32.or - (local.get $4) - (local.get $3) - ) - ) - (local.set $3 - (local.get $1) - ) - (br $label$28) - ) - (local.set $3 - (i32.load offset=8 - (local.get $1) - ) - ) - ) - (i32.store offset=8 - (local.get $1) - (local.get $0) - ) - (i32.store offset=12 - (local.get $3) - (local.get $0) - ) - (i32.store offset=12 - (local.get $0) - (local.get $1) - ) - (i32.store offset=8 - (local.get $0) - (local.get $3) - ) - (return) - ) - (local.set $3 - (i32.const 31) - ) - (block $label$30 - (br_if $label$30 - (i32.gt_u - (local.get $1) - (i32.const 16777215) - ) - ) - (local.set $3 - (i32.add - (i32.or - (i32.shl - (local.tee $3 - (i32.sub - (i32.shr_u - (i32.shl - (local.tee $6 - (i32.shl - (local.tee $4 - (i32.shl - (local.tee $3 - (i32.shr_u - (local.get $1) - (i32.const 8) - ) - ) - (local.tee $3 - (i32.and - (i32.shr_u - (i32.add - (local.get $3) - (i32.const 1048320) - ) - (i32.const 16) - ) - (i32.const 8) - ) - ) - ) - ) - (local.tee $4 - (i32.and - (i32.shr_u - (i32.add - (local.get $4) - (i32.const 520192) - ) - (i32.const 16) - ) - (i32.const 4) - ) - ) - ) - ) - (local.tee $6 - (i32.and - (i32.shr_u - (i32.add - (local.get $6) - (i32.const 245760) - ) - (i32.const 16) - ) - (i32.const 2) - ) - ) - ) - (i32.const 15) - ) - (i32.or - (i32.or - (local.get $3) - (local.get $4) - ) - (local.get $6) - ) - ) - ) - (i32.const 1) - ) - (i32.and - (i32.shr_u - (local.get $1) - (i32.add - (local.get $3) - (i32.const 21) - ) - ) - (i32.const 1) - ) - ) - (i32.const 28) - ) - ) - ) - (i64.store offset=16 align=4 - (local.get $0) - (i64.const 0) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 28) - ) - (local.get $3) - ) - (local.set $4 - (i32.add - (i32.shl - (local.get $3) - (i32.const 2) - ) - (i32.const 2172) - ) - ) - (block $label$31 - (block $label$32 - (block $label$33 - (br_if $label$33 - (i32.and - (local.tee $6 - (i32.load offset=1872 - (i32.const 0) - ) - ) - (local.tee $2 - (i32.shl - (i32.const 1) - (local.get $3) - ) - ) - ) - ) - (i32.store offset=1872 - (i32.const 0) - (i32.or - (local.get $6) - (local.get $2) - ) - ) - (i32.store - (local.get $4) - (local.get $0) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 24) - ) - (local.get $4) - ) - (br $label$32) - ) - (local.set $3 - (i32.shl - (local.get $1) - (select - (i32.const 0) - (i32.sub - (i32.const 25) - (i32.shr_u - (local.get $3) - (i32.const 1) - ) - ) - (i32.eq - (local.get $3) - (i32.const 31) - ) - ) - ) - ) - (local.set $6 - (i32.load - (local.get $4) - ) - ) - (loop $label$34 - (br_if $label$31 - (i32.eq - (i32.and - (i32.load offset=4 - (local.tee $4 - (local.get $6) - ) - ) - (i32.const -8) - ) - (local.get $1) - ) - ) - (local.set $6 - (i32.shr_u - (local.get $3) - (i32.const 29) - ) - ) - (local.set $3 - (i32.shl - (local.get $3) - (i32.const 1) - ) - ) - (br_if $label$34 - (local.tee $6 - (i32.load - (local.tee $2 - (i32.add - (i32.add - (local.get $4) - (i32.and - (local.get $6) - (i32.const 4) - ) - ) - (i32.const 16) - ) - ) - ) - ) - ) - ) - (i32.store - (local.get $2) - (local.get $0) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 24) - ) - (local.get $4) - ) - ) - (i32.store offset=12 - (local.get $0) - (local.get $0) - ) - (i32.store offset=8 - (local.get $0) - (local.get $0) - ) - (return) - ) - (i32.store offset=12 - (local.tee $1 - (i32.load offset=8 - (local.get $4) - ) - ) - (local.get $0) - ) - (i32.store offset=8 - (local.get $4) - (local.get $0) - ) - (i32.store - (i32.add - (local.get $0) - (i32.const 24) - ) - (i32.const 0) - ) - (i32.store offset=12 - (local.get $0) - (local.get $4) - ) - (i32.store offset=8 - (local.get $0) - (local.get $1) - ) - ) - ) - (func $66 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local.set $2 - (i32.lt_s - (local.tee $1 - (i32.and - (i32.add - (local.get $0) - (i32.const 3) - ) - (i32.const -4) - ) - ) - (i32.const 1) - ) - ) - (block $label$1 - (loop $label$2 - (local.set $0 - (i32.add - (local.tee $3 - (i32.atomic.load offset=1436 - (i32.const 0) - ) - ) - (local.get $1) - ) - ) - (block $label$3 - (br_if $label$3 - (local.get $2) - ) - (br_if $label$1 - (i32.le_u - (local.get $0) - (local.get $3) - ) - ) - ) - (block $label$4 - (br_if $label$4 - (i32.le_u - (local.get $0) - (i32.shl - (memory.size) - (i32.const 16) - ) - ) - ) - (br_if $label$1 - (i32.eqz - (call $fimport$15 - (local.get $0) - ) - ) - ) - ) - (br_if $label$2 - (i32.ne - (i32.atomic.rmw.cmpxchg offset=1436 - (i32.const 0) - (local.get $3) - (local.get $0) - ) - (local.get $3) - ) - ) - ) - (return - (local.get $3) - ) - ) - (i32.store - (call $25) - (i32.const 48) - ) - (i32.const -1) - ) - (func $67 (param $0 i32) - ) - (func $68 (param $0 i32) - ) - (func $69 (result i32) - (call $67 - (i32.const 2396) - ) - (i32.const 2404) - ) - (func $70 - (call $68 - (i32.const 2396) - ) - ) - (func $71 (param $0 i32) (result i32) - (block $label$1 - (br_if $label$1 - (local.get $0) - ) - (return - (i32.const 0) - ) - ) - (i32.store - (call $25) - (local.get $0) - ) - (i32.const -1) - ) - (func $72 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (local $7 i32) - (local $8 i32) - (local $9 i32) - (global.set $global$0 - (local.tee $3 - (i32.sub - (global.get $global$0) - (i32.const 32) - ) - ) - ) - (i32.store offset=16 - (local.get $3) - (local.tee $4 - (i32.load offset=28 - (local.get $0) - ) - ) - ) - (local.set $5 - (i32.load offset=20 - (local.get $0) - ) - ) - (i32.store offset=28 - (local.get $3) - (local.get $2) - ) - (i32.store offset=24 - (local.get $3) - (local.get $1) - ) - (i32.store offset=20 - (local.get $3) - (local.tee $1 - (i32.sub - (local.get $5) - (local.get $4) - ) - ) - ) - (local.set $6 - (i32.add - (local.get $1) - (local.get $2) - ) - ) - (local.set $7 - (i32.const 2) - ) - (local.set $1 - (i32.add - (local.get $3) - (i32.const 16) - ) - ) - (block $label$1 - (block $label$2 - (block $label$3 - (block $label$4 - (br_if $label$4 - (call $71 - (call $fimport$16 - (i32.load offset=60 - (local.get $0) - ) - (i32.add - (local.get $3) - (i32.const 16) - ) - (i32.const 2) - (i32.add - (local.get $3) - (i32.const 12) - ) - ) - ) - ) - (loop $label$5 - (br_if $label$3 - (i32.eq - (local.get $6) - (local.tee $4 - (i32.load offset=12 - (local.get $3) - ) - ) - ) - ) - (br_if $label$2 - (i32.le_s - (local.get $4) - (i32.const -1) - ) - ) - (i32.store - (local.tee $9 - (i32.add - (local.get $1) - (i32.shl - (local.tee $5 - (i32.gt_u - (local.get $4) - (local.tee $8 - (i32.load offset=4 - (local.get $1) - ) - ) - ) - ) - (i32.const 3) - ) - ) - ) - (i32.add - (i32.load - (local.get $9) - ) - (local.tee $8 - (i32.sub - (local.get $4) - (select - (local.get $8) - (i32.const 0) - (local.get $5) - ) - ) - ) - ) - ) - (i32.store - (local.tee $9 - (i32.add - (local.get $1) - (select - (i32.const 12) - (i32.const 4) - (local.get $5) - ) - ) - ) - (i32.sub - (i32.load - (local.get $9) - ) - (local.get $8) - ) - ) - (local.set $6 - (i32.sub - (local.get $6) - (local.get $4) - ) - ) - (br_if $label$5 - (i32.eqz - (call $71 - (call $fimport$16 - (i32.load offset=60 - (local.get $0) - ) - (local.tee $1 - (select - (i32.add - (local.get $1) - (i32.const 8) - ) - (local.get $1) - (local.get $5) - ) - ) - (local.tee $7 - (i32.sub - (local.get $7) - (local.get $5) - ) - ) - (i32.add - (local.get $3) - (i32.const 12) - ) - ) - ) - ) - ) - ) - ) - (br_if $label$2 - (i32.ne - (local.get $6) - (i32.const -1) - ) - ) - ) - (i32.store offset=28 - (local.get $0) - (local.tee $1 - (i32.load offset=44 - (local.get $0) - ) - ) - ) - (i32.store offset=20 - (local.get $0) - (local.get $1) - ) - (i32.store offset=16 - (local.get $0) - (i32.add - (local.get $1) - (i32.load offset=48 - (local.get $0) - ) - ) - ) - (local.set $4 - (local.get $2) - ) - (br $label$1) - ) - (local.set $4 - (i32.const 0) - ) - (i32.store offset=28 - (local.get $0) - (i32.const 0) - ) - (i64.store offset=16 - (local.get $0) - (i64.const 0) - ) - (i32.store - (local.get $0) - (i32.or - (i32.load - (local.get $0) - ) - (i32.const 32) - ) - ) - (br_if $label$1 - (i32.eq - (local.get $7) - (i32.const 2) - ) - ) - (local.set $4 - (i32.sub - (local.get $2) - (i32.load offset=4 - (local.get $1) - ) - ) - ) - ) - (global.set $global$0 - (i32.add - (local.get $3) - (i32.const 32) - ) - ) - (local.get $4) - ) - (func $73 (param $0 i32) (result i32) - (i32.const 0) - ) - (func $74 (param $0 i32) (param $1 i64) (param $2 i32) (result i64) - (i64.const 0) - ) - (func $75 (param $0 i32) (result i32) - (i32.const 1) - ) - (func $76 (param $0 i32) - ) - (func $77 (result i32) - (global.get $global$0) - ) - (func $78 (param $0 i32) - (global.set $global$0 - (local.get $0) - ) - ) - (func $79 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (global.set $global$0 - (local.tee $1 - (i32.and - (i32.sub - (global.get $global$0) - (local.get $0) - ) - (i32.const -16) - ) - ) - ) - (local.get $1) - ) - (func $80 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (block $label$1 - (block $label$2 - (br_if $label$2 - (i32.eqz - (local.get $0) - ) - ) - (block $label$3 - (br_if $label$3 - (i32.gt_s - (i32.load offset=76 - (local.get $0) - ) - (i32.const -1) - ) - ) - (return - (call $81 - (local.get $0) - ) - ) - ) - (local.set $1 - (call $75 - (local.get $0) - ) - ) - (local.set $2 - (call $81 - (local.get $0) - ) - ) - (br_if $label$1 - (i32.eqz - (local.get $1) - ) - ) - (call $76 - (local.get $0) - ) - (return - (local.get $2) - ) - ) - (local.set $2 - (i32.const 0) - ) - (block $label$4 - (br_if $label$4 - (i32.eqz - (i32.load offset=1584 - (i32.const 0) - ) - ) - ) - (local.set $2 - (call $80 - (i32.load offset=1584 - (i32.const 0) - ) - ) - ) - ) - (block $label$5 - (br_if $label$5 - (i32.eqz - (local.tee $0 - (i32.load - (call $69) - ) - ) - ) - ) - (loop $label$6 - (local.set $1 - (i32.const 0) - ) - (block $label$7 - (br_if $label$7 - (i32.lt_s - (i32.load offset=76 - (local.get $0) - ) - (i32.const 0) - ) - ) - (local.set $1 - (call $75 - (local.get $0) - ) - ) - ) - (block $label$8 - (br_if $label$8 - (i32.le_u - (i32.load offset=20 - (local.get $0) - ) - (i32.load offset=28 - (local.get $0) - ) - ) - ) - (local.set $2 - (i32.or - (call $81 - (local.get $0) - ) - (local.get $2) - ) - ) - ) - (block $label$9 - (br_if $label$9 - (i32.eqz - (local.get $1) - ) - ) - (call $76 - (local.get $0) - ) - ) - (br_if $label$6 - (local.tee $0 - (i32.load offset=56 - (local.get $0) - ) - ) - ) - ) - ) - (call $70) - ) - (local.get $2) - ) - (func $81 (param $0 i32) (result i32) - (local $1 i32) - (local $2 i32) - (block $label$1 - (br_if $label$1 - (i32.le_u - (i32.load offset=20 - (local.get $0) - ) - (i32.load offset=28 - (local.get $0) - ) - ) - ) - (drop - (call_indirect (type $i32_i32_i32_=>_i32) - (local.get $0) - (i32.const 0) - (i32.const 0) - (i32.load offset=36 - (local.get $0) - ) - ) - ) - (br_if $label$1 - (i32.load offset=20 - (local.get $0) - ) - ) - (return - (i32.const -1) - ) - ) - (block $label$2 - (br_if $label$2 - (i32.ge_u - (local.tee $1 - (i32.load offset=4 - (local.get $0) - ) - ) - (local.tee $2 - (i32.load offset=8 - (local.get $0) - ) - ) - ) - ) - (drop - (call_indirect (type $i32_i64_i32_=>_i64) - (local.get $0) - (i64.extend_i32_s - (i32.sub - (local.get $1) - (local.get $2) - ) - ) - (i32.const 1) - (i32.load offset=40 - (local.get $0) - ) - ) - ) - ) - (i32.store offset=28 - (local.get $0) - (i32.const 0) - ) - (i64.store offset=16 - (local.get $0) - (i64.const 0) - ) - (i64.store offset=4 align=4 - (local.get $0) - (i64.const 0) - ) - (i32.const 0) - ) - (func $82 (result i32) - (i32.const 3448) - ) - (func $83 - (call $fimport$17) - (i32.store offset=172 - (call $14) - (i32.add - (i32.const 3448) - (i32.const 40) - ) - ) - ) - (func $84 - (local $0 i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local $6 i32) - (block $label$1 - (br_if $label$1 - (i32.eqz - (i32.load offset=44 - (local.tee $0 - (call $7) - ) - ) - ) - ) - (local.set $1 - (i32.const 0) - ) - (loop $label$2 - (local.set $2 - (i32.const 0) - ) - (local.set $3 - (i32.const 0) - ) - (loop $label$3 - (block $label$4 - (br_if $label$4 - (i32.eqz - (local.tee $6 - (i32.load - (local.tee $5 - (i32.add - (i32.load offset=100 - (local.get $0) - ) - (local.tee $4 - (i32.shl - (local.get $2) - (i32.const 2) - ) - ) - ) - ) - ) - ) - ) - ) - (br_if $label$4 - (i32.eqz - (i32.load - (local.tee $4 - (i32.add - (local.get $4) - (i32.const 3520) - ) - ) - ) - ) - ) - (i32.store - (local.get $5) - (i32.const 0) - ) - (call_indirect (type $i32_=>_none) - (local.get $6) - (i32.load - (local.get $4) - ) - ) - (local.set $3 - (i32.const 1) - ) - ) - (br_if $label$3 - (i32.ne - (local.tee $2 - (i32.add - (local.get $2) - (i32.const 1) - ) - ) - (i32.const 128) - ) - ) - ) - (br_if $label$1 - (i32.gt_u - (local.get $1) - (i32.const 2) - ) - ) - (local.set $1 - (i32.add - (local.get $1) - (i32.const 1) - ) - ) - (br_if $label$2 - (local.get $3) - ) - ) - ) - ) - (func $dynCall_vi (param $fptr i32) (param $0 i32) - (call_indirect (type $i32_=>_none) - (local.get $0) - (local.get $fptr) - ) - ) - (func $dynCall_ii (param $fptr i32) (param $0 i32) (result i32) - (call_indirect (type $i32_=>_i32) - (local.get $0) - (local.get $fptr) - ) - ) - (func $dynCall_iiii (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (call_indirect (type $i32_i32_i32_=>_i32) - (local.get $0) - (local.get $1) - (local.get $2) - (local.get $fptr) - ) - ) - (func $dynCall_jiji (param $fptr i32) (param $0 i32) (param $1 i64) (param $2 i32) (result i64) - (call_indirect (type $i32_i64_i32_=>_i64) - (local.get $0) - (local.get $1) - (local.get $2) - (local.get $fptr) - ) - ) - (func $legalstub$dynCall_jiji (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) - (local $5 i64) - (local.set $5 - (call $dynCall_jiji - (local.get $0) - (local.get $1) - (i64.or - (i64.extend_i32_u - (local.get $2) - ) - (i64.shl - (i64.extend_i32_u - (local.get $3) - ) - (i64.const 32) - ) - ) - (local.get $4) - ) - ) - (call $setTempRet0 - (i32.wrap_i64 - (i64.shr_u - (local.get $5) - (i64.const 32) - ) - ) - ) - (i32.wrap_i64 - (local.get $5) - ) - ) - ;; custom section "producers", size 172 -) -(; ---BEGIN METADATA -- -{ - "asmConsts": { - "1658": "{ console.log(\"Hello.\"); }", - "1685": "throw 'Canceled!'", - "1703": "{ setTimeout(function() { __emscripten_do_dispatch_to_thread($0, $1); }, 0); }" - }, - "emJsFuncs": { - "initPthreadsJS": "(void)<::>{ PThread.initRuntime(); }", - "world": "()<::>{ console.log(\"World.\"); }" - }, - "declares": [ - "emscripten_asm_const_int", - "__cxa_thread_atexit", - "__clock_gettime", - "emscripten_get_now", - "emscripten_conditional_set_current_thread_status", - "emscripten_futex_wait", - "emscripten_futex_wake", - "__assert_fail", - "emscripten_set_current_thread_status", - "_emscripten_notify_thread_queue", - "emscripten_webgl_create_context", - "emscripten_set_canvas_element_size", - "pthread_create", - "emscripten_receive_on_main_thread_js", - "emscripten_resize_heap", - "fd_write", - "setTempRet0" - ], - "globalImports": [ - ], - "exports": [ - "__wasm_call_ctors", - "main", - "emscripten_tls_init", - "emscripten_get_global_libc", - "__errno_location", - "fflush", - "__emscripten_pthread_data_constructor", - "pthread_self", - "__pthread_tsd_run_dtors", - "emscripten_current_thread_process_queued_calls", - "emscripten_register_main_browser_thread_id", - "emscripten_main_browser_thread_id", - "_emscripten_do_dispatch_to_thread", - "emscripten_sync_run_in_main_thread_2", - "emscripten_sync_run_in_main_thread_4", - "emscripten_main_thread_process_queued_calls", - "emscripten_run_in_main_runtime_thread_js", - "_emscripten_call_on_thread", - "_emscripten_thread_init", - "stackSave", - "stackRestore", - "stackAlloc", - "emscripten_stack_init", - "emscripten_stack_set_limits", - "emscripten_stack_get_free", - "emscripten_stack_get_end", - "malloc", - "free", - "memalign", - "dynCall_vi", - "dynCall_ii", - "dynCall_iiii", - "dynCall_jiji" - ], - "namedGlobals": { - "_emscripten_allow_main_runtime_queued_calls" : "1432", - "_emscripten_main_thread_futex" : "1836" - }, - "invokeFuncs": [ - ], - "mainReadsParams": 1, - "features": [ - "--enable-threads", - "--enable-mutable-globals", - "--enable-bulk-memory", - "--enable-sign-ext" - ] -} --- END METADATA -- -;) diff -Nru binaryen-108/test/lld/em_asm_shared.wat binaryen-99/test/lld/em_asm_shared.wat --- binaryen-108/test/lld/em_asm_shared.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_shared.wat 2021-01-07 20:01:06.000000000 +0000 @@ -3,41 +3,37 @@ (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (import "env" "memory" (memory $mimport$0 1)) - (data $.data (global.get $__memory_base) "\00ii\00i\00{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") + (import "env" "memory" (memory $mimport$0 0)) + (data (global.get $gimport$1) "{ Module.print(\"Hello world\"); }\00\00{ return $0 + $1; }\00ii\00{ Module.print(\"Got \" + $0); }\00i\00") (import "env" "__indirect_function_table" (table $timport$0 0 funcref)) - (import "env" "__stack_pointer" (global $__stack_pointer (mut i32))) - (import "env" "__memory_base" (global $__memory_base i32)) - (import "env" "__table_base" (global $__table_base i32)) - (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $__em_asm_sig_builder<__em_asm_type_tuple<>\20>::buffer (mut i32))) - (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" (global $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer (mut i32))) - (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" (global $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer (mut i32))) + (import "env" "__stack_pointer" (global $gimport$0 (mut i32))) + (import "env" "__memory_base" (global $gimport$1 i32)) + (import "env" "__table_base" (global $gimport$2 i32)) + (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $gimport$3 (mut i32))) + (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" (global $gimport$4 (mut i32))) + (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" (global $gimport$5 (mut i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) - (global $global$0 i32 (i32.const 0)) - (global $global$1 i32 (i32.const 1)) - (global $global$2 i32 (i32.const 4)) - (global $global$3 i32 (i32.const 6)) - (global $global$4 i32 (i32.const 90)) + (global $global$0 i32 (i32.const 33)) + (global $global$1 i32 (i32.const 54)) + (global $global$2 i32 (i32.const 88)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "__original_main" (func $__original_main)) (export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $global$0)) (export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" (global $global$1)) (export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" (global $global$2)) (export "main" (func $main)) - (export "__start_em_asm" (global $global$3)) - (export "__stop_em_asm" (global $global$4)) (func $__wasm_call_ctors - (call $__wasm_apply_data_relocs) + (call $__wasm_apply_relocs) ) - (func $__wasm_apply_data_relocs + (func $__wasm_apply_relocs ) (func $__original_main (result i32) (local $0 i32) (local $1 i32) - (global.set $__stack_pointer + (global.set $gimport$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $gimport$0) (i32.const 32) ) ) @@ -46,11 +42,11 @@ (call $emscripten_asm_const_int (i32.add (local.tee $1 - (global.get $__memory_base) + (global.get $gimport$1) ) - (i32.const 6) + (i32.const 0) ) - (global.get $__em_asm_sig_builder<__em_asm_type_tuple<>\20>::buffer) + (global.get $gimport$3) (i32.const 0) ) ) @@ -63,9 +59,9 @@ (call $emscripten_asm_const_int (i32.add (local.get $1) - (i32.const 39) + (i32.const 34) ) - (global.get $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer) + (global.get $gimport$4) (i32.add (local.get $0) (i32.const 16) @@ -76,13 +72,13 @@ (call $emscripten_asm_const_int (i32.add (local.get $1) - (i32.const 59) + (i32.const 57) ) - (global.get $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer) + (global.get $gimport$5) (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $gimport$0 (i32.add (local.get $0) (i32.const 32) @@ -93,8 +89,11 @@ (func $main (param $0 i32) (param $1 i32) (result i32) (call $__original_main) ) - ;; custom section "dylink.0", size 6 + ;; dylink section + ;; memorysize: 90 + ;; memoryalignment: 0 + ;; tablesize: 0 + ;; tablealignment: 0 ;; custom section "producers", size 112 - ;; features section: mutable-globals ) diff -Nru binaryen-108/test/lld/em_asm_shared.wat.out binaryen-99/test/lld/em_asm_shared.wat.out --- binaryen-108/test/lld/em_asm_shared.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_shared.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,42 +1,40 @@ (module (type $none_=>_none (func)) - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (import "env" "memory" (memory $mimport$0 1)) - (data $.data (global.get $__memory_base) "\00ii\00i\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (import "env" "memory" (memory $mimport$0 0)) + (data (global.get $gimport$1) "{ Module.print(\"Hello world\"); }\00\00{ return $0 + $1; }\00ii\00{ Module.print(\"Got \" + $0); }\00i\00") (import "env" "__indirect_function_table" (table $timport$0 0 funcref)) - (import "env" "__stack_pointer" (global $__stack_pointer (mut i32))) - (import "env" "__memory_base" (global $__memory_base i32)) - (import "env" "__table_base" (global $__table_base i32)) - (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $__em_asm_sig_builder<__em_asm_type_tuple<>\20>::buffer (mut i32))) - (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" (global $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer (mut i32))) - (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" (global $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer (mut i32))) + (import "env" "__stack_pointer" (global $gimport$0 (mut i32))) + (import "env" "__memory_base" (global $gimport$1 i32)) + (import "env" "__table_base" (global $gimport$2 i32)) + (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $gimport$3 (mut i32))) + (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" (global $gimport$4 (mut i32))) + (import "GOT.mem" "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" (global $gimport$5 (mut i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) - (global $global$0 i32 (i32.const 0)) - (global $global$1 i32 (i32.const 1)) - (global $global$2 i32 (i32.const 4)) - (global $global$3 i32 (i32.const 6)) - (global $global$4 i32 (i32.const 90)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (global $global$0 i32 (i32.const 33)) + (global $global$1 i32 (i32.const 54)) + (global $global$2 i32 (i32.const 88)) + (export "__post_instantiate" (func $__wasm_call_ctors)) (export "__original_main" (func $__original_main)) (export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" (global $global$0)) (export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" (global $global$1)) (export "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" (global $global$2)) (export "main" (func $main)) (func $__wasm_call_ctors - (call $__wasm_apply_data_relocs) + (call $__wasm_apply_relocs) ) - (func $__wasm_apply_data_relocs + (func $__wasm_apply_relocs (nop) ) (func $__original_main (result i32) (local $0 i32) (local $1 i32) - (global.set $__stack_pointer + (global.set $gimport$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $gimport$0) (i32.const 32) ) ) @@ -45,11 +43,11 @@ (call $emscripten_asm_const_int (i32.add (local.tee $1 - (global.get $__memory_base) + (global.get $gimport$1) ) - (i32.const 6) + (i32.const 0) ) - (global.get $__em_asm_sig_builder<__em_asm_type_tuple<>\20>::buffer) + (global.get $gimport$3) (i32.const 0) ) ) @@ -62,9 +60,9 @@ (call $emscripten_asm_const_int (i32.add (local.get $1) - (i32.const 39) + (i32.const 34) ) - (global.get $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer) + (global.get $gimport$4) (i32.add (local.get $0) (i32.const 16) @@ -75,13 +73,13 @@ (call $emscripten_asm_const_int (i32.add (local.get $1) - (i32.const 59) + (i32.const 57) ) - (global.get $__em_asm_sig_builder<__em_asm_type_tuple\20>::buffer) + (global.get $gimport$5) (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $gimport$0 (i32.add (local.get $0) (i32.const 32) @@ -97,30 +95,31 @@ --BEGIN METADATA -- { "asmConsts": { - "6": "{ Module.print(\"Hello world\"); }", - "39": "{ return $0 + $1; }", - "59": "{ Module.print(\"Got \" + $0); }" + "0": ["{ Module.print(\"Hello world\"); }", ["iii"], [""]], + "34": ["{ return $0 + $1; }", ["iii"], [""]], + "57": ["{ Module.print(\"Got \" + $0); }", ["iii"], [""]] }, + "tableSize": 0, "declares": [ "emscripten_asm_const_int" ], - "globalImports": [ - "__stack_pointer", - "__memory_base", - "__table_base", - "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE", - "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE", - "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" + "externs": [ + "___stack_pointer", + "___memory_base", + "___table_base", + "__ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE", + "__ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE", + "__ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" ], "exports": [ - "__wasm_call_ctors", + "__post_instantiate", "__original_main", "main" ], "namedGlobals": { - "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" : "0", - "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" : "1", - "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" : "4" + "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJEEE6bufferE" : "33", + "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiiEEE6bufferE" : "54", + "_ZN20__em_asm_sig_builderI19__em_asm_type_tupleIJiEEE6bufferE" : "88" }, "invokeFuncs": [ ], diff -Nru binaryen-108/test/lld/em_asm_table.wat.out binaryen-99/test/lld/em_asm_table.wat.out --- binaryen-108/test/lld/em_asm_table.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm_table.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,27 +1,27 @@ (module - (type $0 (func (param i32 i32))) - (type $1 (func (param i32 i32 i32) (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory $2 8192)) (import "env" "emscripten_log" (func $fimport$0 (param i32 i32))) (import "env" "emscripten_asm_const_int" (func $fimport$1 (param i32 i32 i32) (result i32))) - (global $global$0 (mut i32) (i32.const 1024)) - (global $global$1 i32 (i32.const 1048)) (table $0 159609 funcref) (elem (i32.const 1) $fimport$0 $fimport$1) + (global $global$0 (mut i32) (i32.const 1024)) + (global $global$1 i32 (i32.const 1048)) (export "__data_end" (global $global$1)) (export "dynCall_vii" (func $dynCall_vii)) (export "dynCall_iiii" (func $dynCall_iiii)) (func $dynCall_vii (param $fptr i32) (param $0 i32) (param $1 i32) - (call_indirect (type $0) + (call_indirect (type $i32_i32_=>_none) (local.get $0) (local.get $1) (local.get $fptr) ) ) (func $dynCall_iiii (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (call_indirect (type $1) + (call_indirect (type $i32_i32_i32_=>_i32) (local.get $0) (local.get $1) (local.get $2) @@ -32,11 +32,12 @@ (; --BEGIN METADATA -- { + "tableSize": 159609, "declares": [ "emscripten_log", "emscripten_asm_const_int" ], - "globalImports": [ + "externs": [ ], "exports": [ "dynCall_vii", diff -Nru binaryen-108/test/lld/em_asm.wat binaryen-99/test/lld/em_asm.wat --- binaryen-108/test/lld/em_asm.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm.wat 2021-01-07 20:01:06.000000000 +0000 @@ -5,33 +5,28 @@ (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) (memory $0 2) - (data $.rodata (i32.const 568) "\00ii\00i\00") - (data $em_asm (i32.const 574) "{ Module.print(\"Hello \\\\ world\\t\\n\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00") + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00\00{ return $0 + $1; }\00ii\00{ Module.print(\"Got \" + $0); }\00i\00") (table $0 1 1 funcref) - (global $__stack_pointer (mut i32) (i32.const 66208)) - (global $global$1 i32 (i32.const 574)) - (global $global$2 i32 (i32.const 665)) + (global $global$0 (mut i32) (i32.const 66208)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) - (export "__start_em_asm" (global $global$1)) - (export "__stop_em_asm" (global $global$2)) (func $__wasm_call_ctors ) (func $__original_main (result i32) (local $0 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 32) ) ) ) (drop (call $emscripten_asm_const_int - (i32.const 574) (i32.const 568) + (i32.const 601) (i32.const 0) ) ) @@ -42,8 +37,8 @@ (i32.store (local.get $0) (call $emscripten_asm_const_int - (i32.const 614) - (i32.const 569) + (i32.const 602) + (i32.const 622) (i32.add (local.get $0) (i32.const 16) @@ -52,12 +47,12 @@ ) (drop (call $emscripten_asm_const_int - (i32.const 634) - (i32.const 572) + (i32.const 625) + (i32.const 656) (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $0) (i32.const 32) Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/lld/em_asm.wat.mem.mem and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/lld/em_asm.wat.mem.mem differ diff -Nru binaryen-108/test/lld/em_asm.wat.mem.out binaryen-99/test/lld/em_asm.wat.mem.out --- binaryen-108/test/lld/em_asm.wat.mem.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm.wat.mem.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,14 +1,12 @@ (module - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66208)) - (global $global$1 i32 (i32.const 574)) - (global $global$2 i32 (i32.const 665)) (memory $0 2) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66208)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -17,18 +15,18 @@ ) (func $__original_main (result i32) (local $0 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 32) ) ) ) (drop (call $emscripten_asm_const_int - (i32.const 574) (i32.const 568) + (i32.const 601) (i32.const 0) ) ) @@ -39,8 +37,8 @@ (i32.store (local.get $0) (call $emscripten_asm_const_int - (i32.const 614) - (i32.const 569) + (i32.const 602) + (i32.const 622) (i32.add (local.get $0) (i32.const 16) @@ -49,12 +47,12 @@ ) (drop (call $emscripten_asm_const_int - (i32.const 634) - (i32.const 572) + (i32.const 625) + (i32.const 656) (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $0) (i32.const 32) @@ -70,14 +68,18 @@ --BEGIN METADATA -- { "asmConsts": { - "574": "{ Module.print(\"Hello \\ world\\t\\n\"); }", - "614": "{ return $0 + $1; }", - "634": "{ Module.print(\"Got \" + $0); }" + "568": ["{ Module.print(\"Hello world\"); }", ["iii"], [""]], + "602": ["{ return $0 + $1; }", ["iii"], [""]], + "625": ["{ Module.print(\"Got \" + $0); }", ["iii"], [""]] }, + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "emscripten_asm_const_int" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/em_asm.wat.out binaryen-99/test/lld/em_asm.wat.out --- binaryen-108/test/lld/em_asm.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_asm.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,16 +1,13 @@ (module - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66208)) - (global $global$1 i32 (i32.const 574)) - (global $global$2 i32 (i32.const 665)) (memory $0 2) - (data $.rodata (i32.const 568) "\00ii\00i\00") - (data $em_asm (i32.const 574) "") + (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00\00{ return $0 + $1; }\00ii\00{ Module.print(\"Got \" + $0); }\00i\00") (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66208)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -19,18 +16,18 @@ ) (func $__original_main (result i32) (local $0 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 32) ) ) ) (drop (call $emscripten_asm_const_int - (i32.const 574) (i32.const 568) + (i32.const 601) (i32.const 0) ) ) @@ -41,8 +38,8 @@ (i32.store (local.get $0) (call $emscripten_asm_const_int - (i32.const 614) - (i32.const 569) + (i32.const 602) + (i32.const 622) (i32.add (local.get $0) (i32.const 16) @@ -51,12 +48,12 @@ ) (drop (call $emscripten_asm_const_int - (i32.const 634) - (i32.const 572) + (i32.const 625) + (i32.const 656) (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $0) (i32.const 32) @@ -72,14 +69,18 @@ --BEGIN METADATA -- { "asmConsts": { - "574": "{ Module.print(\"Hello \\ world\\t\\n\"); }", - "614": "{ return $0 + $1; }", - "634": "{ Module.print(\"Got \" + $0); }" + "568": ["{ Module.print(\"Hello world\"); }", ["iii"], [""]], + "602": ["{ return $0 + $1; }", ["iii"], [""]], + "625": ["{ Module.print(\"Got \" + $0); }", ["iii"], [""]] }, + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "emscripten_asm_const_int" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/em_js_O0.wat.out binaryen-99/test/lld/em_js_O0.wat.out --- binaryen-108/test/lld/em_js_O0.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/em_js_O0.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -15,9 +15,10 @@ "emJsFuncs": { "noarg": "(void)<::>{ out(\"no args works\"); }" }, + "tableSize": 0, "declares": [ ], - "globalImports": [ + "externs": [ ], "exports": [ ], diff -Nru binaryen-108/test/lld/hello_world.passive.wat binaryen-99/test/lld/hello_world.passive.wat --- binaryen-108/test/lld/hello_world.passive.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/hello_world.passive.wat 2021-01-07 20:01:06.000000000 +0000 @@ -5,7 +5,7 @@ (type $3 (func (param i32 i32) (result i32))) (import "env" "puts" (func $puts (param i32) (result i32))) (memory $0 2) - (data "Hello, world\00") + (data passive "Hello, world\00") (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 66128)) (global $global$1 i32 (i32.const 66128)) diff -Nru binaryen-108/test/lld/hello_world.passive.wat.out binaryen-99/test/lld/hello_world.passive.wat.out --- binaryen-108/test/lld/hello_world.passive.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/hello_world.passive.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,15 @@ (module - (type $1 (func)) - (type $0 (func (param i32) (result i32))) - (type $2 (func (result i32))) - (type $3 (func (param i32 i32) (result i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "puts" (func $puts (param i32) (result i32))) + (memory $0 2) + (data passive "Hello, world\00") + (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 66128)) (global $global$1 i32 (i32.const 66128)) (global $global$2 i32 (i32.const 581)) - (memory $0 2) - (data "Hello, world\00") - (table $0 1 1 funcref) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "__heap_base" (global $global$1)) @@ -40,10 +40,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "puts" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/hello_world.wat binaryen-99/test/lld/hello_world.wat --- binaryen-108/test/lld/hello_world.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/hello_world.wat 2021-01-07 20:01:06.000000000 +0000 @@ -5,9 +5,9 @@ (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "puts" (func $puts (param i32) (result i32))) (memory $0 2) - (data $.rodata (i32.const 568) "Hello, world\00") + (data (i32.const 568) "Hello, world\00") (table $0 1 1 funcref) - (global $__stack_pointer (mut i32) (i32.const 66128)) + (global $global$0 (mut i32) (i32.const 66128)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) diff -Nru binaryen-108/test/lld/hello_world.wat.mem.out binaryen-99/test/lld/hello_world.wat.mem.out --- binaryen-108/test/lld/hello_world.wat.mem.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/hello_world.wat.mem.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "puts" (func $puts (param i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66128)) (memory $0 2) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66128)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -28,10 +28,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "puts" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/hello_world.wat.out binaryen-99/test/lld/hello_world.wat.out --- binaryen-108/test/lld/hello_world.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/hello_world.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,13 +1,13 @@ (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "puts" (func $puts (param i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66128)) (memory $0 2) - (data $.rodata (i32.const 568) "Hello, world\00") + (data (i32.const 568) "Hello, world\00") (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66128)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -29,10 +29,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "puts" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/init.c binaryen-99/test/lld/init.c --- binaryen-108/test/lld/init.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/init.c 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,15 @@ volatile int x, y; -__attribute__((constructor)) void init_x() { x = 14; } +__attribute__((constructor)) +void init_x() { + x = 14; +} -__attribute__((constructor)) void init_y() { y = 144; } +__attribute__((constructor)) +void init_y() { + y = 144; +} -int main() { return x + y; } +int main() { + return x + y; +} diff -Nru binaryen-108/test/lld/init.wat binaryen-99/test/lld/init.wat --- binaryen-108/test/lld/init.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/init.wat 2021-01-07 20:01:06.000000000 +0000 @@ -4,7 +4,7 @@ (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (memory $0 2) (table $0 1 1 funcref) - (global $__stack_pointer (mut i32) (i32.const 66112)) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) diff -Nru binaryen-108/test/lld/init.wat.out binaryen-99/test/lld/init.wat.out --- binaryen-108/test/lld/init.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/init.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -2,9 +2,9 @@ (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66112)) (memory $0 2) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -41,9 +41,13 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/longjmp.wat binaryen-99/test/lld/longjmp.wat --- binaryen-108/test/lld/longjmp.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/longjmp.wat 2021-01-07 20:01:06.000000000 +0000 @@ -8,38 +8,38 @@ (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - (import "env" "malloc" (func $malloc (param i32) (result i32))) - (import "env" "saveSetjmp" (func $saveSetjmp (param i32 i32 i32 i32) (result i32))) - (import "env" "getTempRet0" (func $getTempRet0 (result i32))) - (import "env" "emscripten_longjmp" (func $emscripten_longjmp (param i32 i32))) - (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - (import "env" "testSetjmp" (func $testSetjmp (param i32 i32 i32) (result i32))) - (import "env" "setTempRet0" (func $setTempRet0 (param i32))) - (import "env" "free" (func $free (param i32))) + (import "env" "malloc" (func $fimport$0 (param i32) (result i32))) + (import "env" "saveSetjmp" (func $fimport$1 (param i32 i32 i32 i32) (result i32))) + (import "env" "getTempRet0" (func $fimport$2 (result i32))) + (import "env" "emscripten_longjmp" (func $fimport$3 (param i32 i32))) + (import "env" "invoke_vii" (func $fimport$4 (param i32 i32 i32))) + (import "env" "testSetjmp" (func $fimport$5 (param i32 i32 i32) (result i32))) + (import "env" "setTempRet0" (func $fimport$6 (param i32))) + (import "env" "free" (func $fimport$7 (param i32))) (memory $0 2) (table $0 2 2 funcref) - (elem (i32.const 1) $emscripten_longjmp) - (global $__stack_pointer (mut i32) (i32.const 66112)) + (elem (i32.const 1) $fimport$3) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) - (export "main" (func $main)) - (func $__wasm_call_ctors + (export "__wasm_call_ctors" (func $0)) + (export "main" (func $2)) + (func $0 ) - (func $__original_main (result i32) + (func $1 (result i32) (local $0 i32) (local $1 i32) (local $2 i32) (local $3 i32) (i32.store (local.tee $0 - (call $malloc + (call $fimport$0 (i32.const 40) ) ) (i32.const 0) ) (local.set $1 - (call $saveSetjmp + (call $fimport$1 (local.get $0) (i32.const 1) (local.get $0) @@ -47,7 +47,7 @@ ) ) (local.set $2 - (call $getTempRet0) + (call $fimport$2) ) (local.set $0 (i32.const 0) @@ -62,7 +62,7 @@ (i32.const 0) (i32.const 0) ) - (call $invoke_vii + (call $fimport$4 (i32.const 1) (local.get $0) (i32.const 1) @@ -93,7 +93,7 @@ ) (br_if $label$1 (i32.eqz - (call $testSetjmp + (call $fimport$5 (i32.load (local.get $0) ) @@ -102,34 +102,31 @@ ) ) ) - (call $setTempRet0 + (call $fimport$6 (local.get $3) ) ) (local.set $0 - (call $getTempRet0) + (call $fimport$2) ) (br $label$3) ) ) - (call $free + (call $fimport$7 (local.get $1) ) (return (i32.const 0) ) ) - (call $free - (local.get $1) - ) - (call $emscripten_longjmp + (call $fimport$3 (local.get $0) (local.get $3) ) (unreachable) ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (call $__original_main) + (func $2 (param $0 i32) (param $1 i32) (result i32) + (call $1) ) ;; custom section "producers", size 112 ) diff -Nru binaryen-108/test/lld/longjmp.wat.out binaryen-99/test/lld/longjmp.wat.out --- binaryen-108/test/lld/longjmp.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/longjmp.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,47 +1,47 @@ (module - (type $none_=>_i32 (func (result i32))) + (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (import "env" "malloc" (func $malloc (param i32) (result i32))) - (import "env" "saveSetjmp" (func $saveSetjmp (param i32 i32 i32 i32) (result i32))) - (import "env" "getTempRet0" (func $getTempRet0 (result i32))) - (import "env" "emscripten_longjmp" (func $emscripten_longjmp (param i32 i32))) - (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - (import "env" "testSetjmp" (func $testSetjmp (param i32 i32 i32) (result i32))) - (import "env" "setTempRet0" (func $setTempRet0 (param i32))) - (import "env" "free" (func $free (param i32))) - (global $__stack_pointer (mut i32) (i32.const 66112)) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (import "env" "malloc" (func $fimport$0 (param i32) (result i32))) + (import "env" "saveSetjmp" (func $fimport$1 (param i32 i32 i32 i32) (result i32))) + (import "env" "getTempRet0" (func $fimport$2 (result i32))) + (import "env" "emscripten_longjmp" (func $fimport$3 (param i32 i32))) + (import "env" "invoke_vii" (func $fimport$4 (param i32 i32 i32))) + (import "env" "testSetjmp" (func $fimport$5 (param i32 i32 i32) (result i32))) + (import "env" "setTempRet0" (func $fimport$6 (param i32))) + (import "env" "free" (func $fimport$7 (param i32))) (memory $0 2) (table $0 2 2 funcref) - (elem (i32.const 1) $emscripten_longjmp) + (elem (i32.const 1) $fimport$3) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) - (export "main" (func $main)) + (export "__wasm_call_ctors" (func $0)) + (export "main" (func $2)) (export "dynCall_vii" (func $dynCall_vii)) - (func $__wasm_call_ctors + (func $0 (nop) ) - (func $__original_main (result i32) + (func $1 (result i32) (local $0 i32) (local $1 i32) (local $2 i32) (local $3 i32) (i32.store (local.tee $0 - (call $malloc + (call $fimport$0 (i32.const 40) ) ) (i32.const 0) ) (local.set $1 - (call $saveSetjmp + (call $fimport$1 (local.get $0) (i32.const 1) (local.get $0) @@ -49,7 +49,7 @@ ) ) (local.set $2 - (call $getTempRet0) + (call $fimport$2) ) (local.set $0 (i32.const 0) @@ -64,7 +64,7 @@ (i32.const 0) (i32.const 0) ) - (call $invoke_vii + (call $fimport$4 (i32.const 1) (local.get $0) (i32.const 1) @@ -95,7 +95,7 @@ ) (br_if $label$1 (i32.eqz - (call $testSetjmp + (call $fimport$5 (i32.load (local.get $0) ) @@ -104,34 +104,31 @@ ) ) ) - (call $setTempRet0 + (call $fimport$6 (local.get $3) ) ) (local.set $0 - (call $getTempRet0) + (call $fimport$2) ) (br $label$3) ) ) - (call $free + (call $fimport$7 (local.get $1) ) (return (i32.const 0) ) ) - (call $free - (local.get $1) - ) - (call $emscripten_longjmp + (call $fimport$3 (local.get $0) (local.get $3) ) (unreachable) ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (call $__original_main) + (func $2 (param $0 i32) (param $1 i32) (result i32) + (call $1) ) (func $dynCall_vii (param $fptr i32) (param $0 i32) (param $1 i32) (call_indirect (type $i32_i32_=>_none) @@ -144,6 +141,10 @@ (; --BEGIN METADATA -- { + "tableSize": 2, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "malloc", "saveSetjmp", @@ -153,7 +154,7 @@ "setTempRet0", "free" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/main_module_table_2.wat.out binaryen-99/test/lld/main_module_table_2.wat.out --- binaryen-108/test/lld/main_module_table_2.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/main_module_table_2.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -13,11 +13,12 @@ (; --BEGIN METADATA -- { + "tableSize": 1, "declares": [ ], - "globalImports": [ - "__stack_pointer", - "__stdio_write" + "externs": [ + "___stack_pointer", + "___stdio_write" ], "exports": [ "__stdio_write" diff -Nru binaryen-108/test/lld/main_module_table_3.wat.out binaryen-99/test/lld/main_module_table_3.wat.out --- binaryen-108/test/lld/main_module_table_3.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/main_module_table_3.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -4,7 +4,6 @@ (import "env" "__stack_pointer" (global $sp (mut i32))) (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) (global $global i32 (i32.const 42)) - (elem (i32.const 0)) (export "__stdio_write" (func $__stdio_write)) (export "__data_end" (global $global)) (func $__stdio_write @@ -14,11 +13,12 @@ (; --BEGIN METADATA -- { + "tableSize": 1, "declares": [ ], - "globalImports": [ - "__stack_pointer", - "__stdio_write" + "externs": [ + "___stack_pointer", + "___stdio_write" ], "exports": [ "__stdio_write" diff -Nru binaryen-108/test/lld/main_module_table_4.wat.out binaryen-99/test/lld/main_module_table_4.wat.out --- binaryen-108/test/lld/main_module_table_4.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/main_module_table_4.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -5,7 +5,6 @@ (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) (import "env" "__table_base" (global $tb i32)) (global $global i32 (i32.const 42)) - (elem (global.get $tb)) (export "__stdio_write" (func $__stdio_write)) (export "__data_end" (global $global)) (func $__stdio_write @@ -15,12 +14,13 @@ (; --BEGIN METADATA -- { + "tableSize": 1, "declares": [ ], - "globalImports": [ - "__stack_pointer", - "__stdio_write", - "__table_base" + "externs": [ + "___stack_pointer", + "___stdio_write", + "___table_base" ], "exports": [ "__stdio_write" diff -Nru binaryen-108/test/lld/main_module_table_5.wat.out binaryen-99/test/lld/main_module_table_5.wat.out --- binaryen-108/test/lld/main_module_table_5.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/main_module_table_5.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -2,11 +2,11 @@ (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (import "env" "table" (table $timport$9 1 funcref)) + (elem (global.get $tb) $other $stuff) (import "env" "__stack_pointer" (global $sp (mut i32))) (import "GOT.func" "__stdio_write" (global $gimport$9 (mut i32))) (import "env" "__table_base" (global $tb i32)) (global $global i32 (i32.const 42)) - (elem (global.get $tb) $other $stuff) (export "__stdio_write" (func $__stdio_write)) (export "__data_end" (global $global)) (export "dynCall_v" (func $dynCall_v)) @@ -28,12 +28,13 @@ (; --BEGIN METADATA -- { + "tableSize": 1, "declares": [ ], - "globalImports": [ - "__stack_pointer", - "__stdio_write", - "__table_base" + "externs": [ + "___stack_pointer", + "___stdio_write", + "___table_base" ], "exports": [ "__stdio_write", diff -Nru binaryen-108/test/lld/main_module_table.wat.out binaryen-99/test/lld/main_module_table.wat.out --- binaryen-108/test/lld/main_module_table.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/main_module_table.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -12,11 +12,12 @@ (; --BEGIN METADATA -- { + "tableSize": 0, "declares": [ ], - "globalImports": [ - "__stack_pointer", - "__stdio_write" + "externs": [ + "___stack_pointer", + "___stdio_write" ], "exports": [ "__stdio_write" diff -Nru binaryen-108/test/lld/main_module.wat.out binaryen-99/test/lld/main_module.wat.out --- binaryen-108/test/lld/main_module.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/main_module.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $1 (func)) - (type $0 (func (param i32) (result i32))) - (type $2 (func (result i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "memory" (memory $0 0)) (data (global.get $gimport$2) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00") (import "env" "__indirect_function_table" (table $timport$1 0 funcref)) @@ -56,16 +56,20 @@ (; --BEGIN METADATA -- { + "tableSize": 0, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "puts" ], - "globalImports": [ - "__stack_pointer", - "__memory_base", - "__table_base", - "external_var", - "puts", - "_Z13print_messagev" + "externs": [ + "___stack_pointer", + "___memory_base", + "___table_base", + "_external_var", + "_puts", + "__Z13print_messagev" ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/no-emit-metadata.wat binaryen-99/test/lld/no-emit-metadata.wat --- binaryen-108/test/lld/no-emit-metadata.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/no-emit-metadata.wat 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -(module - (memory $0 2) - (table $0 1 1 funcref) - (elem (i32.const 0) $foo) - (global $global$0 (mut i32) (i32.const 66112)) - (global $global$1 i32 (i32.const 66112)) - (global $global$2 i32 (i32.const 576)) - (export "memory" (memory $0)) - (export "main" (func $main)) - (export "__heap_base" (global $global$1)) - (export "__data_end" (global $global$2)) - (func $__original_main (result i32) - (nop) - ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (call $__original_main) - ) - (func $foo (result i32)) -) - diff -Nru binaryen-108/test/lld/no-emit-metadata.wat.out binaryen-99/test/lld/no-emit-metadata.wat.out --- binaryen-108/test/lld/no-emit-metadata.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/no-emit-metadata.wat.out 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (global $global$0 (mut i32) (i32.const 66112)) - (global $global$1 i32 (i32.const 66112)) - (global $global$2 i32 (i32.const 576)) - (memory $0 2) - (table $0 1 1 funcref) - (elem (i32.const 0) $foo) - (export "memory" (memory $0)) - (export "main" (func $main)) - (export "__heap_base" (global $global$1)) - (export "__data_end" (global $global$2)) - (export "dynCall_i" (func $dynCall_i)) - (func $__original_main (result i32) - (nop) - ) - (func $main (param $0 i32) (param $1 i32) (result i32) - (call $__original_main) - ) - (func $foo (result i32) - (nop) - ) - (func $dynCall_i (param $fptr i32) (result i32) - (call_indirect (type $none_=>_i32) - (local.get $fptr) - ) - ) -) diff -Nru binaryen-108/test/lld/recursive.c binaryen-99/test/lld/recursive.c --- binaryen-108/test/lld/recursive.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/recursive.c 2021-01-07 20:01:06.000000000 +0000 @@ -3,9 +3,10 @@ int printf(const char* fmt, ...); -__attribute__((noinline)) int foo(int a, int b) { - printf("%d:%d\n", a, b); - return a + b; +__attribute__((noinline)) +int foo(int a, int b) { + printf("%d:%d\n", a, b); + return a + b; } int main() { diff -Nru binaryen-108/test/lld/recursive_safe_stack.wat.out binaryen-99/test/lld/recursive_safe_stack.wat.out --- binaryen-108/test/lld/recursive_safe_stack.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/recursive_safe_stack.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,19 +1,18 @@ (module - (type $0 (func (param i32 i32) (result i32))) - (type $1 (func)) - (type $2 (func (result i32))) - (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_none (func)) (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "printf" (func $printf (param i32 i32) (result i32))) - (import "env" "__handle_stack_overflow" (func $__handle_stack_overflow (param i32))) + (import "env" "__handle_stack_overflow" (func $__handle_stack_overflow)) + (memory $0 2) + (data (i32.const 568) "%d:%d\n\00Result: %d\n\00") + (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 66128)) (global $global$1 i32 (i32.const 66128)) (global $global$2 i32 (i32.const 587)) (global $__stack_base (mut i32) (i32.const 0)) (global $__stack_limit (mut i32) (i32.const 0)) - (memory $0 2) - (data (i32.const 568) "%d:%d\n\00Result: %d\n\00") - (table $0 1 1 funcref) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "__heap_base" (global $global$1)) @@ -46,9 +45,7 @@ (global.get $__stack_limit) ) ) - (call $__handle_stack_overflow - (local.get $3) - ) + (call $__handle_stack_overflow) ) (global.set $global$0 (local.get $3) @@ -85,9 +82,7 @@ (global.get $__stack_limit) ) ) - (call $__handle_stack_overflow - (local.get $4) - ) + (call $__handle_stack_overflow) ) (global.set $global$0 (local.get $4) @@ -121,9 +116,7 @@ (global.get $__stack_limit) ) ) - (call $__handle_stack_overflow - (local.get $1) - ) + (call $__handle_stack_overflow) ) (global.set $global$0 (local.get $1) @@ -159,9 +152,7 @@ (global.get $__stack_limit) ) ) - (call $__handle_stack_overflow - (local.get $2) - ) + (call $__handle_stack_overflow) ) (global.set $global$0 (local.get $2) @@ -184,11 +175,15 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "printf", "__handle_stack_overflow" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/recursive.wat binaryen-99/test/lld/recursive.wat --- binaryen-108/test/lld/recursive.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/recursive.wat 2021-01-07 20:01:06.000000000 +0000 @@ -4,9 +4,9 @@ (type $none_=>_i32 (func (result i32))) (import "env" "iprintf" (func $iprintf (param i32 i32) (result i32))) (memory $0 2) - (data $.rodata (i32.const 568) "%d:%d\n\00Result: %d\n\00") + (data (i32.const 568) "%d:%d\n\00Result: %d\n\00") (table $0 1 1 funcref) - (global $__stack_pointer (mut i32) (i32.const 66128)) + (global $global$0 (mut i32) (i32.const 66128)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -14,10 +14,10 @@ ) (func $foo (param $0 i32) (param $1 i32) (result i32) (local $2 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $2 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 16) ) ) @@ -36,7 +36,7 @@ (local.get $2) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $2) (i32.const 16) @@ -49,10 +49,10 @@ ) (func $__original_main (result i32) (local $0 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 16) ) ) @@ -70,7 +70,7 @@ (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $0) (i32.const 16) diff -Nru binaryen-108/test/lld/recursive.wat.out binaryen-99/test/lld/recursive.wat.out --- binaryen-108/test/lld/recursive.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/recursive.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -3,10 +3,10 @@ (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (import "env" "iprintf" (func $iprintf (param i32 i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66128)) (memory $0 2) - (data $.rodata (i32.const 568) "%d:%d\n\00Result: %d\n\00") + (data (i32.const 568) "%d:%d\n\00Result: %d\n\00") (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 66128)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -15,10 +15,10 @@ ) (func $foo (param $0 i32) (param $1 i32) (result i32) (local $2 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $2 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 16) ) ) @@ -37,7 +37,7 @@ (local.get $2) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $2) (i32.const 16) @@ -50,10 +50,10 @@ ) (func $__original_main (result i32) (local $0 i32) - (global.set $__stack_pointer + (global.set $global$0 (local.tee $0 (i32.sub - (global.get $__stack_pointer) + (global.get $global$0) (i32.const 16) ) ) @@ -71,7 +71,7 @@ (local.get $0) ) ) - (global.set $__stack_pointer + (global.set $global$0 (i32.add (local.get $0) (i32.const 16) @@ -86,10 +86,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "iprintf" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/reserved_func_ptr.cpp binaryen-99/test/lld/reserved_func_ptr.cpp --- binaryen-108/test/lld/reserved_func_ptr.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/reserved_func_ptr.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ -int atoi(const char* nptr); +int atoi(const char *nptr); void address_taken_func(int a, int b, int c) {} void address_taken_func2(int a, int b, int c) {} -int main(int argc, char** argv) { +int main(int argc, char **argv) { int fp_v = atoi(argv[1]); int fp_vi = atoi(argv[2]); int fp_iii = atoi(argv[3]); @@ -20,9 +20,9 @@ void (*f_vi)(int) = reinterpret_cast(fp_vi); int (*f_iii)(int, int) = reinterpret_cast(fp_iii); float (*f_fffi)(float, float, int) = - reinterpret_cast(fp_fffi); + reinterpret_cast(fp_fffi); double (*f_ddi)(double, int) = - reinterpret_cast(fp_ddi); + reinterpret_cast(fp_ddi); f_v(); f_vi(3); diff -Nru binaryen-108/test/lld/reserved_func_ptr.wat binaryen-99/test/lld/reserved_func_ptr.wat --- binaryen-108/test/lld/reserved_func_ptr.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/reserved_func_ptr.wat 2021-01-07 20:01:06.000000000 +0000 @@ -10,7 +10,7 @@ (memory $0 2) (table $0 3 3 funcref) (elem (i32.const 1) $address_taken_func\28int\2c\20int\2c\20int\29 $address_taken_func2\28int\2c\20int\2c\20int\29) - (global $__stack_pointer (mut i32) (i32.const 66112)) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) diff -Nru binaryen-108/test/lld/reserved_func_ptr.wat.out binaryen-99/test/lld/reserved_func_ptr.wat.out --- binaryen-108/test/lld/reserved_func_ptr.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/reserved_func_ptr.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -2,16 +2,16 @@ (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_none (func)) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $f32_f32_i32_=>_f32 (func (param f32 f32 i32) (result f32))) (type $f64_i32_=>_f64 (func (param f64 i32) (result f64))) - (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (import "env" "_Z4atoiPKc" (func $atoi\28char\20const*\29 (param i32) (result i32))) - (global $__stack_pointer (mut i32) (i32.const 66112)) (memory $0 2) (table $0 3 3 funcref) (elem (i32.const 1) $address_taken_func\28int\2c\20int\2c\20int\29 $address_taken_func2\28int\2c\20int\2c\20int\29) + (global $global$0 (mut i32) (i32.const 66112)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) @@ -121,10 +121,14 @@ (; --BEGIN METADATA -- { + "tableSize": 3, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "_Z4atoiPKc" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/safe_stack_standalone-wasm.wat.out binaryen-99/test/lld/safe_stack_standalone-wasm.wat.out --- binaryen-108/test/lld/safe_stack_standalone-wasm.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/safe_stack_standalone-wasm.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,17 +1,17 @@ (module - (type $0 (func (param i32 i32) (result i32))) - (type $1 (func)) - (type $2 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_none (func)) (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "printf" (func $printf (param i32 i32) (result i32))) + (memory $0 2) + (data (i32.const 568) "%d:%d\n\00Result: %d\n\00") + (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 66128)) (global $global$1 i32 (i32.const 66128)) (global $global$2 i32 (i32.const 587)) (global $__stack_base (mut i32) (i32.const 0)) (global $__stack_limit (mut i32) (i32.const 0)) - (memory $0 2) - (data (i32.const 568) "%d:%d\n\00Result: %d\n\00") - (table $0 1 1 funcref) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "__heap_base" (global $global$1)) @@ -174,10 +174,14 @@ (; --BEGIN METADATA -- { + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], "declares": [ "printf" ], - "globalImports": [ + "externs": [ ], "exports": [ "__wasm_call_ctors", diff -Nru binaryen-108/test/lld/shared_add_to_table.wasm.out binaryen-99/test/lld/shared_add_to_table.wasm.out --- binaryen-108/test/lld/shared_add_to_table.wasm.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/shared_add_to_table.wasm.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 0)) @@ -16,7 +16,7 @@ (import "env" "_Z16waka_func_theirsi" (func $waka_func_theirs\28int\29 (param i32) (result i32))) (global $global$0 i32 (i32.const 0)) (global $global$1 i32 (i32.const 0)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (export "__post_instantiate" (func $__wasm_call_ctors)) (export "__wasm_apply_relocs" (func $__wasm_apply_relocs)) (export "_Z14waka_func_minei" (func $waka_func_mine\28int\29)) (export "__original_main" (func $__original_main)) @@ -71,20 +71,21 @@ (; --BEGIN METADATA -- { + "tableSize": 0, "declares": [ "_Z16waka_func_theirsi" ], - "globalImports": [ - "__stack_pointer", - "__memory_base", - "__table_base", - "_Z16waka_func_theirsi", - "_Z14waka_func_minei", - "waka_mine", - "waka_others" + "externs": [ + "___stack_pointer", + "___memory_base", + "___table_base", + "__Z16waka_func_theirsi", + "__Z14waka_func_minei", + "_waka_mine", + "_waka_others" ], "exports": [ - "__wasm_call_ctors", + "__post_instantiate", "__wasm_apply_relocs", "_Z14waka_func_minei", "__original_main", diff -Nru binaryen-108/test/lld/shared_longjmp.wat binaryen-99/test/lld/shared_longjmp.wat --- binaryen-108/test/lld/shared_longjmp.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/shared_longjmp.wat 2021-01-07 20:01:06.000000000 +0000 @@ -7,48 +7,48 @@ (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) - (import "env" "memory" (memory $mimport$0 1)) - (data $.bss (global.get $__memory_base) "\00\00\00\00\00\00\00\00") + (import "env" "memory" (memory $mimport$0 0)) + (data (global.get $gimport$0) "\00\00\00\00\00\00\00\00") (import "env" "__indirect_function_table" (table $timport$0 0 funcref)) - (import "env" "__memory_base" (global $__memory_base i32)) - (import "env" "__table_base" (global $__table_base i32)) - (import "GOT.mem" "__THREW__" (global $__THREW__ (mut i32))) - (import "GOT.func" "emscripten_longjmp" (global $emscripten_longjmp (mut i32))) - (import "GOT.mem" "__threwValue" (global $__threwValue (mut i32))) - (import "env" "malloc" (func $malloc (param i32) (result i32))) - (import "env" "saveSetjmp" (func $saveSetjmp (param i32 i32 i32 i32) (result i32))) - (import "env" "getTempRet0" (func $getTempRet0 (result i32))) - (import "env" "emscripten_longjmp" (func $emscripten_longjmp (param i32 i32))) - (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - (import "env" "testSetjmp" (func $testSetjmp (param i32 i32 i32) (result i32))) - (import "env" "setTempRet0" (func $setTempRet0 (param i32))) - (import "env" "free" (func $free (param i32))) + (import "env" "__memory_base" (global $gimport$0 i32)) + (import "env" "__table_base" (global $gimport$1 i32)) + (import "GOT.mem" "__THREW__" (global $gimport$2 (mut i32))) + (import "GOT.func" "emscripten_longjmp" (global $gimport$3 (mut i32))) + (import "GOT.mem" "__threwValue" (global $gimport$4 (mut i32))) + (import "env" "malloc" (func $fimport$0 (param i32) (result i32))) + (import "env" "saveSetjmp" (func $fimport$1 (param i32 i32 i32 i32) (result i32))) + (import "env" "getTempRet0" (func $fimport$2 (result i32))) + (import "env" "emscripten_longjmp" (func $fimport$3 (param i32 i32))) + (import "env" "invoke_vii" (func $fimport$4 (param i32 i32 i32))) + (import "env" "testSetjmp" (func $fimport$5 (param i32 i32 i32) (result i32))) + (import "env" "setTempRet0" (func $fimport$6 (param i32))) + (import "env" "free" (func $fimport$7 (param i32))) (global $global$0 i32 (i32.const 0)) (global $global$1 i32 (i32.const 4)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) - (export "_start" (func $_start)) + (export "__wasm_call_ctors" (func $0)) + (export "_start" (func $2)) (export "__THREW__" (global $global$0)) (export "__threwValue" (global $global$1)) - (func $__wasm_call_ctors - (call $__wasm_apply_data_relocs) + (func $0 + (call $1) ) - (func $__wasm_apply_data_relocs + (func $1 ) - (func $_start + (func $2 (local $0 i32) (local $1 i32) (local $2 i32) (local $3 i32) (i32.store (local.tee $0 - (call $malloc + (call $fimport$0 (i32.const 40) ) ) (i32.const 0) ) (local.set $1 - (call $saveSetjmp + (call $fimport$1 (local.get $0) (i32.const 1) (local.get $0) @@ -56,7 +56,7 @@ ) ) (local.set $2 - (call $getTempRet0) + (call $fimport$2) ) (local.set $0 (i32.const 0) @@ -69,12 +69,12 @@ ) (i32.store (local.tee $0 - (global.get $__THREW__) + (global.get $gimport$2) ) (i32.const 0) ) - (call $invoke_vii - (global.get $emscripten_longjmp) + (call $fimport$4 + (global.get $gimport$3) (local.get $0) (i32.const 1) ) @@ -88,7 +88,7 @@ (i32.const 0) ) (local.set $0 - (global.get $__threwValue) + (global.get $gimport$4) ) (block $label$4 (br_if $label$4 @@ -107,7 +107,7 @@ ) (br_if $label$1 (i32.eqz - (call $testSetjmp + (call $fimport$5 (i32.load (local.get $3) ) @@ -116,32 +116,32 @@ ) ) ) - (call $setTempRet0 + (call $fimport$6 (local.get $0) ) ) (local.set $0 - (call $getTempRet0) + (call $fimport$2) ) (br $label$3) ) ) - (call $free + (call $fimport$7 (local.get $1) ) (return) ) - (call $free - (local.get $1) - ) - (call $emscripten_longjmp + (call $fimport$3 (local.get $3) (local.get $0) ) (unreachable) ) - ;; custom section "dylink.0", size 6 + ;; dylink section + ;; memorysize: 8 + ;; memoryalignment: 2 + ;; tablesize: 0 + ;; tablealignment: 0 ;; custom section "producers", size 112 - ;; features section: mutable-globals ) diff -Nru binaryen-108/test/lld/shared_longjmp.wat.out binaryen-99/test/lld/shared_longjmp.wat.out --- binaryen-108/test/lld/shared_longjmp.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/shared_longjmp.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,56 +1,56 @@ (module (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (import "env" "memory" (memory $mimport$0 1)) - (data $.bss (global.get $__memory_base) "\00\00\00\00\00\00\00\00") + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (import "env" "memory" (memory $mimport$0 0)) + (data (global.get $gimport$0) "\00\00\00\00\00\00\00\00") (import "env" "__indirect_function_table" (table $timport$0 0 funcref)) - (import "env" "__memory_base" (global $__memory_base i32)) - (import "env" "__table_base" (global $__table_base i32)) - (import "GOT.mem" "__THREW__" (global $__THREW__ (mut i32))) - (import "GOT.func" "emscripten_longjmp" (global $emscripten_longjmp (mut i32))) - (import "GOT.mem" "__threwValue" (global $__threwValue (mut i32))) - (import "env" "malloc" (func $malloc (param i32) (result i32))) - (import "env" "saveSetjmp" (func $saveSetjmp (param i32 i32 i32 i32) (result i32))) - (import "env" "getTempRet0" (func $getTempRet0 (result i32))) - (import "env" "emscripten_longjmp" (func $emscripten_longjmp (param i32 i32))) - (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) - (import "env" "testSetjmp" (func $testSetjmp (param i32 i32 i32) (result i32))) - (import "env" "setTempRet0" (func $setTempRet0 (param i32))) - (import "env" "free" (func $free (param i32))) + (import "env" "__memory_base" (global $gimport$0 i32)) + (import "env" "__table_base" (global $gimport$1 i32)) + (import "GOT.mem" "__THREW__" (global $gimport$2 (mut i32))) + (import "GOT.func" "emscripten_longjmp" (global $gimport$3 (mut i32))) + (import "GOT.mem" "__threwValue" (global $gimport$4 (mut i32))) + (import "env" "malloc" (func $fimport$0 (param i32) (result i32))) + (import "env" "saveSetjmp" (func $fimport$1 (param i32 i32 i32 i32) (result i32))) + (import "env" "getTempRet0" (func $fimport$2 (result i32))) + (import "env" "emscripten_longjmp" (func $fimport$3 (param i32 i32))) + (import "env" "invoke_vii" (func $fimport$4 (param i32 i32 i32))) + (import "env" "testSetjmp" (func $fimport$5 (param i32 i32 i32) (result i32))) + (import "env" "setTempRet0" (func $fimport$6 (param i32))) + (import "env" "free" (func $fimport$7 (param i32))) (global $global$0 i32 (i32.const 0)) (global $global$1 i32 (i32.const 4)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) - (export "_start" (func $_start)) + (export "__post_instantiate" (func $0)) + (export "_start" (func $2)) (export "__THREW__" (global $global$0)) (export "__threwValue" (global $global$1)) (export "dynCall_vii" (func $dynCall_vii)) - (func $__wasm_call_ctors - (call $__wasm_apply_data_relocs) + (func $0 + (call $1) ) - (func $__wasm_apply_data_relocs + (func $1 (nop) ) - (func $_start + (func $2 (local $0 i32) (local $1 i32) (local $2 i32) (local $3 i32) (i32.store (local.tee $0 - (call $malloc + (call $fimport$0 (i32.const 40) ) ) (i32.const 0) ) (local.set $1 - (call $saveSetjmp + (call $fimport$1 (local.get $0) (i32.const 1) (local.get $0) @@ -58,7 +58,7 @@ ) ) (local.set $2 - (call $getTempRet0) + (call $fimport$2) ) (local.set $0 (i32.const 0) @@ -71,12 +71,12 @@ ) (i32.store (local.tee $0 - (global.get $__THREW__) + (global.get $gimport$2) ) (i32.const 0) ) - (call $invoke_vii - (global.get $emscripten_longjmp) + (call $fimport$4 + (global.get $gimport$3) (local.get $0) (i32.const 1) ) @@ -90,7 +90,7 @@ (i32.const 0) ) (local.set $0 - (global.get $__threwValue) + (global.get $gimport$4) ) (block $label$4 (br_if $label$4 @@ -109,7 +109,7 @@ ) (br_if $label$1 (i32.eqz - (call $testSetjmp + (call $fimport$5 (i32.load (local.get $3) ) @@ -118,25 +118,22 @@ ) ) ) - (call $setTempRet0 + (call $fimport$6 (local.get $0) ) ) (local.set $0 - (call $getTempRet0) + (call $fimport$2) ) (br $label$3) ) ) - (call $free + (call $fimport$7 (local.get $1) ) (return) ) - (call $free - (local.get $1) - ) - (call $emscripten_longjmp + (call $fimport$3 (local.get $3) (local.get $0) ) @@ -153,6 +150,7 @@ (; --BEGIN METADATA -- { + "tableSize": 0, "declares": [ "malloc", "saveSetjmp", @@ -162,15 +160,15 @@ "setTempRet0", "free" ], - "globalImports": [ - "__memory_base", - "__table_base", - "__THREW__", - "emscripten_longjmp", - "__threwValue" + "externs": [ + "___memory_base", + "___table_base", + "___THREW__", + "_emscripten_longjmp", + "___threwValue" ], "exports": [ - "__wasm_call_ctors", + "__post_instantiate", "_start", "dynCall_vii" ], diff -Nru binaryen-108/test/lld/shared.wat binaryen-99/test/lld/shared.wat --- binaryen-108/test/lld/shared.wat 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/shared.wat 2021-01-07 20:01:06.000000000 +0000 @@ -2,14 +2,14 @@ (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "memory" (memory $mimport$0 1)) - (data $.data (global.get $__memory_base) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00") + (import "env" "memory" (memory $mimport$0 0)) + (data (global.get $gimport$0) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00") (import "env" "__indirect_function_table" (table $timport$0 0 funcref)) - (import "env" "__memory_base" (global $__memory_base i32)) - (import "env" "__table_base" (global $__table_base i32)) - (import "GOT.mem" "external_var" (global $external_var (mut i32))) - (import "GOT.func" "puts" (global $puts (mut i32))) - (import "GOT.func" "_Z13print_messagev" (global $print_message\28\29 (mut i32))) + (import "env" "__memory_base" (global $gimport$0 i32)) + (import "env" "__table_base" (global $gimport$1 i32)) + (import "GOT.mem" "external_var" (global $gimport$2 (mut i32))) + (import "GOT.func" "puts" (global $gimport$3 (mut i32))) + (import "GOT.func" "_Z13print_messagev" (global $gimport$4 (mut i32))) (import "env" "puts" (func $puts (param i32) (result i32))) (global $global$0 i32 (i32.const 16)) (global $global$1 i32 (i32.const 20)) @@ -18,39 +18,42 @@ (export "ptr_puts" (global $global$0)) (export "ptr_local_func" (global $global$1)) (func $__wasm_call_ctors - (call $__wasm_apply_data_relocs) + (call $__wasm_apply_relocs) ) - (func $__wasm_apply_data_relocs + (func $__wasm_apply_relocs (i32.store (i32.add - (global.get $__memory_base) + (global.get $gimport$0) (i32.const 16) ) - (global.get $puts) + (global.get $gimport$3) ) (i32.store (i32.add - (global.get $__memory_base) + (global.get $gimport$0) (i32.const 20) ) - (global.get $print_message\28\29) + (global.get $gimport$4) ) ) (func $print_message\28\29 (result i32) (drop (call $puts (i32.add - (global.get $__memory_base) + (global.get $gimport$0) (i32.const 0) ) ) ) (i32.load - (global.get $external_var) + (global.get $gimport$2) ) ) - ;; custom section "dylink.0", size 6 + ;; dylink section + ;; memorysize: 24 + ;; memoryalignment: 2 + ;; tablesize: 0 + ;; tablealignment: 0 ;; custom section "producers", size 112 - ;; features section: mutable-globals ) diff -Nru binaryen-108/test/lld/shared.wat.out binaryen-99/test/lld/shared.wat.out --- binaryen-108/test/lld/shared.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/shared.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,70 +1,71 @@ (module (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) - (import "env" "memory" (memory $mimport$0 1)) - (data $.data (global.get $__memory_base) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00") + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "memory" (memory $mimport$0 0)) + (data (global.get $gimport$0) "Hello, world\00\00\00\00\00\00\00\00\00\00\00\00") (import "env" "__indirect_function_table" (table $timport$0 0 funcref)) - (import "env" "__memory_base" (global $__memory_base i32)) - (import "env" "__table_base" (global $__table_base i32)) - (import "GOT.mem" "external_var" (global $external_var (mut i32))) - (import "GOT.func" "puts" (global $puts (mut i32))) - (import "GOT.func" "_Z13print_messagev" (global $print_message\28\29 (mut i32))) + (import "env" "__memory_base" (global $gimport$0 i32)) + (import "env" "__table_base" (global $gimport$1 i32)) + (import "GOT.mem" "external_var" (global $gimport$2 (mut i32))) + (import "GOT.func" "puts" (global $gimport$3 (mut i32))) + (import "GOT.func" "_Z13print_messagev" (global $gimport$4 (mut i32))) (import "env" "puts" (func $puts (param i32) (result i32))) (global $global$0 i32 (i32.const 16)) (global $global$1 i32 (i32.const 20)) - (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (export "__post_instantiate" (func $__wasm_call_ctors)) (export "_Z13print_messagev" (func $print_message\28\29)) (export "ptr_puts" (global $global$0)) (export "ptr_local_func" (global $global$1)) (func $__wasm_call_ctors - (call $__wasm_apply_data_relocs) + (call $__wasm_apply_relocs) ) - (func $__wasm_apply_data_relocs + (func $__wasm_apply_relocs (i32.store (i32.add - (global.get $__memory_base) + (global.get $gimport$0) (i32.const 16) ) - (global.get $puts) + (global.get $gimport$3) ) (i32.store (i32.add - (global.get $__memory_base) + (global.get $gimport$0) (i32.const 20) ) - (global.get $print_message\28\29) + (global.get $gimport$4) ) ) (func $print_message\28\29 (result i32) (drop (call $puts (i32.add - (global.get $__memory_base) + (global.get $gimport$0) (i32.const 0) ) ) ) (i32.load - (global.get $external_var) + (global.get $gimport$2) ) ) ) (; --BEGIN METADATA -- { + "tableSize": 0, "declares": [ "puts" ], - "globalImports": [ - "__memory_base", - "__table_base", - "external_var", - "puts", - "_Z13print_messagev" + "externs": [ + "___memory_base", + "___table_base", + "_external_var", + "_puts", + "__Z13print_messagev" ], "exports": [ - "__wasm_call_ctors", + "__post_instantiate", "_Z13print_messagev" ], "namedGlobals": { diff -Nru binaryen-108/test/lld/standalone-wasm2.wat.out binaryen-99/test/lld/standalone-wasm2.wat.out --- binaryen-108/test/lld/standalone-wasm2.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/standalone-wasm2.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (memory $0 2) (global $global$0 (mut i32) (i32.const 66112)) (global $global$1 i32 (i32.const 66112)) (global $global$2 i32 (i32.const 576)) - (memory $0 2) (export "memory" (memory $0)) (export "main" (func $main)) (export "__heap_base" (global $global$1)) @@ -21,9 +21,10 @@ (; --BEGIN METADATA -- { + "tableSize": 0, "declares": [ ], - "globalImports": [ + "externs": [ ], "exports": [ "main" diff -Nru binaryen-108/test/lld/standalone-wasm3.wat.out binaryen-99/test/lld/standalone-wasm3.wat.out --- binaryen-108/test/lld/standalone-wasm3.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/standalone-wasm3.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (memory $0 2) (global $global$0 (mut i32) (i32.const 66112)) (global $global$1 i32 (i32.const 66112)) (global $global$2 i32 (i32.const 576)) - (memory $0 2) (export "memory" (memory $0)) (export "__heap_base" (global $global$1)) (export "__data_end" (global $global$2)) @@ -14,9 +14,10 @@ (; --BEGIN METADATA -- { + "tableSize": 0, "declares": [ ], - "globalImports": [ + "externs": [ ], "exports": [ ], diff -Nru binaryen-108/test/lld/standalone-wasm.wat.out binaryen-99/test/lld/standalone-wasm.wat.out --- binaryen-108/test/lld/standalone-wasm.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/standalone-wasm.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (global $global$0 (mut i32) (i32.const 66112)) - (global $global$1 i32 (i32.const 66112)) - (global $global$2 i32 (i32.const 576)) (memory $0 2) (table $0 1 1 funcref) (elem (i32.const 0) $foo) + (global $global$0 (mut i32) (i32.const 66112)) + (global $global$1 i32 (i32.const 66112)) + (global $global$2 i32 (i32.const 576)) (export "memory" (memory $0)) (export "main" (func $main)) (export "__heap_base" (global $global$1)) @@ -24,9 +24,10 @@ (; --BEGIN METADATA -- { + "tableSize": 1, "declares": [ ], - "globalImports": [ + "externs": [ ], "exports": [ "main" diff -Nru binaryen-108/test/lld/standalone-wasm-with-start.wat.out binaryen-99/test/lld/standalone-wasm-with-start.wat.out --- binaryen-108/test/lld/standalone-wasm-with-start.wat.out 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/lld/standalone-wasm-with-start.wat.out 2021-01-07 20:01:06.000000000 +0000 @@ -1,11 +1,11 @@ (module (type $none_=>_i32 (func (result i32))) - (global $global$0 (mut i32) (i32.const 66112)) - (global $global$1 i32 (i32.const 66112)) - (global $global$2 i32 (i32.const 576)) (memory $0 2) (table $0 1 1 funcref) (elem (i32.const 0) $foo) + (global $global$0 (mut i32) (i32.const 66112)) + (global $global$1 i32 (i32.const 66112)) + (global $global$2 i32 (i32.const 576)) (export "memory" (memory $0)) (export "_start" (func $_start)) (export "__heap_base" (global $global$1)) @@ -20,9 +20,10 @@ (; --BEGIN METADATA -- { + "tableSize": 1, "declares": [ ], - "globalImports": [ + "externs": [ ], "exports": [ "_start" diff -Nru binaryen-108/test/mem.cpp binaryen-99/test/mem.cpp --- binaryen-108/test/mem.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/mem.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ -#include #include +#include extern "C" { @@ -14,35 +14,21 @@ double EMSCRIPTEN_KEEPALIVE loadf32(size_t addr) { return ((float*)addr)[0]; } double EMSCRIPTEN_KEEPALIVE loadf64(size_t addr) { return ((double*)addr)[0]; } -void EMSCRIPTEN_KEEPALIVE storei8(size_t addr, int8_t v) { - ((int8_t*)addr)[0] = v; -} -void EMSCRIPTEN_KEEPALIVE storei16(size_t addr, int16_t v) { - ((int16_t*)addr)[0] = v; -} -void EMSCRIPTEN_KEEPALIVE storei32(size_t addr, int32_t v) { - ((int32_t*)addr)[0] = v; -} +void EMSCRIPTEN_KEEPALIVE storei8(size_t addr, int8_t v) { ((int8_t*)addr)[0] = v; } +void EMSCRIPTEN_KEEPALIVE storei16(size_t addr, int16_t v) { ((int16_t*)addr)[0] = v; } +void EMSCRIPTEN_KEEPALIVE storei32(size_t addr, int32_t v) { ((int32_t*)addr)[0] = v; } + +void EMSCRIPTEN_KEEPALIVE storeu8(size_t addr, uint8_t v) { ((uint8_t*)addr)[0] = v; } +void EMSCRIPTEN_KEEPALIVE storeu16(size_t addr, uint16_t v) { ((uint16_t*)addr)[0] = v; } +void EMSCRIPTEN_KEEPALIVE storeu32(size_t addr, uint32_t v) { ((uint32_t*)addr)[0] = v; } -void EMSCRIPTEN_KEEPALIVE storeu8(size_t addr, uint8_t v) { - ((uint8_t*)addr)[0] = v; -} -void EMSCRIPTEN_KEEPALIVE storeu16(size_t addr, uint16_t v) { - ((uint16_t*)addr)[0] = v; -} -void EMSCRIPTEN_KEEPALIVE storeu32(size_t addr, uint32_t v) { - ((uint32_t*)addr)[0] = v; -} - -void EMSCRIPTEN_KEEPALIVE storef32(size_t addr, float v) { - ((float*)addr)[0] = v; -} -void EMSCRIPTEN_KEEPALIVE storef64(size_t addr, double v) { - ((double*)addr)[0] = v; -} +void EMSCRIPTEN_KEEPALIVE storef32(size_t addr, float v) { ((float*)addr)[0] = v; } +void EMSCRIPTEN_KEEPALIVE storef64(size_t addr, double v) { ((double*)addr)[0] = v; } int* EMSCRIPTEN_KEEPALIVE get_stack() { int t; return &t; } + } + diff -Nru binaryen-108/test/memory-import64.wast.fromBinary binaryen-99/test/memory-import64.wast.fromBinary --- binaryen-108/test/memory-import64.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/memory-import64.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "memory" (memory $0 i64 1 1)) (func $foo (result i32) (i32.load offset=13 diff -Nru binaryen-108/test/memory-import64.wast.from-wast binaryen-99/test/memory-import64.wast.from-wast --- binaryen-108/test/memory-import64.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/memory-import64.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "memory" (memory $0 i64 1 1)) (func $foo (result i32) (i32.load offset=13 diff -Nru binaryen-108/test/memory-import.wast.fromBinary binaryen-99/test/memory-import.wast.fromBinary --- binaryen-108/test/memory-import.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/memory-import.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "memory" (memory $0 1 1)) (func $foo (result i32) (i32.load offset=13 diff -Nru binaryen-108/test/memory-import.wast.from-wast binaryen-99/test/memory-import.wast.from-wast --- binaryen-108/test/memory-import.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/memory-import.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "memory" (memory $0 1 1)) (func $foo (result i32) (i32.load offset=13 diff -Nru binaryen-108/test/metadce/corners.wast.dced binaryen-99/test/metadce/corners.wast.dced --- binaryen-108/test/metadce/corners.wast.dced 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/corners.wast.dced 2021-01-07 20:01:06.000000000 +0000 @@ -1,11 +1,11 @@ (module (type $none_=>_none (func)) (import "env" "table" (table $timport$0 10 10 funcref)) + (elem (i32.const 0) $imported_table_func) (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) (import "env" "imported_twice" (func $imported_twice_a)) (import "env" "an-imported-table-func" (func $imported_table_func)) (global $STACKTOP (mut i32) (global.get $STACKTOP$asm2wasm$import)) - (elem (i32.const 0) $imported_table_func) (export "stackAlloc" (func $stackAlloc)) (func $stackAlloc (drop diff -Nru binaryen-108/test/metadce/outside.wast.dced binaryen-99/test/metadce/outside.wast.dced --- binaryen-108/test/metadce/outside.wast.dced 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/outside.wast.dced 2021-01-07 20:01:06.000000000 +0000 @@ -4,11 +4,11 @@ (data (i32.const 1024) "abcd") (data (global.get $from_segment) "abcd") (import "env" "table" (table $timport$0 10 10 funcref)) + (elem (global.get $from_segment_2) $table_func) (import "env" "js_func" (func $a_js_func)) (global $__THREW__ (mut i32) (i32.const 0)) (global $from_segment (mut i32) (i32.const 0)) (global $from_segment_2 (mut i32) (i32.const 0)) - (elem (global.get $from_segment_2) $table_func) (export "wasm_func" (func $a_wasm_func)) (func $table_func (nop) diff -Nru binaryen-108/test/metadce/rooted-export.wast binaryen-99/test/metadce/rooted-export.wast --- binaryen-108/test/metadce/rooted-export.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/rooted-export.wast 2021-01-07 20:01:06.000000000 +0000 @@ -9,10 +9,10 @@ (unreachable) ) - (export "wasm_tag_a" (tag $a_wasm_tag)) - (export "wasm_tag_b" (tag $b_wasm_tag)) + (export "wasm_event_a" (event $a_wasm_event)) + (export "wasm_event_b" (event $b_wasm_event)) - (tag $a_wasm_tag (param i32)) - (tag $b_wasm_tag (param i32)) + (event $a_wasm_event (attr 0) (param i32)) + (event $b_wasm_event (attr 0) (param i32)) ) diff -Nru binaryen-108/test/metadce/rooted-export.wast.dced binaryen-99/test/metadce/rooted-export.wast.dced --- binaryen-108/test/metadce/rooted-export.wast.dced 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/rooted-export.wast.dced 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) - (tag $b_wasm_tag (param i32)) + (type $i32_=>_none (func (param i32))) + (event $b_wasm_event (attr 0) (param i32)) (export "wasm_func_b" (func $b_wasm_func)) - (export "wasm_tag_b" (tag $b_wasm_tag)) + (export "wasm_event_b" (event $b_wasm_event)) (func $b_wasm_func (unreachable) ) diff -Nru binaryen-108/test/metadce/rooted-export.wast.dced.stdout binaryen-99/test/metadce/rooted-export.wast.dced.stdout --- binaryen-108/test/metadce/rooted-export.wast.dced.stdout 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/rooted-export.wast.dced.stdout 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,4 @@ +unused: event$a_wasm_event$2 +unused: export$wasm_event_a$5 unused: export$wasm_func_a$4 -unused: export$wasm_tag_a$5 unused: func$a_wasm_func$0 -unused: tag$a_wasm_tag$2 diff -Nru binaryen-108/test/metadce/rooted-export.wast.graph.txt binaryen-99/test/metadce/rooted-export.wast.graph.txt --- binaryen-108/test/metadce/rooted-export.wast.graph.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/rooted-export.wast.graph.txt 2021-01-07 20:01:06.000000000 +0000 @@ -5,9 +5,9 @@ "export": "wasm_func_b" }, { - "name": "rooted-export-tag", + "name": "rooted-export-event", "root": true, - "export": "wasm_tag_b" + "export": "wasm_event_b" } ] diff -Nru binaryen-108/test/metadce/spanning_cycle.wast binaryen-99/test/metadce/spanning_cycle.wast --- binaryen-108/test/metadce/spanning_cycle.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/spanning_cycle.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module (memory 1 1) - (data "Hello, datacount section!") + (data passive "Hello, datacount section!") (import "env" "js_func" (func $a_js_func)) diff -Nru binaryen-108/test/metadce/spanning_cycle.wast.dced binaryen-99/test/metadce/spanning_cycle.wast.dced --- binaryen-108/test/metadce/spanning_cycle.wast.dced 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/spanning_cycle.wast.dced 2021-01-07 20:01:06.000000000 +0000 @@ -2,7 +2,7 @@ (type $none_=>_none (func)) (import "env" "js_func" (func $a_js_func)) (memory $0 1 1) - (data "Hello, datacount section!") + (data passive "Hello, datacount section!") (export "wasm_func_a" (func $a_wasm_func)) (func $a_wasm_func (memory.init 0 diff -Nru binaryen-108/test/metadce/tag.wast binaryen-99/test/metadce/tag.wast --- binaryen-108/test/metadce/tag.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/tag.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -(module - (import "env" "imported_tag" (tag $t0)) - (tag $t1) - (export "test" (func $test)) - - (func $test - (try - (do - (throw $t0) - ) - (catch $t1) - ) - ) -) diff -Nru binaryen-108/test/metadce/tag.wast.dced binaryen-99/test/metadce/tag.wast.dced --- binaryen-108/test/metadce/tag.wast.dced 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/tag.wast.dced 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -(module - (type $none_=>_none (func)) - (import "env" "imported_tag" (tag $t0 (param))) - (tag $t1 (param)) - (export "test" (func $test)) - (func $test - (try $try - (do - (throw $t0) - ) - (catch $t1 - (nop) - ) - ) - ) -) diff -Nru binaryen-108/test/metadce/tag.wast.graph.txt binaryen-99/test/metadce/tag.wast.graph.txt --- binaryen-108/test/metadce/tag.wast.graph.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/metadce/tag.wast.graph.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -[ - { - "name": "tag_import", - "import": ["env", "imported_tag"] - }, - { - "name": "func_export", - "root": true, - "export": "test" - } -] diff -Nru binaryen-108/test/min.wast.fromBinary binaryen-99/test/min.wast.fromBinary --- binaryen-108/test/min.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/min.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module - (type $0 (func (param f32) (result f32))) - (type $1 (func (param i32 i32) (result f32))) - (type $2 (func (param i32) (result i32))) - (type $3 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $f32_=>_f32 (func (param f32) (result f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (memory $0 256 256) (export "floats" (func $floats)) (func $floats (param $f f32) (result f32) diff -Nru binaryen-108/test/min.wast.fromBinary.noDebugInfo binaryen-99/test/min.wast.fromBinary.noDebugInfo --- binaryen-108/test/min.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/min.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module - (type $f32_=>_f32 (func (param f32) (result f32))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $f32_=>_f32 (func (param f32) (result f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (memory $0 256 256) (export "floats" (func $0)) (func $0 (param $0 f32) (result f32) diff -Nru binaryen-108/test/min.wast.from-wast binaryen-99/test/min.wast.from-wast --- binaryen-108/test/min.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/min.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module - (type $0 (func (param f32) (result f32))) - (type $1 (func (param i32 i32) (result f32))) - (type $2 (func (param i32) (result i32))) - (type $3 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $f32_=>_f32 (func (param f32) (result f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (memory $0 256 256) (export "floats" (func $floats)) (func $floats (param $f f32) (result f32) diff -Nru binaryen-108/test/multi-table.minified.txt binaryen-99/test/multi-table.minified.txt --- binaryen-108/test/multi-table.minified.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multi-table.minified.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -(module(type $none_=>_none (func))(import "a" "b" (table $t1 1 10 funcref))(elem (table $t1) (i32.const 0) func $f)(table $t2 3 3 funcref)(elem (table $t2) (i32.const 0) func $f)(elem (table $t2) (i32.const 1) func $f $g)(func $f(nop))(func $g(nop))) \ No newline at end of file diff -Nru binaryen-108/test/multi-table.wast binaryen-99/test/multi-table.wast --- binaryen-108/test/multi-table.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multi-table.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -(module - (type $none_=>_none (func)) - (type $A (struct)) - (global $g1 (ref null $none_=>_none) (ref.func $f)) - (global $g2 i32 (i32.const 0)) - - (import "a" "b" (table $t1 1 10 funcref)) - (table $t2 3 3 funcref) - (table $t3 4 4 funcref) - (table $textern 0 externref) - - ;; A table with a typed function references specialized type. - (table $tspecial 5 5 (ref null $none_=>_none)) - - ;; add to $t1 - (elem (i32.const 0) $f) - - ;; add to $t2 - (elem (table $t2) (i32.const 0) func $f) - (elem $activeNonZeroOffset (table $t2) (offset (i32.const 1)) func $f $g) - - (elem $e3-1 (table $t3) (global.get $g2) funcref (ref.func $f) (ref.null func)) - (elem $e3-2 (table $t3) (offset (i32.const 2)) (ref null $none_=>_none) (item ref.func $f) (item (ref.func $g))) - - (elem $passive-1 func $f $g) - (elem $passive-2 funcref (item ref.func $f) (item (ref.func $g)) (ref.null func)) - (elem $passive-3 (ref null $none_=>_none) (item ref.func $f) (item (ref.func $g)) (ref.null $none_=>_none) (global.get $g1)) - (elem $empty func) - (elem $declarative declare func $h) - - ;; This elem will be emitted as usesExpressions because of the type of the - ;; table. - (elem $especial (table $tspecial) (i32.const 0) (ref null $none_=>_none) $f $h) - - (func $f (drop (ref.func $h))) - (func $g) - (func $h) -) diff -Nru binaryen-108/test/multi-table.wast.fromBinary binaryen-99/test/multi-table.wast.fromBinary --- binaryen-108/test/multi-table.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multi-table.wast.fromBinary 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -(module - (type $none_=>_none (func)) - (import "a" "b" (table $t1 1 10 funcref)) - (global $g1 (ref null $none_=>_none) (ref.func $f)) - (global $g2 i32 (i32.const 0)) - (table $t2 3 3 funcref) - (table $t3 4 4 funcref) - (table $textern 0 anyref) - (table $tspecial 5 5 (ref null $none_=>_none)) - (elem $0 (table $t1) (i32.const 0) func $f) - (elem $1 (table $t2) (i32.const 0) func $f) - (elem $activeNonZeroOffset (table $t2) (i32.const 1) func $f $g) - (elem $e3-1 (table $t3) (global.get $g2) funcref (ref.func $f) (ref.null func)) - (elem $e3-2 (table $t3) (i32.const 2) func $f $g) - (elem $passive-1 func $f $g) - (elem $passive-2 funcref (ref.func $f) (ref.func $g) (ref.null func)) - (elem $passive-3 (ref null $none_=>_none) (ref.func $f) (ref.func $g) (ref.null $none_=>_none) (global.get $g1)) - (elem $empty func) - (elem $especial (table $tspecial) (i32.const 0) (ref null $none_=>_none) (ref.func $f) (ref.func $h)) - (func $f - (drop - (ref.func $h) - ) - ) - (func $g - (nop) - ) - (func $h - (nop) - ) -) - diff -Nru binaryen-108/test/multi-table.wast.fromBinary.noDebugInfo binaryen-99/test/multi-table.wast.fromBinary.noDebugInfo --- binaryen-108/test/multi-table.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multi-table.wast.fromBinary.noDebugInfo 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -(module - (type $none_=>_none (func)) - (import "a" "b" (table $timport$0 1 10 funcref)) - (global $global$0 (ref null $none_=>_none) (ref.func $0)) - (global $global$1 i32 (i32.const 0)) - (table $0 3 3 funcref) - (table $1 4 4 funcref) - (table $2 0 anyref) - (table $3 5 5 (ref null $none_=>_none)) - (elem $0 (table $timport$0) (i32.const 0) func $0) - (elem $1 (table $0) (i32.const 0) func $0) - (elem $2 (table $0) (i32.const 1) func $0 $1) - (elem $3 (table $1) (global.get $global$1) funcref (ref.func $0) (ref.null func)) - (elem $4 (table $1) (i32.const 2) func $0 $1) - (elem $5 func $0 $1) - (elem $6 funcref (ref.func $0) (ref.func $1) (ref.null func)) - (elem $7 (ref null $none_=>_none) (ref.func $0) (ref.func $1) (ref.null $none_=>_none) (global.get $global$0)) - (elem $8 func) - (elem $9 (table $3) (i32.const 0) (ref null $none_=>_none) (ref.func $0) (ref.func $2)) - (func $0 - (drop - (ref.func $2) - ) - ) - (func $1 - (nop) - ) - (func $2 - (nop) - ) -) - diff -Nru binaryen-108/test/multi-table.wast.from-wast binaryen-99/test/multi-table.wast.from-wast --- binaryen-108/test/multi-table.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multi-table.wast.from-wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -(module - (type $none_=>_none (func)) - (import "a" "b" (table $t1 1 10 funcref)) - (global $g1 (ref null $none_=>_none) (ref.func $f)) - (global $g2 i32 (i32.const 0)) - (table $t2 3 3 funcref) - (table $t3 4 4 funcref) - (table $textern 0 anyref) - (table $tspecial 5 5 (ref null $none_=>_none)) - (elem $0 (table $t1) (i32.const 0) func $f) - (elem $1 (table $t2) (i32.const 0) func $f) - (elem $activeNonZeroOffset (table $t2) (i32.const 1) func $f $g) - (elem $e3-1 (table $t3) (global.get $g2) funcref (ref.func $f) (ref.null func)) - (elem $e3-2 (table $t3) (i32.const 2) func $f $g) - (elem $passive-1 func $f $g) - (elem $passive-2 funcref (ref.func $f) (ref.func $g) (ref.null func)) - (elem $passive-3 (ref null $none_=>_none) (ref.func $f) (ref.func $g) (ref.null $none_=>_none) (global.get $g1)) - (elem $empty func) - (elem $especial (table $tspecial) (i32.const 0) (ref null $none_=>_none) (ref.func $f) (ref.func $h)) - (func $f - (drop - (ref.func $h) - ) - ) - (func $g - (nop) - ) - (func $h - (nop) - ) -) diff -Nru binaryen-108/test/multivalue.wast.fromBinary binaryen-99/test/multivalue.wast.fromBinary --- binaryen-108/test/multivalue.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multivalue.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module (type $none_=>_i32_i64 (func (result i32 i64))) (type $none_=>_none (func)) - (type $none_=>_i32_i64_anyref (func (result i32 i64 anyref))) + (type $none_=>_i32_i64_externref (func (result i32 i64 externref))) (type $none_=>_i64 (func (result i64))) (type $none_=>_f32_i64_i32 (func (result f32 i64 i32))) - (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_f32 (func (result f32))) + (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) (import "env" "pair" (func $pair (result i32 i64))) (global $g1 (mut i32) (i32.const 0)) (global $g2 (mut i64) (i64.const 0)) @@ -389,20 +389,20 @@ ) ) ) - (func $mv-if (result i32 i64 anyref) - (local $0 (i32 i64 anyref)) + (func $mv-if (result i32 i64 externref) + (local $0 (i32 i64 externref)) (local.set $0 - (if (result i32 i64 anyref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null any) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null any) + (ref.null extern) ) ) ) diff -Nru binaryen-108/test/multivalue.wast.fromBinary.noDebugInfo binaryen-99/test/multivalue.wast.fromBinary.noDebugInfo --- binaryen-108/test/multivalue.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multivalue.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module (type $none_=>_i32_i64 (func (result i32 i64))) (type $none_=>_none (func)) - (type $none_=>_i32_i64_anyref (func (result i32 i64 anyref))) + (type $none_=>_i32_i64_externref (func (result i32 i64 externref))) (type $none_=>_i64 (func (result i64))) (type $none_=>_f32_i64_i32 (func (result f32 i64 i32))) - (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_f32 (func (result f32))) + (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) (import "env" "pair" (func $fimport$0 (result i32 i64))) (global $global$0 (mut i32) (i32.const 0)) (global $global$1 (mut i64) (i64.const 0)) @@ -389,20 +389,20 @@ ) ) ) - (func $14 (result i32 i64 anyref) - (local $0 (i32 i64 anyref)) + (func $14 (result i32 i64 externref) + (local $0 (i32 i64 externref)) (local.set $0 - (if (result i32 i64 anyref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null any) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null any) + (ref.null extern) ) ) ) diff -Nru binaryen-108/test/multivalue.wast.from-wast binaryen-99/test/multivalue.wast.from-wast --- binaryen-108/test/multivalue.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/multivalue.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,11 +2,11 @@ (type $none_=>_i32_i64 (func (result i32 i64))) (type $none_=>_none (func)) (type $none_=>_i64 (func (result i64))) + (type $none_=>_i32_i64_externref (func (result i32 i64 externref))) (type $none_=>_f32_i64_i32 (func (result f32 i64 i32))) - (type $none_=>_i32_i64_anyref (func (result i32 i64 anyref))) - (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_f32 (func (result f32))) + (type $none_=>_i32_i64_f32 (func (result i32 i64 f32))) (import "env" "pair" (func $pair (result i32 i64))) (global $g1 (mut (i32 i64)) (tuple.make (i32.const 0) @@ -135,18 +135,18 @@ ) ) ) - (func $mv-if (result i32 i64 anyref) - (if (result i32 i64 anyref) + (func $mv-if (result i32 i64 externref) + (if (result i32 i64 externref) (i32.const 1) (tuple.make (i32.const 42) (i64.const 42) - (ref.null any) + (ref.null extern) ) (tuple.make (i32.const 42) (i64.const 42) - (ref.null any) + (ref.null extern) ) ) ) diff -Nru binaryen-108/test/mutable-global.wast.fromBinary binaryen-99/test/mutable-global.wast.fromBinary --- binaryen-108/test/mutable-global.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/mutable-global.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (import "env" "global-mut" (global $global-mut (mut i32))) (func $foo (global.set $global-mut diff -Nru binaryen-108/test/mutable-global.wast.from-wast binaryen-99/test/mutable-global.wast.from-wast --- binaryen-108/test/mutable-global.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/mutable-global.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (import "env" "global-mut" (global $global-mut (mut i32))) (func $foo (global.set $global-mut diff -Nru binaryen-108/test/newsyntax.wast.fromBinary binaryen-99/test/newsyntax.wast.fromBinary --- binaryen-108/test/newsyntax.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/newsyntax.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -5,13 +5,13 @@ (export "call_indirect" (func $0)) (func $0 (drop - (call_indirect $timport$0 (type $i32_f64_=>_i32) + (call_indirect (type $i32_f64_=>_i32) (i32.const 10) (f64.const 20) (i32.const 30) ) ) - (call_indirect $timport$0 (type $none_=>_none) + (call_indirect (type $none_=>_none) (i32.const 1) ) ) diff -Nru binaryen-108/test/newsyntax.wast.fromBinary.noDebugInfo binaryen-99/test/newsyntax.wast.fromBinary.noDebugInfo --- binaryen-108/test/newsyntax.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/newsyntax.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -5,13 +5,13 @@ (export "call_indirect" (func $0)) (func $0 (drop - (call_indirect $timport$0 (type $i32_f64_=>_i32) + (call_indirect (type $i32_f64_=>_i32) (i32.const 10) (f64.const 20) (i32.const 30) ) ) - (call_indirect $timport$0 (type $none_=>_none) + (call_indirect (type $none_=>_none) (i32.const 1) ) ) diff -Nru binaryen-108/test/newsyntax.wast.from-wast binaryen-99/test/newsyntax.wast.from-wast --- binaryen-108/test/newsyntax.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/newsyntax.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -5,13 +5,13 @@ (export "call_indirect" (func $0)) (func $0 (drop - (call_indirect $timport$0 (type $i32_f64_=>_i32) + (call_indirect (type $i32_f64_=>_i32) (i32.const 10) (f64.const 20) (i32.const 30) ) ) - (call_indirect $timport$0 (type $none_=>_none) + (call_indirect (type $none_=>_none) (i32.const 1) ) ) diff -Nru binaryen-108/test/passes/alignment-lowering64.passes binaryen-99/test/passes/alignment-lowering64.passes --- binaryen-108/test/passes/alignment-lowering64.passes 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/alignment-lowering64.passes 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +alignment-lowering_enable-memory64 diff -Nru binaryen-108/test/passes/alignment-lowering64.txt binaryen-99/test/passes/alignment-lowering64.txt --- binaryen-108/test/passes/alignment-lowering64.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/alignment-lowering64.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1948 @@ +(module + (type $none_=>_none (func)) + (memory $0 i64 1 1) + (func $func_4 + (local $0 i64) + (local $1 i64) + (local $2 i64) + (local $3 i64) + (local $4 i64) + (local $5 i32) + (local $6 i64) + (local $7 i32) + (local $8 i64) + (local $9 i32) + (local $10 i64) + (local $11 i32) + (drop + (i32.load + (i64.const 4) + ) + ) + (drop + (block (result i32) + (local.set $0 + (i64.const 4) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $0) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $0) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (local.set $1 + (i64.const 4) + ) + (i32.or + (i32.load16_u + (local.get $1) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i32.load + (i64.const 4) + ) + ) + (drop + (i32.load offset=100 + (i64.const 4) + ) + ) + (drop + (block (result i32) + (local.set $2 + (i64.const 4) + ) + (i32.or + (i32.or + (i32.load8_u offset=100 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=101 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=102 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=103 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (local.set $3 + (i64.const 4) + ) + (i32.or + (i32.load16_u offset=100 + (local.get $3) + ) + (i32.shl + (i32.load16_u offset=102 + (local.get $3) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i32.load offset=100 + (i64.const 4) + ) + ) + (drop + (unreachable) + ) + (i32.store + (i64.const 4) + (i32.const 8) + ) + (block + (local.set $4 + (i64.const 4) + ) + (local.set $5 + (i32.const 8) + ) + (i32.store8 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=1 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + (block + (local.set $6 + (i64.const 4) + ) + (local.set $7 + (i32.const 8) + ) + (i32.store16 + (local.get $6) + (local.get $7) + ) + (i32.store16 offset=2 + (local.get $6) + (i32.shr_u + (local.get $7) + (i32.const 16) + ) + ) + ) + (i32.store + (i64.const 4) + (i32.const 8) + ) + (i32.store offset=100 + (i64.const 4) + (i32.const 8) + ) + (block + (local.set $8 + (i64.const 4) + ) + (local.set $9 + (i32.const 8) + ) + (i32.store8 offset=100 + (local.get $8) + (local.get $9) + ) + (i32.store8 offset=101 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 8) + ) + ) + (i32.store8 offset=102 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + (i32.store8 offset=103 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 24) + ) + ) + ) + (block + (local.set $10 + (i64.const 4) + ) + (local.set $11 + (i32.const 8) + ) + (i32.store16 offset=100 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=102 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + (i32.store offset=100 + (i64.const 4) + (i32.const 8) + ) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) + ) + (block + (drop + (i64.const 4) + ) + (drop + (unreachable) + ) + ) + ) + (func $func_2 + (local $0 i64) + (local $1 i64) + (local $2 i64) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (drop + (i32.load16_u + (i64.const 4) + ) + ) + (drop + (block (result i32) + (local.set $0 + (i64.const 4) + ) + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + ) + ) + (drop + (i32.load16_u + (i64.const 4) + ) + ) + (drop + (i32.load16_u offset=100 + (i64.const 4) + ) + ) + (drop + (block (result i32) + (local.set $1 + (i64.const 4) + ) + (i32.or + (i32.load8_u offset=100 + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=101 + (local.get $1) + ) + (i32.const 8) + ) + ) + ) + ) + (drop + (i32.load16_u offset=100 + (i64.const 4) + ) + ) + (drop + (unreachable) + ) + (i32.store16 + (i64.const 4) + (i32.const 8) + ) + (block + (local.set $2 + (i64.const 4) + ) + (local.set $3 + (i32.const 8) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + ) + (i32.store16 + (i64.const 4) + (i32.const 8) + ) + (i32.store16 offset=100 + (i64.const 4) + (i32.const 8) + ) + (block + (local.set $4 + (i64.const 4) + ) + (local.set $5 + (i32.const 8) + ) + (i32.store8 offset=100 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=101 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + ) + (i32.store16 offset=100 + (i64.const 4) + (i32.const 8) + ) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) + ) + (block + (drop + (i64.const 4) + ) + (drop + (unreachable) + ) + ) + ) + (func $func_1 + (drop + (i32.load8_u + (i64.const 4) + ) + ) + (drop + (i32.load8_u + (i64.const 4) + ) + ) + (drop + (i32.load8_u offset=100 + (i64.const 4) + ) + ) + (drop + (i32.load8_u offset=100 + (i64.const 4) + ) + ) + (drop + (unreachable) + ) + (i32.store8 + (i64.const 4) + (i32.const 8) + ) + (i32.store8 + (i64.const 4) + (i32.const 8) + ) + (i32.store8 offset=100 + (i64.const 4) + (i32.const 8) + ) + (i32.store8 offset=100 + (i64.const 4) + (i32.const 8) + ) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) + ) + (block + (drop + (i64.const 4) + ) + (drop + (unreachable) + ) + ) + ) + (func $func_signed + (local $0 i64) + (local $1 i64) + (drop + (i32.load16_s + (i64.const 4) + ) + ) + (drop + (block (result i32) + (local.set $0 + (i64.const 4) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (drop + (i32.load16_s + (i64.const 4) + ) + ) + (drop + (i32.load16_s offset=100 + (i64.const 4) + ) + ) + (drop + (block (result i32) + (local.set $1 + (i64.const 4) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u offset=100 + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=101 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (drop + (i32.load16_s offset=100 + (i64.const 4) + ) + ) + (drop + (unreachable) + ) + ) + (func $i64-load + (local $0 i64) + (local $1 i64) + (local $2 i64) + (local $3 i64) + (local $4 i64) + (local $5 i64) + (local $6 i64) + (local $7 i64) + (local $8 i64) + (local $9 i64) + (local $10 i64) + (local $11 i64) + (local $12 i64) + (local $13 i64) + (drop + (block (result i64) + (local.set $0 + (i64.const 12) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $1 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $1) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $2 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=7 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $3 + (i64.const 16) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $4 + (local.get $3) + ) + (i32.or + (i32.load16_u + (local.get $4) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $4) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $5 + (local.get $3) + ) + (i32.or + (i32.load16_u offset=4 + (local.get $5) + ) + (i32.shl + (i32.load16_u offset=6 + (local.get $5) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $6 + (i64.const 20) + ) + (i64.or + (i64.extend_i32_u + (i32.load + (local.get $6) + ) + ) + (i64.shl + (i64.extend_i32_u + (i32.load offset=4 + (local.get $6) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $7 + (i64.const 20) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $8 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $8) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $8) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $8) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $8) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $9 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=7 + (local.get $9) + ) + (i32.shl + (i32.load8_u offset=8 + (local.get $9) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=9 + (local.get $9) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=10 + (local.get $9) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (i64.extend_i32_s + (block (result i32) + (local.set $10 + (i64.const 28) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u + (local.get $10) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $10) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i64.extend_i32_s + (block (result i32) + (local.set $11 + (i64.const 32) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $11) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $11) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $11) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $11) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (block (result i32) + (local.set $12 + (i64.const 40) + ) + (i32.or + (i32.load8_u + (local.get $12) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $12) + ) + (i32.const 8) + ) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (block (result i32) + (local.set $13 + (i64.const 44) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $13) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $13) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $13) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $13) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + ) + (func $f32-load + (local $0 i64) + (local $1 i64) + (local $2 i64) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $0 + (i64.const 12) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $0) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $0) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $1 + (i64.const 16) + ) + (i32.or + (i32.load16_u + (local.get $1) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + ) + ) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $2 + (i64.const 20) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + ) + (func $f64-load + (local $0 i64) + (local $1 i64) + (local $2 i64) + (local $3 i64) + (local $4 i64) + (local $5 i64) + (local $6 i64) + (local $7 i64) + (local $8 i64) + (local $9 i64) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $0 + (i64.const 12) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $1 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $1) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $2 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=7 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $3 + (i64.const 16) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $4 + (local.get $3) + ) + (i32.or + (i32.load16_u + (local.get $4) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $4) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $5 + (local.get $3) + ) + (i32.or + (i32.load16_u offset=4 + (local.get $5) + ) + (i32.shl + (i32.load16_u offset=6 + (local.get $5) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $6 + (i64.const 20) + ) + (i64.or + (i64.extend_i32_u + (i32.load + (local.get $6) + ) + ) + (i64.shl + (i64.extend_i32_u + (i32.load offset=4 + (local.get $6) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $7 + (i64.const 20) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $8 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $8) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $8) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $8) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $8) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $9 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=7 + (local.get $9) + ) + (i32.shl + (i32.load8_u offset=8 + (local.get $9) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=9 + (local.get $9) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=10 + (local.get $9) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + ) + (func $i64-store + (local $0 i64) + (local $1 i64) + (local $2 i64) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (local $6 i64) + (local $7 i64) + (local $8 i64) + (local $9 i32) + (local $10 i64) + (local $11 i32) + (local $12 i64) + (local $13 i64) + (local $14 i64) + (local $15 i64) + (local $16 i64) + (local $17 i32) + (local $18 i64) + (local $19 i32) + (local $20 i64) + (local $21 i32) + (local $22 i64) + (local $23 i32) + (block + (local.set $0 + (i64.const 12) + ) + (local.set $1 + (i64.const 100) + ) + (block + (local.set $2 + (local.get $0) + ) + (local.set $3 + (i32.wrap_i64 + (local.get $1) + ) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + ) + (block + (local.set $4 + (local.get $0) + ) + (local.set $5 + (i32.wrap_i64 + (i64.shr_u + (local.get $1) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=4 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=7 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $6 + (i64.const 16) + ) + (local.set $7 + (i64.const 200) + ) + (block + (local.set $8 + (local.get $6) + ) + (local.set $9 + (i32.wrap_i64 + (local.get $7) + ) + ) + (i32.store16 + (local.get $8) + (local.get $9) + ) + (i32.store16 offset=2 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $11 + (i32.wrap_i64 + (i64.shr_u + (local.get $7) + (i64.const 32) + ) + ) + ) + (i32.store16 offset=4 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=6 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $12 + (i64.const 20) + ) + (local.set $13 + (i64.const 300) + ) + (i32.store + (local.get $12) + (i32.wrap_i64 + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.wrap_i64 + (i64.shr_u + (local.get $13) + (i64.const 32) + ) + ) + ) + ) + (block + (local.set $14 + (i64.const 24) + ) + (local.set $15 + (i64.const 400) + ) + (block + (local.set $16 + (local.get $14) + ) + (local.set $17 + (i32.wrap_i64 + (local.get $15) + ) + ) + (i32.store8 offset=3 + (local.get $16) + (local.get $17) + ) + (i32.store8 offset=4 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 24) + ) + ) + ) + (block + (local.set $18 + (local.get $14) + ) + (local.set $19 + (i32.wrap_i64 + (i64.shr_u + (local.get $15) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=7 + (local.get $18) + (local.get $19) + ) + (i32.store8 offset=8 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 8) + ) + ) + (i32.store8 offset=9 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 16) + ) + ) + (i32.store8 offset=10 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $20 + (i64.const 20) + ) + (local.set $21 + (i32.wrap_i64 + (i64.const 600) + ) + ) + (i32.store8 + (local.get $20) + (local.get $21) + ) + (i32.store8 offset=1 + (local.get $20) + (i32.shr_u + (local.get $21) + (i32.const 8) + ) + ) + ) + (block + (local.set $22 + (i64.const 20) + ) + (local.set $23 + (i32.wrap_i64 + (i64.const 700) + ) + ) + (i32.store8 + (local.get $22) + (local.get $23) + ) + (i32.store8 offset=1 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 24) + ) + ) + ) + ) + (func $f32-store + (local $0 i64) + (local $1 i32) + (local $2 i64) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (block + (local.set $0 + (i64.const 12) + ) + (local.set $1 + (i32.reinterpret_f32 + (f32.const 100) + ) + ) + (i32.store8 + (local.get $0) + (local.get $1) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 24) + ) + ) + ) + (block + (local.set $2 + (i64.const 16) + ) + (local.set $3 + (i32.reinterpret_f32 + (f32.const 200) + ) + ) + (i32.store16 + (local.get $2) + (local.get $3) + ) + (i32.store16 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + ) + (block + (local.set $4 + (i64.const 24) + ) + (local.set $5 + (i32.reinterpret_f32 + (f32.const 400) + ) + ) + (i32.store8 offset=3 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=4 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (func $f64-store + (local $0 i64) + (local $1 i64) + (local $2 i64) + (local $3 i32) + (local $4 i64) + (local $5 i32) + (local $6 i64) + (local $7 i64) + (local $8 i64) + (local $9 i32) + (local $10 i64) + (local $11 i32) + (local $12 i64) + (local $13 i64) + (local $14 i64) + (local $15 i64) + (local $16 i64) + (local $17 i32) + (local $18 i64) + (local $19 i32) + (block + (local.set $0 + (i64.const 12) + ) + (local.set $1 + (i64.reinterpret_f64 + (f64.const 100) + ) + ) + (block + (local.set $2 + (local.get $0) + ) + (local.set $3 + (i32.wrap_i64 + (local.get $1) + ) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + ) + (block + (local.set $4 + (local.get $0) + ) + (local.set $5 + (i32.wrap_i64 + (i64.shr_u + (local.get $1) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=4 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=7 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $6 + (i64.const 16) + ) + (local.set $7 + (i64.reinterpret_f64 + (f64.const 200) + ) + ) + (block + (local.set $8 + (local.get $6) + ) + (local.set $9 + (i32.wrap_i64 + (local.get $7) + ) + ) + (i32.store16 + (local.get $8) + (local.get $9) + ) + (i32.store16 offset=2 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $11 + (i32.wrap_i64 + (i64.shr_u + (local.get $7) + (i64.const 32) + ) + ) + ) + (i32.store16 offset=4 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=6 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $12 + (i64.const 20) + ) + (local.set $13 + (i64.reinterpret_f64 + (f64.const 300) + ) + ) + (i32.store + (local.get $12) + (i32.wrap_i64 + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.wrap_i64 + (i64.shr_u + (local.get $13) + (i64.const 32) + ) + ) + ) + ) + (block + (local.set $14 + (i64.const 24) + ) + (local.set $15 + (i64.reinterpret_f64 + (f64.const 400) + ) + ) + (block + (local.set $16 + (local.get $14) + ) + (local.set $17 + (i32.wrap_i64 + (local.get $15) + ) + ) + (i32.store8 offset=3 + (local.get $16) + (local.get $17) + ) + (i32.store8 offset=4 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 24) + ) + ) + ) + (block + (local.set $18 + (local.get $14) + ) + (local.set $19 + (i32.wrap_i64 + (i64.shr_u + (local.get $15) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=7 + (local.get $18) + (local.get $19) + ) + (i32.store8 offset=8 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 8) + ) + ) + (i32.store8 offset=9 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 16) + ) + ) + (i32.store8 offset=10 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 24) + ) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/alignment-lowering64.wast binaryen-99/test/passes/alignment-lowering64.wast --- binaryen-108/test/passes/alignment-lowering64.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/alignment-lowering64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,103 @@ +(module + (memory $0 i64 1 1) + (func $func_4 + (drop (i32.load (i64.const 4))) + (drop (i32.load align=1 (i64.const 4))) + (drop (i32.load align=2 (i64.const 4))) + (drop (i32.load align=4 (i64.const 4))) + (drop (i32.load offset=100 (i64.const 4))) + (drop (i32.load offset=100 align=1 (i64.const 4))) + (drop (i32.load offset=100 align=2 (i64.const 4))) + (drop (i32.load offset=100 align=4 (i64.const 4))) + (drop (i32.load offset=100 align=1 (unreachable))) + (i32.store (i64.const 4) (i32.const 8)) + (i32.store align=1 (i64.const 4) (i32.const 8)) + (i32.store align=2 (i64.const 4) (i32.const 8)) + (i32.store align=4 (i64.const 4) (i32.const 8)) + (i32.store offset=100 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=1 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=2 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=4 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store offset=100 align=1 (i64.const 4) (unreachable)) + ) + (func $func_2 + (drop (i32.load16_u (i64.const 4))) + (drop (i32.load16_u align=1 (i64.const 4))) + (drop (i32.load16_u align=2 (i64.const 4))) + (drop (i32.load16_u offset=100 (i64.const 4))) + (drop (i32.load16_u offset=100 align=1 (i64.const 4))) + (drop (i32.load16_u offset=100 align=2 (i64.const 4))) + (drop (i32.load16_u offset=100 align=1 (unreachable))) + (i32.store16 (i64.const 4) (i32.const 8)) + (i32.store16 align=1 (i64.const 4) (i32.const 8)) + (i32.store16 align=2 (i64.const 4) (i32.const 8)) + (i32.store16 offset=100 (i64.const 4) (i32.const 8)) + (i32.store16 offset=100 align=1 (i64.const 4) (i32.const 8)) + (i32.store16 offset=100 align=2 (i64.const 4) (i32.const 8)) + (i32.store16 offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store16 offset=100 align=1 (i64.const 4) (unreachable)) + ) + (func $func_1 + (drop (i32.load8_u (i64.const 4))) + (drop (i32.load8_u align=1 (i64.const 4))) + (drop (i32.load8_u offset=100 (i64.const 4))) + (drop (i32.load8_u offset=100 align=1 (i64.const 4))) + (drop (i32.load8_u offset=100 align=1 (unreachable))) + (i32.store8 (i64.const 4) (i32.const 8)) + (i32.store8 align=1 (i64.const 4) (i32.const 8)) + (i32.store8 offset=100 (i64.const 4) (i32.const 8)) + (i32.store8 offset=100 align=1 (i64.const 4) (i32.const 8)) + (i32.store8 offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store8 offset=100 align=1 (i64.const 4) (unreachable)) + ) + (func $func_signed + (drop (i32.load16_s (i64.const 4))) + (drop (i32.load16_s align=1 (i64.const 4))) + (drop (i32.load16_s align=2 (i64.const 4))) + (drop (i32.load16_s offset=100 (i64.const 4))) + (drop (i32.load16_s offset=100 align=1 (i64.const 4))) + (drop (i32.load16_s offset=100 align=2 (i64.const 4))) + (drop (i32.load16_s offset=100 align=1 (unreachable))) + ) + (func $i64-load + (drop (i64.load align=1 (i64.const 12))) + (drop (i64.load align=2 (i64.const 16))) + (drop (i64.load align=4 (i64.const 20))) + (drop (i64.load align=1 offset=3 (i64.const 20))) + (drop (i64.load16_s align=1 (i64.const 28))) + (drop (i64.load32_s align=1 (i64.const 32))) + (drop (i64.load16_u align=1 (i64.const 40))) + (drop (i64.load32_u align=1 (i64.const 44))) + ) + (func $f32-load + (drop (f32.load align=1 (i64.const 12))) + (drop (f32.load align=2 (i64.const 16))) + (drop (f32.load align=1 offset=3 (i64.const 20))) + ) + (func $f64-load + (drop (f64.load align=1 (i64.const 12))) + (drop (f64.load align=2 (i64.const 16))) + (drop (f64.load align=4 (i64.const 20))) + (drop (f64.load align=1 offset=3 (i64.const 20))) + ) + (func $i64-store + (i64.store align=1 (i64.const 12) (i64.const 100)) + (i64.store align=2 (i64.const 16) (i64.const 200)) + (i64.store align=4 (i64.const 20) (i64.const 300)) + (i64.store align=1 offset=3 (i64.const 24) (i64.const 400)) + (i64.store16 align=1 (i64.const 20) (i64.const 600)) + (i64.store32 align=1 (i64.const 20) (i64.const 700)) + ) + (func $f32-store + (f32.store align=1 (i64.const 12) (f32.const 100)) + (f32.store align=2 (i64.const 16) (f32.const 200)) + (f32.store align=1 offset=3 (i64.const 24) (f32.const 400)) + ) + (func $f64-store + (f64.store align=1 (i64.const 12) (f64.const 100)) + (f64.store align=2 (i64.const 16) (f64.const 200)) + (f64.store align=4 (i64.const 20) (f64.const 300)) + (f64.store align=1 offset=3 (i64.const 24) (f64.const 400)) + ) +) diff -Nru binaryen-108/test/passes/alignment-lowering.txt binaryen-99/test/passes/alignment-lowering.txt --- binaryen-108/test/passes/alignment-lowering.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/alignment-lowering.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1948 @@ +(module + (type $none_=>_none (func)) + (memory $0 1 1) + (func $func_4 + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (drop + (i32.load + (i32.const 4) + ) + ) + (drop + (block (result i32) + (local.set $0 + (i32.const 4) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $0) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $0) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (local.set $1 + (i32.const 4) + ) + (i32.or + (i32.load16_u + (local.get $1) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i32.load + (i32.const 4) + ) + ) + (drop + (i32.load offset=100 + (i32.const 4) + ) + ) + (drop + (block (result i32) + (local.set $2 + (i32.const 4) + ) + (i32.or + (i32.or + (i32.load8_u offset=100 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=101 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=102 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=103 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (local.set $3 + (i32.const 4) + ) + (i32.or + (i32.load16_u offset=100 + (local.get $3) + ) + (i32.shl + (i32.load16_u offset=102 + (local.get $3) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i32.load offset=100 + (i32.const 4) + ) + ) + (drop + (unreachable) + ) + (i32.store + (i32.const 4) + (i32.const 8) + ) + (block + (local.set $4 + (i32.const 4) + ) + (local.set $5 + (i32.const 8) + ) + (i32.store8 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=1 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + (block + (local.set $6 + (i32.const 4) + ) + (local.set $7 + (i32.const 8) + ) + (i32.store16 + (local.get $6) + (local.get $7) + ) + (i32.store16 offset=2 + (local.get $6) + (i32.shr_u + (local.get $7) + (i32.const 16) + ) + ) + ) + (i32.store + (i32.const 4) + (i32.const 8) + ) + (i32.store offset=100 + (i32.const 4) + (i32.const 8) + ) + (block + (local.set $8 + (i32.const 4) + ) + (local.set $9 + (i32.const 8) + ) + (i32.store8 offset=100 + (local.get $8) + (local.get $9) + ) + (i32.store8 offset=101 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 8) + ) + ) + (i32.store8 offset=102 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + (i32.store8 offset=103 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 24) + ) + ) + ) + (block + (local.set $10 + (i32.const 4) + ) + (local.set $11 + (i32.const 8) + ) + (i32.store16 offset=100 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=102 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + (i32.store offset=100 + (i32.const 4) + (i32.const 8) + ) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) + ) + (block + (drop + (i32.const 4) + ) + (drop + (unreachable) + ) + ) + ) + (func $func_2 + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (drop + (i32.load16_u + (i32.const 4) + ) + ) + (drop + (block (result i32) + (local.set $0 + (i32.const 4) + ) + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + ) + ) + (drop + (i32.load16_u + (i32.const 4) + ) + ) + (drop + (i32.load16_u offset=100 + (i32.const 4) + ) + ) + (drop + (block (result i32) + (local.set $1 + (i32.const 4) + ) + (i32.or + (i32.load8_u offset=100 + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=101 + (local.get $1) + ) + (i32.const 8) + ) + ) + ) + ) + (drop + (i32.load16_u offset=100 + (i32.const 4) + ) + ) + (drop + (unreachable) + ) + (i32.store16 + (i32.const 4) + (i32.const 8) + ) + (block + (local.set $2 + (i32.const 4) + ) + (local.set $3 + (i32.const 8) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + ) + (i32.store16 + (i32.const 4) + (i32.const 8) + ) + (i32.store16 offset=100 + (i32.const 4) + (i32.const 8) + ) + (block + (local.set $4 + (i32.const 4) + ) + (local.set $5 + (i32.const 8) + ) + (i32.store8 offset=100 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=101 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + ) + (i32.store16 offset=100 + (i32.const 4) + (i32.const 8) + ) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) + ) + (block + (drop + (i32.const 4) + ) + (drop + (unreachable) + ) + ) + ) + (func $func_1 + (drop + (i32.load8_u + (i32.const 4) + ) + ) + (drop + (i32.load8_u + (i32.const 4) + ) + ) + (drop + (i32.load8_u offset=100 + (i32.const 4) + ) + ) + (drop + (i32.load8_u offset=100 + (i32.const 4) + ) + ) + (drop + (unreachable) + ) + (i32.store8 + (i32.const 4) + (i32.const 8) + ) + (i32.store8 + (i32.const 4) + (i32.const 8) + ) + (i32.store8 offset=100 + (i32.const 4) + (i32.const 8) + ) + (i32.store8 offset=100 + (i32.const 4) + (i32.const 8) + ) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) + ) + (block + (drop + (i32.const 4) + ) + (drop + (unreachable) + ) + ) + ) + (func $func_signed + (local $0 i32) + (local $1 i32) + (drop + (i32.load16_s + (i32.const 4) + ) + ) + (drop + (block (result i32) + (local.set $0 + (i32.const 4) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (drop + (i32.load16_s + (i32.const 4) + ) + ) + (drop + (i32.load16_s offset=100 + (i32.const 4) + ) + ) + (drop + (block (result i32) + (local.set $1 + (i32.const 4) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u offset=100 + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=101 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (drop + (i32.load16_s offset=100 + (i32.const 4) + ) + ) + (drop + (unreachable) + ) + ) + (func $i64-load + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (drop + (block (result i64) + (local.set $0 + (i32.const 12) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $1 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $1) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $2 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=7 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $3 + (i32.const 16) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $4 + (local.get $3) + ) + (i32.or + (i32.load16_u + (local.get $4) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $4) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $5 + (local.get $3) + ) + (i32.or + (i32.load16_u offset=4 + (local.get $5) + ) + (i32.shl + (i32.load16_u offset=6 + (local.get $5) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $6 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (i32.load + (local.get $6) + ) + ) + (i64.shl + (i64.extend_i32_u + (i32.load offset=4 + (local.get $6) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $7 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $8 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $8) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $8) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $8) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $8) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $9 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=7 + (local.get $9) + ) + (i32.shl + (i32.load8_u offset=8 + (local.get $9) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=9 + (local.get $9) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=10 + (local.get $9) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (i64.extend_i32_s + (block (result i32) + (local.set $10 + (i32.const 28) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u + (local.get $10) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $10) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i64.extend_i32_s + (block (result i32) + (local.set $11 + (i32.const 32) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $11) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $11) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $11) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $11) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (block (result i32) + (local.set $12 + (i32.const 40) + ) + (i32.or + (i32.load8_u + (local.get $12) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $12) + ) + (i32.const 8) + ) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (block (result i32) + (local.set $13 + (i32.const 44) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $13) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $13) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $13) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $13) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + ) + (func $f32-load + (local $0 i32) + (local $1 i32) + (local $2 i32) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $0 + (i32.const 12) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $0) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $0) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $1 + (i32.const 16) + ) + (i32.or + (i32.load16_u + (local.get $1) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + ) + ) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $2 + (i32.const 20) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + ) + (func $f64-load + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $0 + (i32.const 12) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $1 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $1) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $2 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=7 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $3 + (i32.const 16) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $4 + (local.get $3) + ) + (i32.or + (i32.load16_u + (local.get $4) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $4) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $5 + (local.get $3) + ) + (i32.or + (i32.load16_u offset=4 + (local.get $5) + ) + (i32.shl + (i32.load16_u offset=6 + (local.get $5) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $6 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (i32.load + (local.get $6) + ) + ) + (i64.shl + (i64.extend_i32_u + (i32.load offset=4 + (local.get $6) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $7 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $8 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $8) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $8) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $8) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $8) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $9 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=7 + (local.get $9) + ) + (i32.shl + (i32.load8_u offset=8 + (local.get $9) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=9 + (local.get $9) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=10 + (local.get $9) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + ) + (func $i64-store + (local $0 i32) + (local $1 i64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i64) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i64) + (local $14 i32) + (local $15 i64) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 i32) + (block + (local.set $0 + (i32.const 12) + ) + (local.set $1 + (i64.const 100) + ) + (block + (local.set $2 + (local.get $0) + ) + (local.set $3 + (i32.wrap_i64 + (local.get $1) + ) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + ) + (block + (local.set $4 + (local.get $0) + ) + (local.set $5 + (i32.wrap_i64 + (i64.shr_u + (local.get $1) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=4 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=7 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $6 + (i32.const 16) + ) + (local.set $7 + (i64.const 200) + ) + (block + (local.set $8 + (local.get $6) + ) + (local.set $9 + (i32.wrap_i64 + (local.get $7) + ) + ) + (i32.store16 + (local.get $8) + (local.get $9) + ) + (i32.store16 offset=2 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $11 + (i32.wrap_i64 + (i64.shr_u + (local.get $7) + (i64.const 32) + ) + ) + ) + (i32.store16 offset=4 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=6 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $12 + (i32.const 20) + ) + (local.set $13 + (i64.const 300) + ) + (i32.store + (local.get $12) + (i32.wrap_i64 + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.wrap_i64 + (i64.shr_u + (local.get $13) + (i64.const 32) + ) + ) + ) + ) + (block + (local.set $14 + (i32.const 24) + ) + (local.set $15 + (i64.const 400) + ) + (block + (local.set $16 + (local.get $14) + ) + (local.set $17 + (i32.wrap_i64 + (local.get $15) + ) + ) + (i32.store8 offset=3 + (local.get $16) + (local.get $17) + ) + (i32.store8 offset=4 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 24) + ) + ) + ) + (block + (local.set $18 + (local.get $14) + ) + (local.set $19 + (i32.wrap_i64 + (i64.shr_u + (local.get $15) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=7 + (local.get $18) + (local.get $19) + ) + (i32.store8 offset=8 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 8) + ) + ) + (i32.store8 offset=9 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 16) + ) + ) + (i32.store8 offset=10 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $20 + (i32.const 20) + ) + (local.set $21 + (i32.wrap_i64 + (i64.const 600) + ) + ) + (i32.store8 + (local.get $20) + (local.get $21) + ) + (i32.store8 offset=1 + (local.get $20) + (i32.shr_u + (local.get $21) + (i32.const 8) + ) + ) + ) + (block + (local.set $22 + (i32.const 20) + ) + (local.set $23 + (i32.wrap_i64 + (i64.const 700) + ) + ) + (i32.store8 + (local.get $22) + (local.get $23) + ) + (i32.store8 offset=1 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 24) + ) + ) + ) + ) + (func $f32-store + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (local.set $0 + (i32.const 12) + ) + (local.set $1 + (i32.reinterpret_f32 + (f32.const 100) + ) + ) + (i32.store8 + (local.get $0) + (local.get $1) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 24) + ) + ) + ) + (block + (local.set $2 + (i32.const 16) + ) + (local.set $3 + (i32.reinterpret_f32 + (f32.const 200) + ) + ) + (i32.store16 + (local.get $2) + (local.get $3) + ) + (i32.store16 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + ) + (block + (local.set $4 + (i32.const 24) + ) + (local.set $5 + (i32.reinterpret_f32 + (f32.const 400) + ) + ) + (i32.store8 offset=3 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=4 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (func $f64-store + (local $0 i32) + (local $1 i64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i64) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i64) + (local $14 i32) + (local $15 i64) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (block + (local.set $0 + (i32.const 12) + ) + (local.set $1 + (i64.reinterpret_f64 + (f64.const 100) + ) + ) + (block + (local.set $2 + (local.get $0) + ) + (local.set $3 + (i32.wrap_i64 + (local.get $1) + ) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + ) + (block + (local.set $4 + (local.get $0) + ) + (local.set $5 + (i32.wrap_i64 + (i64.shr_u + (local.get $1) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=4 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=7 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $6 + (i32.const 16) + ) + (local.set $7 + (i64.reinterpret_f64 + (f64.const 200) + ) + ) + (block + (local.set $8 + (local.get $6) + ) + (local.set $9 + (i32.wrap_i64 + (local.get $7) + ) + ) + (i32.store16 + (local.get $8) + (local.get $9) + ) + (i32.store16 offset=2 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $11 + (i32.wrap_i64 + (i64.shr_u + (local.get $7) + (i64.const 32) + ) + ) + ) + (i32.store16 offset=4 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=6 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $12 + (i32.const 20) + ) + (local.set $13 + (i64.reinterpret_f64 + (f64.const 300) + ) + ) + (i32.store + (local.get $12) + (i32.wrap_i64 + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.wrap_i64 + (i64.shr_u + (local.get $13) + (i64.const 32) + ) + ) + ) + ) + (block + (local.set $14 + (i32.const 24) + ) + (local.set $15 + (i64.reinterpret_f64 + (f64.const 400) + ) + ) + (block + (local.set $16 + (local.get $14) + ) + (local.set $17 + (i32.wrap_i64 + (local.get $15) + ) + ) + (i32.store8 offset=3 + (local.get $16) + (local.get $17) + ) + (i32.store8 offset=4 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 24) + ) + ) + ) + (block + (local.set $18 + (local.get $14) + ) + (local.set $19 + (i32.wrap_i64 + (i64.shr_u + (local.get $15) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=7 + (local.get $18) + (local.get $19) + ) + (i32.store8 offset=8 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 8) + ) + ) + (i32.store8 offset=9 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 16) + ) + ) + (i32.store8 offset=10 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 24) + ) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/alignment-lowering.wast binaryen-99/test/passes/alignment-lowering.wast --- binaryen-108/test/passes/alignment-lowering.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/alignment-lowering.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,103 @@ +(module + (memory $0 1 1) + (func $func_4 + (drop (i32.load (i32.const 4))) + (drop (i32.load align=1 (i32.const 4))) + (drop (i32.load align=2 (i32.const 4))) + (drop (i32.load align=4 (i32.const 4))) + (drop (i32.load offset=100 (i32.const 4))) + (drop (i32.load offset=100 align=1 (i32.const 4))) + (drop (i32.load offset=100 align=2 (i32.const 4))) + (drop (i32.load offset=100 align=4 (i32.const 4))) + (drop (i32.load offset=100 align=1 (unreachable))) + (i32.store (i32.const 4) (i32.const 8)) + (i32.store align=1 (i32.const 4) (i32.const 8)) + (i32.store align=2 (i32.const 4) (i32.const 8)) + (i32.store align=4 (i32.const 4) (i32.const 8)) + (i32.store offset=100 (i32.const 4) (i32.const 8)) + (i32.store offset=100 align=1 (i32.const 4) (i32.const 8)) + (i32.store offset=100 align=2 (i32.const 4) (i32.const 8)) + (i32.store offset=100 align=4 (i32.const 4) (i32.const 8)) + (i32.store offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store offset=100 align=1 (i32.const 4) (unreachable)) + ) + (func $func_2 + (drop (i32.load16_u (i32.const 4))) + (drop (i32.load16_u align=1 (i32.const 4))) + (drop (i32.load16_u align=2 (i32.const 4))) + (drop (i32.load16_u offset=100 (i32.const 4))) + (drop (i32.load16_u offset=100 align=1 (i32.const 4))) + (drop (i32.load16_u offset=100 align=2 (i32.const 4))) + (drop (i32.load16_u offset=100 align=1 (unreachable))) + (i32.store16 (i32.const 4) (i32.const 8)) + (i32.store16 align=1 (i32.const 4) (i32.const 8)) + (i32.store16 align=2 (i32.const 4) (i32.const 8)) + (i32.store16 offset=100 (i32.const 4) (i32.const 8)) + (i32.store16 offset=100 align=1 (i32.const 4) (i32.const 8)) + (i32.store16 offset=100 align=2 (i32.const 4) (i32.const 8)) + (i32.store16 offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store16 offset=100 align=1 (i32.const 4) (unreachable)) + ) + (func $func_1 + (drop (i32.load8_u (i32.const 4))) + (drop (i32.load8_u align=1 (i32.const 4))) + (drop (i32.load8_u offset=100 (i32.const 4))) + (drop (i32.load8_u offset=100 align=1 (i32.const 4))) + (drop (i32.load8_u offset=100 align=1 (unreachable))) + (i32.store8 (i32.const 4) (i32.const 8)) + (i32.store8 align=1 (i32.const 4) (i32.const 8)) + (i32.store8 offset=100 (i32.const 4) (i32.const 8)) + (i32.store8 offset=100 align=1 (i32.const 4) (i32.const 8)) + (i32.store8 offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store8 offset=100 align=1 (i32.const 4) (unreachable)) + ) + (func $func_signed + (drop (i32.load16_s (i32.const 4))) + (drop (i32.load16_s align=1 (i32.const 4))) + (drop (i32.load16_s align=2 (i32.const 4))) + (drop (i32.load16_s offset=100 (i32.const 4))) + (drop (i32.load16_s offset=100 align=1 (i32.const 4))) + (drop (i32.load16_s offset=100 align=2 (i32.const 4))) + (drop (i32.load16_s offset=100 align=1 (unreachable))) + ) + (func $i64-load + (drop (i64.load align=1 (i32.const 12))) + (drop (i64.load align=2 (i32.const 16))) + (drop (i64.load align=4 (i32.const 20))) + (drop (i64.load align=1 offset=3 (i32.const 20))) + (drop (i64.load16_s align=1 (i32.const 28))) + (drop (i64.load32_s align=1 (i32.const 32))) + (drop (i64.load16_u align=1 (i32.const 40))) + (drop (i64.load32_u align=1 (i32.const 44))) + ) + (func $f32-load + (drop (f32.load align=1 (i32.const 12))) + (drop (f32.load align=2 (i32.const 16))) + (drop (f32.load align=1 offset=3 (i32.const 20))) + ) + (func $f64-load + (drop (f64.load align=1 (i32.const 12))) + (drop (f64.load align=2 (i32.const 16))) + (drop (f64.load align=4 (i32.const 20))) + (drop (f64.load align=1 offset=3 (i32.const 20))) + ) + (func $i64-store + (i64.store align=1 (i32.const 12) (i64.const 100)) + (i64.store align=2 (i32.const 16) (i64.const 200)) + (i64.store align=4 (i32.const 20) (i64.const 300)) + (i64.store align=1 offset=3 (i32.const 24) (i64.const 400)) + (i64.store16 align=1 (i32.const 20) (i64.const 600)) + (i64.store32 align=1 (i32.const 20) (i64.const 700)) + ) + (func $f32-store + (f32.store align=1 (i32.const 12) (f32.const 100)) + (f32.store align=2 (i32.const 16) (f32.const 200)) + (f32.store align=1 offset=3 (i32.const 24) (f32.const 400)) + ) + (func $f64-store + (f64.store align=1 (i32.const 12) (f64.const 100)) + (f64.store align=2 (i32.const 16) (f64.const 200)) + (f64.store align=4 (i32.const 20) (f64.const 300)) + (f64.store align=1 offset=3 (i32.const 24) (f64.const 400)) + ) +) diff -Nru binaryen-108/test/passes/asyncify_enable-multivalue.txt binaryen-99/test/passes/asyncify_enable-multivalue.txt --- binaryen-108/test/passes/asyncify_enable-multivalue.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_enable-multivalue.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,2592 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (memory $0 1 2) + (global $sleeping (mut i32) (i32.const 0)) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $do_sleep + (local $0 i32) + (local $1 i32) + (local.set $0 + (global.get $sleeping) + ) + (local.set $1 + (i32.eqz + (local.get $0) + ) + ) + (if + (local.get $1) + (block $block + (global.set $sleeping + (i32.const 1) + ) + (call $asyncify_start_unwind + (i32.const 4) + ) + ) + (block $block0 + (global.set $sleeping + (i32.const 0) + ) + (call $asyncify_stop_rewind) + ) + ) + ) + (func $work + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $stuff) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $do_sleep) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $stuff) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $stuff + (nop) + ) + (func $first_event + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $work) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $second_event + (call $asyncify_stop_unwind) + (call $asyncify_start_rewind + (i32.const 4) + ) + (call $work) + ) + (func $never_sleep + (call $stuff) + (call $stuff) + (call $stuff) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32_i64 (func (result i32 i64))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (import "env" "import-mv" (func $import-mv (result i32 i64))) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $8 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (i32.load + (local.get $8) + ) + ) + ) + ) + (local.set $5 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $6) + (i32.const 0) + ) + ) + (block + (local.set $7 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $1 + (local.get $7) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $temp + (local.get $1) + ) + (local.set $2 + (local.get $temp) + ) + (return + (local.get $2) + ) + ) + ) + (nop) + (nop) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $5) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $9 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $9) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-import2-drop + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-nothing + (local $0 i32) + (local.set $0 + (i32.eqz + (i32.const 17) + ) + ) + (drop + (local.get $0) + ) + ) + (func $many-locals (param $x i32) (result i32) + (local $y i32) + (local $z (f32 i64)) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $13 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $y + (i32.load + (local.get $13) + ) + ) + ) + ) + (local.set $11 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $12 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (loop $l + (local.set $3 + (local.get $y) + ) + (local.set $4 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (local.set $x + (local.get $4) + ) + (local.set $5 + (local.get $x) + ) + (local.set $6 + (i32.div_s + (local.get $5) + (i32.const 3) + ) + ) + (local.set $y + (local.get $6) + ) + (local.set $7 + (local.get $y) + ) + (br_if $l + (local.get $7) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $12) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $8 + (local.get $y) + ) + (return + (local.get $8) + ) + ) + ) + (nop) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $11) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $14 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $14) + (local.get $y) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-import2-if (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $2 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $3 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (if + (i32.or + (local.get $1) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $3) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2-if-else (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $2 + (i32.load + (local.get $5) + ) + ) + ) + ) + (local.set $3 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $2 + (local.get $1) + ) + ) + (if + (i32.or + (local.get $2) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $4) + (i32.const 0) + ) + ) + (block + (call $import3 + (i32.const 1) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $2) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $4) + (i32.const 1) + ) + ) + (block + (call $import3 + (i32.const 2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $3) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $6) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-import2-if-else-oneside (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $5 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $4 + (local.get $1) + ) + ) + (if + (i32.or + (local.get $4) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (return + (i32.const 1) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $4) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $6) + (i32.const 0) + ) + ) + (block + (call $import3 + (i32.const 2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (return + (i32.const 3) + ) + ) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $5) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + (i32.const 0) + ) + (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $7 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $4 + (i32.load + (local.get $7) + ) + ) + ) + ) + (local.set $5 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $4 + (local.get $1) + ) + ) + (if + (i32.or + (local.get $4) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $6) + (i32.const 0) + ) + ) + (block + (call $import3 + (i32.const 1) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $4) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (return + (i32.const 2) + ) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (return + (i32.const 3) + ) + ) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $5) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $8 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $8) + (local.get $4) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-mv + (local $x (i32 i64)) + (local $1 (i32 i64)) + (local $2 i32) + (local $3 i32) + (local $4 (i32 i64)) + (local $5 i32) + (local $6 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -12) + ) + ) + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (tuple.make + (i32.load + (local.get $5) + ) + (i64.load offset=4 align=4 + (local.get $5) + ) + ) + ) + ) + ) + (local.set $2 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $3 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $3) + (i32.const 0) + ) + ) + (block + (local.set $4 + (call $import-mv) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $1 + (local.get $4) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $x + (local.get $1) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $6) + (tuple.extract 0 + (local.get $1) + ) + ) + (i64.store offset=4 align=4 + (local.get $6) + (tuple.extract 1 + (local.get $1) + ) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 12) + ) + ) + ) + ) + (func $calls-loop (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $x + (i32.load + (local.get $6) + ) + ) + ) + ) + (local.set $4 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $5 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (loop $l + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $5) + (i32.const 0) + ) + ) + (block + (call $import3 + (i32.const 1) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $1 + (local.get $x) + ) + (local.set $2 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $x + (local.get $2) + ) + (local.set $3 + (local.get $x) + ) + (br_if $l + (local.get $3) + ) + ) + ) + (nop) + (nop) + (nop) + (nop) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $4) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $7 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $7) + (local.get $x) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-loop2 + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (loop $l + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (br_if $l + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-mix + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 1) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $boring + (nop) + ) + (func $calls-mix-deep + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring-deep) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import-deep) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 1) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $boring-deep + (call $boring) + ) + (func $import-deep + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (memory $0 1 1) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_enable-multivalue.wast binaryen-99/test/passes/asyncify_enable-multivalue.wast --- binaryen-108/test/passes/asyncify_enable-multivalue.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_enable-multivalue.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,157 @@ +;; Pre-existing imports that the pass turns into the implementations. +(module + (memory 1 2) + (import "asyncify" "start_unwind" (func $asyncify_start_unwind (param i32))) + (import "asyncify" "stop_unwind" (func $asyncify_stop_unwind)) + (import "asyncify" "start_rewind" (func $asyncify_start_rewind (param i32))) + (import "asyncify" "stop_rewind" (func $asyncify_stop_rewind)) + (global $sleeping (mut i32) (i32.const 0)) + ;; do a sleep operation: start a sleep if running, or resume after a sleep + ;; if we just rewound. + (func $do_sleep + (if + (i32.eqz (global.get $sleeping)) + (block + (global.set $sleeping (i32.const 1)) + ;; we should set up the data at address 4 around here + (call $asyncify_start_unwind (i32.const 4)) + ) + (block + (global.set $sleeping (i32.const 0)) + (call $asyncify_stop_rewind) + ) + ) + ) + ;; a function that does some work and has a sleep (async pause/resume) in the middle + (func $work + (call $stuff) ;; do some work + (call $do_sleep) ;; take a break + (call $stuff) ;; do some more work + ) + (func $stuff) + ;; the first event called from the main event loop: just call into $work + (func $first_event + (call $work) + ;; work will sleep, so we exit through here while it is paused + ) + ;; the second event called from the main event loop: to resume $work, + ;; stop the unwind, then prepare a rewind, and initiate it by doing + ;; the call to rewind the call stack back up to where it was + (func $second_event + (call $asyncify_stop_unwind) + (call $asyncify_start_rewind (i32.const 4)) + (call $work) + ) + ;; a function that can't do a sleep + (func $never_sleep + (call $stuff) + (call $stuff) + (call $stuff) + ) +) +;; Calls to imports that will call into asyncify themselves. +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (import "env" "import-mv" (func $import-mv (result i32 i64))) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) + (func $many-locals (param $x i32) (result i32) + (local $y i32) + (local $z (f32 i64)) + (loop $l + (local.set $x + (i32.add (local.get $y) (i32.const 1)) + ) + (local.set $y + (i32.div_s (local.get $x) (i32.const 3)) + ) + (br_if $l (local.get $y)) + ) + (call $import) + (return (local.get $y)) + ) + (func $calls-import2-if (param $x i32) + (if (local.get $x) + (call $import) + ) + ) + (func $calls-import2-if-else (param $x i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (call $import3 (i32.const 2)) + ) + ) + (func $calls-import2-if-else-oneside (param $x i32) (result i32) + (if (local.get $x) + (return (i32.const 1)) + (call $import3 (i32.const 2)) + ) + (return (i32.const 3)) + ) + (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (return (i32.const 2)) + ) + (return (i32.const 3)) + ) + (func $calls-mv + (local $x (i32 i64)) + (local.set $x (call $import-mv)) + ) + (func $calls-loop (param $x i32) + (loop $l + (call $import3 (i32.const 1)) + (local.set $x + (i32.add (local.get $x) (i32.const 1)) + ) + (br_if $l + (local.get $x) + ) + ) + ) + (func $calls-loop2 + (loop $l + (br_if $l + (call $import2) + ) + ) + ) + (func $calls-mix + (call $boring) + (call $import) + (call $boring) + (call $import) + ) + (func $boring) + (func $calls-mix-deep + (call $boring-deep) + (call $import-deep) + (call $boring) + (call $import) + ) + (func $boring-deep + (call $boring) + ) + (func $import-deep + (call $import) + ) +) +;; empty module, in particular with no memory +(module +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt --- binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,94 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "calls-import" (func $calls-import)) + (export "calls-import2" (func $calls-import)) + (export "calls-import2-drop" (func $calls-import)) + (export "calls-nothing" (func $calls-import)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_unwind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import (; has Stack IR ;) + (local $0 i32) + (call $import) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $asyncify_start_unwind (; has Stack IR ;) (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind (; has Stack IR ;) + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (; has Stack IR ;) (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (; has Stack IR ;) (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast --- binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,24 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (export "calls-import" (func $calls-import)) + (export "calls-import2" (func $calls-import)) + (export "calls-import2-drop" (func $calls-import)) + (export "calls-nothing" (func $calls-import)) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt --- binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,470 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.const 0) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.const 1) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (if + (i32.const 0) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $8 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (i32.load + (local.get $8) + ) + ) + ) + ) + (local.set $5 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.const 0) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $6) + (i32.const 0) + ) + ) + (block + (local.set $7 + (call $import2) + ) + (if + (i32.const 1) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $1 + (local.get $7) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $temp + (local.get $1) + ) + (local.set $2 + (local.get $temp) + ) + (return + (local.get $2) + ) + ) + ) + (nop) + (nop) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $5) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $9 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $9) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-import2-drop + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.const 0) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.const 0) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.const 1) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-nothing + (local $0 i32) + (local.set $0 + (i32.eqz + (i32.const 17) + ) + ) + (drop + (local.get $0) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind.wast binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind.wast --- binaryen-108/test/passes/asyncify_mod-asyncify-always-and-only-unwind.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-always-and-only-unwind.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,20 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind_O.txt binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind_O.txt --- binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind_O.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind_O.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,109 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "calls-import" (func $calls-import)) + (export "calls-import2" (func $calls-import)) + (export "calls-import2-drop" (func $calls-import)) + (export "calls-nothing" (func $calls-import)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_unwind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import (; has Stack IR ;) + (if + (select + (i32.eqz + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block (result i32) + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (call $import) + ) + ) + (func $asyncify_start_unwind (; has Stack IR ;) (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind (; has Stack IR ;) + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (; has Stack IR ;) (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (; has Stack IR ;) (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind_O.wast binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind_O.wast --- binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind_O.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind_O.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,24 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (export "calls-import" (func $calls-import)) + (export "calls-import2" (func $calls-import)) + (export "calls-import2-drop" (func $calls-import)) + (export "calls-nothing" (func $calls-import)) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind.txt binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind.txt --- binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,488 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.const 0) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $8 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (i32.load + (local.get $8) + ) + ) + ) + ) + (local.set $5 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $6) + (i32.const 0) + ) + ) + (block + (local.set $7 + (call $import2) + ) + (if + (i32.const 0) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $1 + (local.get $7) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $temp + (local.get $1) + ) + (local.set $2 + (local.get $temp) + ) + (return + (local.get $2) + ) + ) + ) + (nop) + (nop) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $5) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $9 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $9) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-import2-drop + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.const 0) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-nothing + (local $0 i32) + (local.set $0 + (i32.eqz + (i32.const 17) + ) + ) + (drop + (local.get $0) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind.wast binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind.wast --- binaryen-108/test/passes/asyncify_mod-asyncify-never-unwind.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_mod-asyncify-never-unwind.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,20 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) +) diff -Nru binaryen-108/test/passes/asyncify_optimize-level=1.txt binaryen-99/test/passes/asyncify_optimize-level=1.txt --- binaryen-108/test/passes/asyncify_optimize-level=1.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_optimize-level=1.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1511 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (select + (i32.eqz + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block (result i32) + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + (local.get $0) + ) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $calls-import2 (result i32) + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $0 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (if + (select + (i32.eqz + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block (result i32) + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + (local.get $1) + ) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (local.set $1 + (call $import2) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + (local.set $0 + (local.get $1) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (return + (local.get $0) + ) + ) + (unreachable) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.const 0) + ) + (func $calls-import2-drop + (local $0 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (select + (i32.eqz + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block (result i32) + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + (local.get $0) + ) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (drop + (call $import2) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $calls-nothing + (nop) + ) + (func $many-locals (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (loop $l + (br_if $l + (local.tee $1 + (i32.div_s + (i32.add + (local.get $1) + (i32.const 1) + ) + (i32.const 3) + ) + ) + ) + ) + ) + (if + (select + (i32.eqz + (local.get $2) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (return + (local.get $1) + ) + ) + (unreachable) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.const 0) + ) + (func $calls-import2-if (param $0 i32) + (local $1 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.or + (local.get $0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (select + (i32.eqz + (local.get $1) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $calls-import2-if-else (param $0 i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.or + (local.tee $1 + (select + (local.get $1) + (local.get $0) + (global.get $__asyncify_state) + ) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (select + (i32.eqz + (local.get $2) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import3 + (i32.const 1) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $1) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (select + (i32.eq + (local.get $2) + (i32.const 1) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import3 + (i32.const 2) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 1) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $calls-import2-if-else-oneside (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.or + (local.tee $2 + (select + (local.get $2) + (local.get $0) + (global.get $__asyncify_state) + ) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (return + (i32.const 1) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $2) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (select + (i32.eqz + (local.get $1) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import3 + (i32.const 2) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (return + (i32.const 3) + ) + ) + (unreachable) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.const 0) + ) + (func $calls-import2-if-else-oneside2 (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.or + (local.tee $1 + (select + (local.get $1) + (local.get $0) + (global.get $__asyncify_state) + ) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (select + (i32.eqz + (local.get $2) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import3 + (i32.const 1) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $1) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (return + (i32.const 2) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (return + (i32.const 3) + ) + ) + (unreachable) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.const 0) + ) + (func $calls-loop (param $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $0 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (loop $l + (if + (select + (i32.eqz + (local.get $1) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import3 + (i32.const 1) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (br_if $l + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $calls-loop2 + (local $0 i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $0 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (loop $l + (if + (select + (i32.eqz + (local.get $2) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (local.set $1 + (call $import2) + ) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + (local.set $0 + (local.get $1) + ) + ) + ) + (br_if $l + (select + (i32.eqz + (global.get $__asyncify_state) + ) + (i32.const 0) + (local.get $0) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $calls-mix + (local $0 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $0 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (call $boring) + ) + (if + (select + (i32.eqz + (local.get $0) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (call $boring) + ) + (if + (select + (i32.eq + (local.get $0) + (i32.const 1) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 1) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $boring + (nop) + ) + (func $calls-mix-deep + (local $0 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (local.set $0 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (call $boring-deep) + ) + (if + (select + (i32.eqz + (local.get $0) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import-deep) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (if + (i32.eqz + (global.get $__asyncify_state) + ) + (call $boring) + ) + (if + (select + (i32.eq + (local.get $0) + (i32.const 1) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 1) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $boring-deep + (call $boring) + ) + (func $import-deep + (local $0 i32) + (local.set $0 + (block $__asyncify_unwind (result i32) + (if + (select + (i32.eqz + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block (result i32) + (i32.store + (global.get $__asyncify_data) + (i32.sub + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + (local.get $0) + ) + ) + (i32.const 1) + (global.get $__asyncify_state) + ) + (block + (call $import) + (drop + (br_if $__asyncify_unwind + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + ) + ) + ) + ) + (return) + ) + ) + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_optimize-level=1.wast binaryen-99/test/passes/asyncify_optimize-level=1.wast --- binaryen-108/test/passes/asyncify_optimize-level=1.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_optimize-level=1.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,97 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) + (func $many-locals (param $x i32) (result i32) + (local $y i32) + (loop $l + (local.set $x + (i32.add (local.get $y) (i32.const 1)) + ) + (local.set $y + (i32.div_s (local.get $x) (i32.const 3)) + ) + (br_if $l (local.get $y)) + ) + (call $import) + (return (local.get $y)) + ) + (func $calls-import2-if (param $x i32) + (if (local.get $x) + (call $import) + ) + ) + (func $calls-import2-if-else (param $x i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (call $import3 (i32.const 2)) + ) + ) + (func $calls-import2-if-else-oneside (param $x i32) (result i32) + (if (local.get $x) + (return (i32.const 1)) + (call $import3 (i32.const 2)) + ) + (return (i32.const 3)) + ) + (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (return (i32.const 2)) + ) + (return (i32.const 3)) + ) + (func $calls-loop (param $x i32) + (loop $l + (call $import3 (i32.const 1)) + (local.set $x + (i32.add (local.get $x) (i32.const 1)) + ) + (br_if $l + (local.get $x) + ) + ) + ) + (func $calls-loop2 + (loop $l + (br_if $l + (call $import2) + ) + ) + ) + (func $calls-mix + (call $boring) + (call $import) + (call $boring) + (call $import) + ) + (func $boring) + (func $calls-mix-deep + (call $boring-deep) + (call $import-deep) + (call $boring) + (call $import) + ) + (func $boring-deep + (call $boring) + ) + (func $import-deep + (call $import) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,195 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (table $0 1 funcref) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $foo + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $nothing) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call_indirect (type $none_=>_none) + (i32.const 0) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $bar + (call $nothing) + (call_indirect (type $none_=>_none) + (i32.const 0) + ) + ) + (func $nothing + (nop) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo_pass-arg=asyncify-ignore-indirect.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,18 @@ +(module + (type $t (func)) + (memory 1 2) + (table 1 funcref) + (elem (i32.const 0)) + (import "env" "import" (func $import)) + (func $foo ;; doesn't look like it needs instrumentation, but in add list + (call $nothing) + (call_indirect (type $t) (i32.const 0)) + ) + (func $bar ;; doesn't look like it needs instrumentation, and not in add list + (call $nothing) + (call_indirect (type $t) (i32.const 0)) + ) + (func $nothing + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,162 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $foo + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.tee $0 + (block $__asyncify_unwind + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $nothing) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $bar + (call $nothing) + ) + (func $nothing + (nop) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-addlist@foo.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-addlist@foo.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,13 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (func $foo ;; doesn't look like it needs instrumentation, but in add list + (call $nothing) + ) + (func $bar ;; doesn't look like it needs instrumentation, and not in add list + (call $nothing) + ) + (func $nothing + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,205 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (table $0 2 2 funcref) + (elem (i32.const 0) $calls-import2-drop $calls-import2-drop) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local.set $0 + (global.get $__asyncify_state) + ) + (block + (call $import) + (if + (i32.ne + (global.get $__asyncify_state) + (local.get $0) + ) + (unreachable) + ) + ) + ) + (func $calls-import2-drop + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (global.get $__asyncify_state) + ) + (block + (local.set $0 + (block (result i32) + (local.set $2 + (call $import2) + ) + (if + (i32.ne + (global.get $__asyncify_state) + (local.get $1) + ) + (unreachable) + ) + (local.get $2) + ) + ) + (drop + (local.get $0) + ) + ) + ) + (func $returns (result i32) + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local.set $5 + (global.get $__asyncify_state) + ) + (block + (block + (local.set $1 + (block (result i32) + (local.set $6 + (call $import2) + ) + (if + (i32.ne + (global.get $__asyncify_state) + (local.get $5) + ) + (unreachable) + ) + (local.get $6) + ) + ) + (local.set $x + (local.get $1) + ) + (local.set $2 + (local.get $x) + ) + (local.set $3 + (local.get $2) + ) + ) + (local.set $4 + (local.get $3) + ) + (return + (local.get $4) + ) + ) + ) + (func $calls-indirect (param $x i32) + (local $1 i32) + (local $2 i32) + (local.set $2 + (global.get $__asyncify_state) + ) + (block + (local.set $1 + (local.get $x) + ) + (block + (call_indirect (type $none_=>_none) + (local.get $1) + ) + (if + (i32.ne + (global.get $__asyncify_state) + (local.get $2) + ) + (unreachable) + ) + ) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-asserts_pass-arg=asyncify-onlylist@waka.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,25 @@ +(module + (memory 1 2) + (type $f (func)) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (table 1 1) + (func $calls-import + (call $import) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $returns (result i32) + (local $x i32) + (local.set $x (call $import2)) + (local.get $x) + ) + (func $calls-indirect (param $x i32) + (call_indirect (type $f) + (local.get $x) + ) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,270 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $foo + (call $import) + ) + (func $bar + (call $import) + ) + (func $baz + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $other1 + (call $foo) + ) + (func $other2 + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $baz) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-blacklist@foo,bar.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,20 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (func $foo + (call $import) + ) + (func $bar + (call $import) + ) + (func $baz + (call $import) + ) + (func $other1 + (call $foo) + ) + (func $other2 + (call $baz) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-imports.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,260 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (table $0 2 2 funcref) + (elem (i32.const 0) $calls-import2-drop $calls-import2-drop) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (call $import) + ) + (func $calls-import2-drop + (local $0 i32) + (local.set $0 + (call $import2) + ) + (drop + (local.get $0) + ) + ) + (func $calls-import2-if-else (param $x i32) + (local $1 i32) + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (call $import3 + (i32.const 1) + ) + (call $import3 + (i32.const 2) + ) + ) + ) + (func $calls-indirect (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $2 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $3 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $3) + (i32.const 0) + ) + ) + (block + (call_indirect (type $none_=>_none) + (local.get $1) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-imports.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-imports.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-imports.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-imports.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,26 @@ +(module + (memory 1 2) + (type $f (func)) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (table 1 1) + (func $calls-import + (call $import) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-import2-if-else (param $x i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (call $import3 (i32.const 2)) + ) + ) + (func $calls-indirect (param $x i32) + (call_indirect (type $f) + (local.get $x) + ) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,534 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (table $0 2 2 funcref) + (elem (i32.const 0) $calls-import2-drop $calls-import2-drop) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2-drop + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-import2-if-else (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $2 + (i32.load + (local.get $5) + ) + ) + ) + ) + (local.set $3 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $2 + (local.get $1) + ) + ) + (if + (i32.or + (local.get $2) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $4) + (i32.const 0) + ) + ) + (block + (call $import3 + (i32.const 1) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (if + (i32.or + (i32.eqz + (local.get $2) + ) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $4) + (i32.const 1) + ) + ) + (block + (call $import3 + (i32.const 2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $3) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $6) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-indirect (param $x i32) + (local $1 i32) + (local.set $1 + (local.get $x) + ) + (call_indirect (type $none_=>_none) + (local.get $1) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-ignore-indirect.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,26 @@ +(module + (memory 1 2) + (type $f (func)) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (table 1 1) + (func $calls-import + (call $import) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-import2-if-else (param $x i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (call $import3 (i32.const 2)) + ) + ) + (func $calls-indirect (param $x i32) + (call_indirect (type $f) + (local.get $x) + ) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1708 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (memory $0 1 2) + (global $sleeping (mut i32) (i32.const 0)) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $do_sleep + (local $0 i32) + (local $1 i32) + (local.set $0 + (global.get $sleeping) + ) + (local.set $1 + (i32.eqz + (local.get $0) + ) + ) + (if + (local.get $1) + (block $block + (global.set $sleeping + (i32.const 1) + ) + (call $asyncify_start_unwind + (i32.const 4) + ) + ) + (block $block0 + (global.set $sleeping + (i32.const 0) + ) + (call $asyncify_stop_rewind) + ) + ) + ) + (func $work + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $stuff) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $do_sleep) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $stuff) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $stuff + (nop) + ) + (func $first_event + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $work) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $second_event + (call $asyncify_start_rewind + (i32.const 4) + ) + (call $work) + ) + (func $never_sleep + (call $stuff) + (call $stuff) + (call $stuff) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $8 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (i32.load + (local.get $8) + ) + ) + ) + ) + (local.set $5 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $6 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $6) + (i32.const 0) + ) + ) + (block + (local.set $7 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $1 + (local.get $7) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $temp + (local.get $1) + ) + (local.set $2 + (local.get $temp) + ) + (return + (local.get $2) + ) + ) + ) + (nop) + (nop) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $5) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $9 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $9) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-import2-drop + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-nothing + (local $0 i32) + (local.set $0 + (i32.eqz + (i32.const 17) + ) + ) + (drop + (local.get $0) + ) + ) + (func $many-locals (param $x i32) (result i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $12 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $y + (i32.load + (local.get $12) + ) + ) + ) + ) + (local.set $10 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $11 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (loop $l + (local.set $2 + (local.get $y) + ) + (local.set $3 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (local.set $x + (local.get $3) + ) + (local.set $4 + (local.get $x) + ) + (local.set $5 + (i32.div_s + (local.get $4) + (i32.const 3) + ) + ) + (local.set $y + (local.get $5) + ) + (local.set $6 + (local.get $y) + ) + (br_if $l + (local.get $6) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $11) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $7 + (local.get $y) + ) + (return + (local.get $7) + ) + ) + ) + (nop) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $10) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $13 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $13) + (local.get $y) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (i32.const 0) + ) + (func $calls-import2-if (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $2 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $3 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + ) + (if + (i32.or + (local.get $1) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $3) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-import2-if-else (param $x i32) + (local $1 i32) + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (call $import3 + (i32.const 1) + ) + (call $import3 + (i32.const 2) + ) + ) + ) + (func $calls-import2-if-else-oneside (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (block + (block + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (return + (i32.const 1) + ) + (call $import3 + (i32.const 2) + ) + ) + ) + (return + (i32.const 3) + ) + ) + ) + (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (block + (block + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (call $import3 + (i32.const 1) + ) + (return + (i32.const 2) + ) + ) + ) + (return + (i32.const 3) + ) + ) + ) + (func $calls-loop (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (loop $l + (call $import3 + (i32.const 1) + ) + (local.set $1 + (local.get $x) + ) + (local.set $2 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $x + (local.get $2) + ) + (local.set $3 + (local.get $x) + ) + (br_if $l + (local.get $3) + ) + ) + ) + (func $calls-loop2 + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $1 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $2 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (loop $l + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $2) + (i32.const 0) + ) + ) + (block + (local.set $3 + (call $import2) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (br_if $l + (local.get $0) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $calls-mix + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 1) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $boring + (nop) + ) + (func $calls-mix-deep + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring-deep) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import-deep) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (call $boring) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 1) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $boring-deep + (call $boring) + ) + (func $import-deep + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-imports@env.import,env.import2.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,146 @@ +;; Pre-existing imports that the pass turns into the implementations. +(module + (memory 1 2) + (import "asyncify" "start_unwind" (func $asyncify_start_unwind (param i32))) + (import "asyncify" "start_rewind" (func $asyncify_start_rewind (param i32))) + (import "asyncify" "stop_rewind" (func $asyncify_stop_rewind)) + (global $sleeping (mut i32) (i32.const 0)) + ;; do a sleep operation: start a sleep if running, or resume after a sleep + ;; if we just rewound. + (func $do_sleep + (if + (i32.eqz (global.get $sleeping)) + (block + (global.set $sleeping (i32.const 1)) + ;; we should set up the data at address 4 around here + (call $asyncify_start_unwind (i32.const 4)) + ) + (block + (global.set $sleeping (i32.const 0)) + (call $asyncify_stop_rewind) + ) + ) + ) + ;; a function that does some work and has a sleep (async pause/resume) in the middle + (func $work + (call $stuff) ;; do some work + (call $do_sleep) ;; take a break + (call $stuff) ;; do some more work + ) + (func $stuff) + ;; the first event called from the main event loop: just call into $work + (func $first_event + (call $work) + ;; work will sleep, so we exit through here while it is paused + ) + ;; the second event called from the main event loop: to resume $work, + ;; initiate a rewind, and then do the call to start things back up + (func $second_event + (call $asyncify_start_rewind (i32.const 4)) + (call $work) + ) + ;; a function that can't do a sleep + (func $never_sleep + (call $stuff) + (call $stuff) + (call $stuff) + ) +) +;; Calls to imports that will call into asyncify themselves. +(module + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (result i32))) + (import "env" "import3" (func $import3 (param i32))) + (func $calls-import + (call $import) + ) + (func $calls-import2 (result i32) + (local $temp i32) + (local.set $temp (call $import2)) + (return (local.get $temp)) + ) + (func $calls-import2-drop + (drop (call $import2)) + ) + (func $calls-nothing + (drop (i32.eqz (i32.const 17))) + ) + (func $many-locals (param $x i32) (result i32) + (local $y i32) + (loop $l + (local.set $x + (i32.add (local.get $y) (i32.const 1)) + ) + (local.set $y + (i32.div_s (local.get $x) (i32.const 3)) + ) + (br_if $l (local.get $y)) + ) + (call $import) + (return (local.get $y)) + ) + (func $calls-import2-if (param $x i32) + (if (local.get $x) + (call $import) + ) + ) + (func $calls-import2-if-else (param $x i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (call $import3 (i32.const 2)) + ) + ) + (func $calls-import2-if-else-oneside (param $x i32) (result i32) + (if (local.get $x) + (return (i32.const 1)) + (call $import3 (i32.const 2)) + ) + (return (i32.const 3)) + ) + (func $calls-import2-if-else-oneside2 (param $x i32) (result i32) + (if (local.get $x) + (call $import3 (i32.const 1)) + (return (i32.const 2)) + ) + (return (i32.const 3)) + ) + (func $calls-loop (param $x i32) + (loop $l + (call $import3 (i32.const 1)) + (local.set $x + (i32.add (local.get $x) (i32.const 1)) + ) + (br_if $l + (local.get $x) + ) + ) + ) + (func $calls-loop2 + (loop $l + (br_if $l + (call $import2) + ) + ) + ) + (func $calls-mix + (call $boring) + (call $import) + (call $boring) + (call $import) + ) + (func $boring) + (func $calls-mix-deep + (call $boring-deep) + (call $import-deep) + (call $boring) + (call $import) + ) + (func $boring-deep + (call $boring) + ) + (func $import-deep + (call $import) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,270 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $foo + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $bar + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $baz + (call $import) + ) + (func $other1 + (call $foo) + ) + (func $other2 + (call $baz) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-onlylist@foo,bar.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,20 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (func $foo + (call $import) + ) + (func $bar + (call $import) + ) + (func $baz + (call $import) + ) + (func $other1 + (call $foo) ;; even though we call foo, we are not in the only list, so do not instrument us + ) + (func $other2 + (call $baz) + ) +) + diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-verbose.txt binaryen-99/test/passes/asyncify_pass-arg=asyncify-verbose.txt --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-verbose.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-verbose.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,355 @@ +[asyncify] import is an import that can change the state +[asyncify] calls-import can change the state due to import +[asyncify] calls-calls-import can change the state due to calls-import +[asyncify] calls-calls-calls-import can change the state due to calls-calls-import +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (memory $0 1 2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $calls-import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $calls-calls-calls-import + (local $0 i32) + (local $1 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $0 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $1 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $1) + (i32.const 0) + ) + ) + (block + (call $calls-calls-import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $nothing + (nop) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify_pass-arg=asyncify-verbose.wast binaryen-99/test/passes/asyncify_pass-arg=asyncify-verbose.wast --- binaryen-108/test/passes/asyncify_pass-arg=asyncify-verbose.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify_pass-arg=asyncify-verbose.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,17 @@ +(module + (memory 1 2) + (import "env" "import" (func $import)) + (func $calls-import + (call $import) + ) + (func $calls-calls-import + (call $calls-import) + ) + (func $calls-calls-calls-import + (call $calls-calls-import) + ) + (func $nothing + (nop) + ) +) + diff -Nru binaryen-108/test/passes/asyncify.txt binaryen-99/test/passes/asyncify.txt --- binaryen-108/test/passes/asyncify.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1261 @@ +(module + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (param i32))) + (memory $0 1 2) + (table $0 2 2 funcref) + (elem (i32.const 0) $liveness2 $liveness2) + (global $__asyncify_state (mut i32) (i32.const 0)) + (global $__asyncify_data (mut i32) (i32.const 0)) + (export "asyncify_start_unwind" (func $asyncify_start_unwind)) + (export "asyncify_stop_unwind" (func $asyncify_stop_unwind)) + (export "asyncify_start_rewind" (func $asyncify_start_rewind)) + (export "asyncify_stop_rewind" (func $asyncify_stop_rewind)) + (export "asyncify_get_state" (func $asyncify_get_state)) + (func $liveness1 (param $live0 i32) (param $dead0 i32) + (local $live1 i32) + (local $dead1 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -8) + ) + ) + (local.set $10 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $live0 + (i32.load + (local.get $10) + ) + ) + (local.set $live1 + (i32.load offset=4 + (local.get $10) + ) + ) + ) + ) + (local.set $8 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $9 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $4 + (local.get $dead0) + ) + (drop + (local.get $4) + ) + (local.set $5 + (local.get $dead1) + ) + (drop + (local.get $5) + ) + ) + ) + (nop) + (nop) + (nop) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $9) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $6 + (local.get $live0) + ) + (drop + (local.get $6) + ) + (local.set $7 + (local.get $live1) + ) + (drop + (local.get $7) + ) + ) + ) + (nop) + (nop) + (nop) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $8) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $11 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $11) + (local.get $live0) + ) + (i32.store offset=4 + (local.get $11) + (local.get $live1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 8) + ) + ) + ) + ) + (func $liveness2 (param $live0 i32) (param $dead0 i32) + (local $live1 i32) + (local $dead1 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -8) + ) + ) + (local.set $10 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $live0 + (i32.load + (local.get $10) + ) + ) + (local.set $live1 + (i32.load offset=4 + (local.get $10) + ) + ) + ) + ) + (local.set $8 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $9 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $4 + (local.get $dead0) + ) + (drop + (local.get $4) + ) + (local.set $5 + (local.get $dead1) + ) + (drop + (local.get $5) + ) + ) + ) + (nop) + (nop) + (nop) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $9) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $6 + (local.get $live0) + ) + (drop + (local.get $6) + ) + (local.set $7 + (local.get $live1) + ) + (drop + (local.get $7) + ) + ) + ) + (nop) + (nop) + (nop) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $8) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $11 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $11) + (local.get $live0) + ) + (i32.store offset=4 + (local.get $11) + (local.get $live1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 8) + ) + ) + ) + ) + (func $liveness3 (param $live0 i32) (param $dead0 i32) + (local $live1 i32) + (local $dead1 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -8) + ) + ) + (local.set $8 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $live0 + (i32.load + (local.get $8) + ) + ) + (local.set $live1 + (i32.load offset=4 + (local.get $8) + ) + ) + ) + ) + (local.set $6 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $7 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $7) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $4 + (local.get $live0) + ) + (drop + (local.get $4) + ) + ) + ) + (nop) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $7) + (i32.const 1) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 1) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $5 + (local.get $live1) + ) + (drop + (local.get $5) + ) + ) + ) + (nop) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $6) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $9 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $9) + (local.get $live0) + ) + (i32.store offset=4 + (local.get $9) + (local.get $live1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 8) + ) + ) + ) + ) + (func $liveness4 (param $live0 i32) (param $dead0 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $live0 + (i32.load + (local.get $5) + ) + ) + ) + ) + (local.set $3 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.or + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $4) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $2 + (local.get $live0) + ) + (drop + (local.get $2) + ) + ) + ) + (nop) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $3) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $6) + (local.get $live0) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $liveness5 (param $dead0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (nop) + ) + (local.set $3 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $1 + (local.get $dead0) + ) + (drop + (local.get $1) + ) + ) + ) + (nop) + (if + (i32.or + (i32.const 0) + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $4) + (i32.const 0) + ) + ) + (block + (call $import) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $dead0 + (i32.const 1) + ) + (local.set $2 + (local.get $dead0) + ) + (drop + (local.get $2) + ) + ) + ) + (nop) + (nop) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $3) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (nop) + ) + (func $liveness-call-kills (param $live i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $4 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $1 + (i32.load + (local.get $4) + ) + ) + ) + ) + (local.set $2 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $3 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (local.set $1 + (local.get $live) + ) + ) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $3) + (i32.const 0) + ) + ) + (block + (call $import2 + (local.get $1) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $2) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $5 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $5) + (local.get $1) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + ) + (func $liveness-indirect-kills (param $live0 i32) (param $live1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -8) + ) + ) + (local.set $6 + (i32.load + (global.get $__asyncify_data) + ) + ) + (local.set $2 + (i32.load + (local.get $6) + ) + ) + (local.set $3 + (i32.load offset=4 + (local.get $6) + ) + ) + ) + ) + (local.set $4 + (block $__asyncify_unwind (result i32) + (block + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 2) + ) + (block + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const -4) + ) + ) + (local.set $5 + (i32.load + (i32.load + (global.get $__asyncify_data) + ) + ) + ) + ) + ) + (block + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (block + (local.set $2 + (local.get $live0) + ) + (local.set $3 + (local.get $live1) + ) + ) + ) + (nop) + (if + (if (result i32) + (i32.eq + (global.get $__asyncify_state) + (i32.const 0) + ) + (i32.const 1) + (i32.eq + (local.get $5) + (i32.const 0) + ) + ) + (block + (call_indirect (type $i32_=>_none) + (local.get $2) + (local.get $3) + ) + (if + (i32.eq + (global.get $__asyncify_state) + (i32.const 1) + ) + (br $__asyncify_unwind + (i32.const 0) + ) + ) + ) + ) + ) + ) + (return) + ) + ) + ) + (block + (i32.store + (i32.load + (global.get $__asyncify_data) + ) + (local.get $4) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 4) + ) + ) + ) + (block + (local.set $7 + (i32.load + (global.get $__asyncify_data) + ) + ) + (i32.store + (local.get $7) + (local.get $2) + ) + (i32.store offset=4 + (local.get $7) + (local.get $3) + ) + (i32.store + (global.get $__asyncify_data) + (i32.add + (i32.load + (global.get $__asyncify_data) + ) + (i32.const 8) + ) + ) + ) + ) + (func $asyncify_start_unwind (param $0 i32) + (global.set $__asyncify_state + (i32.const 1) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_unwind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_start_rewind (param $0 i32) + (global.set $__asyncify_state + (i32.const 2) + ) + (global.set $__asyncify_data + (local.get $0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_stop_rewind + (global.set $__asyncify_state + (i32.const 0) + ) + (if + (i32.gt_u + (i32.load + (global.get $__asyncify_data) + ) + (i32.load offset=4 + (global.get $__asyncify_data) + ) + ) + (unreachable) + ) + ) + (func $asyncify_get_state (result i32) + (global.get $__asyncify_state) + ) +) diff -Nru binaryen-108/test/passes/asyncify.wast binaryen-99/test/passes/asyncify.wast --- binaryen-108/test/passes/asyncify.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/asyncify.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,53 @@ +(module + (type $f (func (param i32))) + (memory 1 2) + (import "env" "import" (func $import)) + (import "env" "import2" (func $import2 (param i32))) + (table 1 1) + (func $liveness1 (param $live0 i32) (param $dead0 i32) + (local $live1 i32) + (local $dead1 i32) + (drop (local.get $dead0)) + (drop (local.get $dead1)) + (call $import) + (drop (local.get $live0)) + (drop (local.get $live1)) + ) + (func $liveness2 (param $live0 i32) (param $dead0 i32) + (local $live1 i32) + (local $dead1 i32) + (drop (local.get $dead0)) + (drop (local.get $dead1)) + (call $import) + (drop (local.get $live0)) + (drop (local.get $live1)) + ) + (func $liveness3 (param $live0 i32) (param $dead0 i32) + (local $live1 i32) + (local $dead1 i32) + (call $import) + (drop (local.get $live0)) + (call $import) + (drop (local.get $live1)) + ) + (func $liveness4 (param $live0 i32) (param $dead0 i32) + (if (i32.const 0) + (call $import) + ) + (drop (local.get $live0)) + ) + (func $liveness5 (param $dead0 i32) + (drop (local.get $dead0)) + (if (i32.const 0) + (call $import) ;; live before and after call, but not during + ) + (local.set $dead0 (i32.const 1)) + (drop (local.get $dead0)) + ) + (func $liveness-call-kills (param $live i32) + (call $import2 (local.get $live)) + ) + (func $liveness-indirect-kills (param $live0 i32) (param $live1 i32) + (call_indirect (type $f) (local.get $live0) (local.get $live1)) + ) +) diff -Nru binaryen-108/test/passes/avoid-reinterprets64.passes binaryen-99/test/passes/avoid-reinterprets64.passes --- binaryen-108/test/passes/avoid-reinterprets64.passes 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/avoid-reinterprets64.passes 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +avoid-reinterprets_enable-memory64 diff -Nru binaryen-108/test/passes/avoid-reinterprets64.txt binaryen-99/test/passes/avoid-reinterprets64.txt --- binaryen-108/test/passes/avoid-reinterprets64.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/avoid-reinterprets64.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,182 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_f32 (func (result f32))) + (memory $0 i64 1) + (func $simple + (drop + (f32.load + (i64.const 1024) + ) + ) + (drop + (i32.load + (i64.const 1024) + ) + ) + (drop + (f64.load + (i64.const 1024) + ) + ) + (drop + (i64.load + (i64.const 1024) + ) + ) + ) + (func $one + (local $x i32) + (local $1 i64) + (local $2 f32) + (local.set $x + (block (result i32) + (local.set $1 + (i64.const 1024) + ) + (local.set $2 + (f32.load + (local.get $1) + ) + ) + (i32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $2) + ) + ) + (func $one-b + (local $x f32) + (local $1 i64) + (local $2 i32) + (local.set $x + (block (result f32) + (local.set $1 + (i64.const 1024) + ) + (local.set $2 + (i32.load + (local.get $1) + ) + ) + (f32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $2) + ) + ) + (func $both + (local $x i32) + (local $1 i64) + (local $2 f32) + (local.set $x + (block (result i32) + (local.set $1 + (i64.const 1024) + ) + (local.set $2 + (f32.load + (local.get $1) + ) + ) + (i32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $2) + ) + (drop + (local.get $2) + ) + ) + (func $half + (local $x i32) + (local $1 i64) + (local $2 f32) + (local.set $x + (block (result i32) + (local.set $1 + (i64.const 1024) + ) + (local.set $2 + (f32.load + (local.get $1) + ) + ) + (i32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $2) + ) + ) + (func $copy + (local $x i32) + (local $y i32) + (local $2 i64) + (local $3 f32) + (local.set $x + (block (result i32) + (local.set $2 + (i64.const 1024) + ) + (local.set $3 + (f32.load + (local.get $2) + ) + ) + (i32.load + (local.get $2) + ) + ) + ) + (local.set $y + (local.get $x) + ) + (drop + (local.get $3) + ) + ) + (func $partial1 (result f32) + (f32.reinterpret_i32 + (i32.load16_u + (i64.const 3) + ) + ) + ) + (func $partial2 (result f32) + (f32.reinterpret_i32 + (i32.load8_u + (i64.const 3) + ) + ) + ) + (func $nofallthrough + (local $x i32) + (local.set $x + (i32.load + (i64.const 1024) + ) + ) + (drop + (f32.reinterpret_i32 + (block $block (result i32) + (nop) + (local.get $x) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/avoid-reinterprets64.wast binaryen-99/test/passes/avoid-reinterprets64.wast --- binaryen-108/test/passes/avoid-reinterprets64.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/avoid-reinterprets64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,69 @@ +(module + (memory i64 1) + (func $simple + (drop (f32.reinterpret_i32 (i32.load (i64.const 1024)))) + (drop (i32.reinterpret_f32 (f32.load (i64.const 1024)))) + (drop (f64.reinterpret_i64 (i64.load (i64.const 1024)))) + (drop (i64.reinterpret_f64 (f64.load (i64.const 1024)))) + ) + (func $one + (local $x i32) + (local.set $x (i32.load (i64.const 1024))) + (drop (f32.reinterpret_i32 (local.get $x))) + ) + (func $one-b + (local $x f32) + (local.set $x (f32.load (i64.const 1024))) + (drop (i32.reinterpret_f32 (local.get $x))) + ) + (func $both + (local $x i32) + (local.set $x (i32.load (i64.const 1024))) + (drop (f32.reinterpret_i32 (local.get $x))) + (drop (f32.reinterpret_i32 (local.get $x))) + ) + (func $half + (local $x i32) + (local.set $x (i32.load (i64.const 1024))) + (drop (local.get $x)) + (drop (f32.reinterpret_i32 (local.get $x))) + ) + (func $copy + (local $x i32) + (local $y i32) + (local.set $x (i32.load (i64.const 1024))) + (local.set $y (local.get $x)) + (drop (f32.reinterpret_i32 (local.get $y))) + ) + (func $partial1 (result f32) + (f32.reinterpret_i32 + (i32.load16_u + (i64.const 3) + ) + ) + ) + (func $partial2 (result f32) + (f32.reinterpret_i32 + (i32.load8_u + (i64.const 3) + ) + ) + ) + (func $nofallthrough + (local $x i32) + (local.set $x + (i32.load + (i64.const 1024) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (nop) ;; this would be removed by other opts, but in general, we can't + ;; just look at the fallthrough, as we can't just remove code here + (local.get $x) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/avoid-reinterprets.txt binaryen-99/test/passes/avoid-reinterprets.txt --- binaryen-108/test/passes/avoid-reinterprets.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/avoid-reinterprets.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,182 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_f32 (func (result f32))) + (memory $0 1) + (func $simple + (drop + (f32.load + (i32.const 1024) + ) + ) + (drop + (i32.load + (i32.const 1024) + ) + ) + (drop + (f64.load + (i32.const 1024) + ) + ) + (drop + (i64.load + (i32.const 1024) + ) + ) + ) + (func $one + (local $x i32) + (local $1 i32) + (local $2 f32) + (local.set $x + (block (result i32) + (local.set $1 + (i32.const 1024) + ) + (local.set $2 + (f32.load + (local.get $1) + ) + ) + (i32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $2) + ) + ) + (func $one-b + (local $x f32) + (local $1 i32) + (local $2 i32) + (local.set $x + (block (result f32) + (local.set $1 + (i32.const 1024) + ) + (local.set $2 + (i32.load + (local.get $1) + ) + ) + (f32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $2) + ) + ) + (func $both + (local $x i32) + (local $1 i32) + (local $2 f32) + (local.set $x + (block (result i32) + (local.set $1 + (i32.const 1024) + ) + (local.set $2 + (f32.load + (local.get $1) + ) + ) + (i32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $2) + ) + (drop + (local.get $2) + ) + ) + (func $half + (local $x i32) + (local $1 i32) + (local $2 f32) + (local.set $x + (block (result i32) + (local.set $1 + (i32.const 1024) + ) + (local.set $2 + (f32.load + (local.get $1) + ) + ) + (i32.load + (local.get $1) + ) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $2) + ) + ) + (func $copy + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 f32) + (local.set $x + (block (result i32) + (local.set $2 + (i32.const 1024) + ) + (local.set $3 + (f32.load + (local.get $2) + ) + ) + (i32.load + (local.get $2) + ) + ) + ) + (local.set $y + (local.get $x) + ) + (drop + (local.get $3) + ) + ) + (func $partial1 (result f32) + (f32.reinterpret_i32 + (i32.load16_u + (i32.const 3) + ) + ) + ) + (func $partial2 (result f32) + (f32.reinterpret_i32 + (i32.load8_u + (i32.const 3) + ) + ) + ) + (func $nofallthrough + (local $x i32) + (local.set $x + (i32.load + (i32.const 1024) + ) + ) + (drop + (f32.reinterpret_i32 + (block $block (result i32) + (nop) + (local.get $x) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/avoid-reinterprets.wast binaryen-99/test/passes/avoid-reinterprets.wast --- binaryen-108/test/passes/avoid-reinterprets.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/avoid-reinterprets.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,69 @@ +(module + (memory 1) + (func $simple + (drop (f32.reinterpret_i32 (i32.load (i32.const 1024)))) + (drop (i32.reinterpret_f32 (f32.load (i32.const 1024)))) + (drop (f64.reinterpret_i64 (i64.load (i32.const 1024)))) + (drop (i64.reinterpret_f64 (f64.load (i32.const 1024)))) + ) + (func $one + (local $x i32) + (local.set $x (i32.load (i32.const 1024))) + (drop (f32.reinterpret_i32 (local.get $x))) + ) + (func $one-b + (local $x f32) + (local.set $x (f32.load (i32.const 1024))) + (drop (i32.reinterpret_f32 (local.get $x))) + ) + (func $both + (local $x i32) + (local.set $x (i32.load (i32.const 1024))) + (drop (f32.reinterpret_i32 (local.get $x))) + (drop (f32.reinterpret_i32 (local.get $x))) + ) + (func $half + (local $x i32) + (local.set $x (i32.load (i32.const 1024))) + (drop (local.get $x)) + (drop (f32.reinterpret_i32 (local.get $x))) + ) + (func $copy + (local $x i32) + (local $y i32) + (local.set $x (i32.load (i32.const 1024))) + (local.set $y (local.get $x)) + (drop (f32.reinterpret_i32 (local.get $y))) + ) + (func $partial1 (result f32) + (f32.reinterpret_i32 + (i32.load16_u + (i32.const 3) + ) + ) + ) + (func $partial2 (result f32) + (f32.reinterpret_i32 + (i32.load8_u + (i32.const 3) + ) + ) + ) + (func $nofallthrough + (local $x i32) + (local.set $x + (i32.load + (i32.const 1024) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (nop) ;; this would be removed by other opts, but in general, we can't + ;; just look at the fallthrough, as we can't just remove code here + (local.get $x) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/coalesce-locals-learning.txt binaryen-99/test/passes/coalesce-locals-learning.txt --- binaryen-108/test/passes/coalesce-locals-learning.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/coalesce-locals-learning.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,868 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_f32_=>_none (func (param i32 f32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (import "env" "_emscripten_autodebug_i32" (func $_emscripten_autodebug_i32 (param i32 i32) (result i32))) + (memory $0 10) + (func $nothing-to-do + (local $0 i32) + (nop) + ) + (func $merge + (local $0 i32) + (nop) + ) + (func $leave-type + (local $0 i32) + (local $1 f32) + (nop) + ) + (func $leave-interfere + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $almost-interfere + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + (func $redundant-copy + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (nop) + (drop + (local.get $0) + ) + ) + (func $ineffective-store + (local $0 i32) + (drop + (i32.const 0) + ) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + (func $block + (local $0 i32) + (block $block0 + (local.set $0 + (i32.const 0) + ) + ) + (drop + (local.get $0) + ) + ) + (func $see-both-sides + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (block $block0 + (local.set $1 + (i32.const 0) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $see-br-and-ignore-dead + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (block $block + (br $block) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const -1) + ) + ) + (drop + (local.get $0) + ) + ) + (func $see-block-body + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (block $block + (local.set $1 + (i32.const 0) + ) + (drop + (local.get $1) + ) + (br $block) + ) + (drop + (local.get $0) + ) + ) + (func $zero-init + (local $0 i32) + (local $1 i32) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $multi + (local $0 i32) + (local $1 i32) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-else + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (func $if-else-parallel + (local $0 i32) + (if + (i32.const 0) + (block $block1 + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + (block $block3 + (local.set $0 + (i32.const 1) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (func $if-else-after + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-else-through + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-through + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-through2 + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (if + (i32.const 0) + (local.set $1 + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-through3 + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (func $if2 + (local $0 i32) + (local $1 i32) + (if + (local.tee $0 + (i32.const 0) + ) + (block $block1 + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (func $if3 + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (block $block1 + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + (drop + (local.get $1) + ) + ) + (func $if4 + (local $0 i32) + (if + (i32.const 0) + (block $block1 + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + (local.set $0 + (i32.const 1) + ) + ) + ) + (drop + (local.get $0) + ) + ) + (func $if5 + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $0) + ) + (local.set $1 + (i32.const 1) + ) + ) + ) + (drop + (local.get $1) + ) + ) + (func $loop + (local $0 i32) + (local $1 i32) + (block $out + (loop $in + (drop + (local.get $0) + ) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $1) + ) + (br $in) + ) + ) + ) + (func $interfere-in-dead + (local $0 i32) + (block $block + (br $block) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $interfere-in-dead2 + (local $0 i32) + (block $block + (unreachable) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $interfere-in-dead3 + (local $0 i32) + (block $block + (return) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $params (param $0 i32) (param $1 f32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (drop + (local.get $2) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + ) + (func $interfere-in-dead4 + (local $0 i32) + (local $1 i32) + (block $block + (br_if $block + (i32.const 0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (func $switch + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block $switch$def + (block $switch-case$1 + (block $switch-case$2 + (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def + (i32.const 100) + ) + (drop + (i32.const 0) + ) + ) + (drop + (local.get $0) + ) + ) + (drop + (local.get $1) + ) + ) + (drop + (local.get $2) + ) + ) + (func $greedy-can-be-happy + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $0 + (i32.const 100) + ) + (local.set $1 + (i32.const 101) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block5 + (local.set $0 + (i32.const 102) + ) + (local.set $1 + (i32.const 103) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $0 + (i32.const 104) + ) + (local.set $1 + (i32.const 105) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block10 + (local.set $0 + (i32.const 106) + ) + (local.set $1 + (i32.const 107) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $0 + (i32.const 108) + ) + (local.set $1 + (i32.const 109) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block15 + (local.set $0 + (i32.const 110) + ) + (local.set $1 + (i32.const 111) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + ) + (func $greedy-can-be-sad + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $0 + (i32.const 100) + ) + (local.set $1 + (i32.const 101) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block5 + (local.set $0 + (i32.const 102) + ) + (local.set $1 + (i32.const 103) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $0 + (i32.const 104) + ) + (local.set $1 + (i32.const 105) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block10 + (local.set $0 + (i32.const 106) + ) + (local.set $1 + (i32.const 107) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $0 + (i32.const 108) + ) + (local.set $1 + (i32.const 109) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block15 + (local.set $0 + (i32.const 110) + ) + (local.set $1 + (i32.const 111) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + ) + (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (i32.ge_s + (local.get $2) + (i32.const 4096) + ) + (drop + (local.get $0) + ) + ) + (local.set $3 + (local.get $0) + ) + (if + (i32.eq + (i32.and + (local.get $0) + (i32.const 3) + ) + (i32.and + (local.get $1) + (i32.const 3) + ) + ) + (block $block2 + (block $while-out$0 + (loop $while-in$1 + (if + (i32.eqz + (i32.and + (local.get $0) + (i32.const 3) + ) + ) + (br $while-out$0) + ) + (block $block4 + (if + (i32.eqz + (local.get $2) + ) + (return + (local.get $3) + ) + ) + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + ) + (br $while-in$1) + ) + ) + (block $while-out$2 + (loop $while-in$3 + (if + (i32.eqz + (i32.ge_s + (local.get $2) + (i32.const 4) + ) + ) + (br $while-out$2) + ) + (block $block7 + (i32.store + (local.get $0) + (i32.load + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 4) + ) + ) + ) + (br $while-in$3) + ) + ) + ) + ) + (block $while-out$4 + (loop $while-in$5 + (if + (i32.eqz + (i32.gt_s + (local.get $2) + (i32.const 0) + ) + ) + (br $while-out$4) + ) + (block $block9 + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + ) + (br $while-in$5) + ) + ) + (return + (local.get $3) + ) + ) + (func $this-is-effective-i-tell-you (param $0 i32) + (if + (i32.const -1) + (block $block1 + (if + (i32.const 0) + (nop) + ) + (local.set $0 + (i32.const 1) + ) + ) + (nop) + ) + (drop + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/coalesce-locals-learning.wast binaryen-99/test/passes/coalesce-locals-learning.wast --- binaryen-108/test/passes/coalesce-locals-learning.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/coalesce-locals-learning.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,890 @@ +(module + (memory 10) + (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $2 (func)) + (type $3 (func (param i32 f32))) + (type $4 (func (param i32))) + (import $_emscripten_autodebug_i32 "env" "_emscripten_autodebug_i32" (param i32 i32) (result i32)) + (func $nothing-to-do (type $2) + (local $x i32) + (nop) + ) + (func $merge (type $2) + (local $x i32) + (local $y i32) + (nop) + ) + (func $leave-type (type $2) + (local $x i32) + (local $y f32) + (nop) + ) + (func $leave-interfere (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 0) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $almost-interfere (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.const 0) + ) + (drop + (local.get $y) + ) + ) + (func $redundant-copy (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $ineffective-store (type $2) + (local $x i32) + (local.set $x + (i32.const 0) + ) + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + ) + (func $block (type $2) + (local $x i32) + (block $block0 + (local.set $x + (i32.const 0) + ) + ) + (drop + (local.get $x) + ) + ) + (func $see-both-sides (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (block $block0 + (local.set $y + (i32.const 0) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $see-br-and-ignore-dead (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (block $block + (br $block) + (local.set $y + (i32.const 0) + ) + (drop + (local.get $y) + ) + (local.set $x + (i32.const -1) + ) + ) + (drop + (local.get $x) + ) + ) + (func $see-block-body (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (block $block + (local.set $y + (i32.const 0) + ) + (drop + (local.get $y) + ) + (br $block) + ) + (drop + (local.get $x) + ) + ) + (func $zero-init (type $2) + (local $x i32) + (local $y i32) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $multi (type $2) + (local $x i32) + (local $y i32) + (local $z i32) + (drop + (local.get $y) + ) + (drop + (local.get $z) + ) + ) + (func $if-else (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $if-else-parallel (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + ) + (block $block3 + (local.set $y + (i32.const 1) + ) + (drop + (local.get $y) + ) + ) + ) + ) + (func $if-else-after (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 1) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-else-through (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-through (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-through2 (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (if + (i32.const 0) + (local.set $y + (i32.const 1) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-through3 (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + ) + (func $if2 (type $2) + (local $x i32) + (local $y i32) + (if + (local.tee $x + (i32.const 0) + ) + (block $block1 + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + ) + (func $if3 (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + ) + ) + (drop + (local.get $y) + ) + ) + (func $if4 (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.const 1) + ) + ) + ) + (drop + (local.get $y) + ) + ) + (func $if5 (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $x) + ) + (local.set $y + (i32.const 1) + ) + ) + ) + (drop + (local.get $y) + ) + ) + (func $loop (type $2) + (local $x i32) + (local $y i32) + (block $out + (loop $in + (drop + (local.get $x) + ) + (local.set $x + (i32.const 0) + ) + (drop + (local.get $y) + ) + (br $in) + ) + ) + ) + (func $interfere-in-dead (type $2) + (local $x i32) + (local $y i32) + (block $block + (br $block) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $interfere-in-dead2 (type $2) + (local $x i32) + (local $y i32) + (block $block + (unreachable) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $interfere-in-dead3 (type $2) + (local $x i32) + (local $y i32) + (block $block + (return) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $params (type $3) (param $p i32) (param $q f32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (drop + (local.get $y) + ) + (drop + (local.get $z) + ) + (drop + (local.get $w) + ) + ) + (func $interfere-in-dead4 (type $2) + (local $x i32) + (local $y i32) + (block $block + (br_if $block + (i32.const 0) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $switch (type $2) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (block $switch$def + (block $switch-case$1 + (block $switch-case$2 + (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def + (i32.const 100) + ) + (drop + (local.get $x) + ) + ) + (drop + (local.get $y) + ) + ) + (drop + (local.get $z) + ) + ) + (drop + (local.get $w) + ) + ) + (func $greedy-can-be-happy (type $2) + (local $x1 i32) + (local $x2 i32) + (local $x3 i32) + (local $y1 i32) + (local $y2 i32) + (local $y3 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $x1 + (i32.const 100) + ) + (local.set $y2 + (i32.const 101) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y2) + ) + ) + (block $block5 + (local.set $x1 + (i32.const 102) + ) + (local.set $y3 + (i32.const 103) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y3) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $x2 + (i32.const 104) + ) + (local.set $y1 + (i32.const 105) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y1) + ) + ) + (block $block10 + (local.set $x2 + (i32.const 106) + ) + (local.set $y3 + (i32.const 107) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y3) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $x3 + (i32.const 108) + ) + (local.set $y1 + (i32.const 109) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y1) + ) + ) + (block $block15 + (local.set $x3 + (i32.const 110) + ) + (local.set $y2 + (i32.const 111) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y2) + ) + ) + ) + ) + ) + (func $greedy-can-be-sad (type $2) + (local $x1 i32) + (local $y1 i32) + (local $x2 i32) + (local $y2 i32) + (local $x3 i32) + (local $y3 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $x1 + (i32.const 100) + ) + (local.set $y2 + (i32.const 101) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y2) + ) + ) + (block $block5 + (local.set $x1 + (i32.const 102) + ) + (local.set $y3 + (i32.const 103) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y3) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $x2 + (i32.const 104) + ) + (local.set $y1 + (i32.const 105) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y1) + ) + ) + (block $block10 + (local.set $x2 + (i32.const 106) + ) + (local.set $y3 + (i32.const 107) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y3) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $x3 + (i32.const 108) + ) + (local.set $y1 + (i32.const 109) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y1) + ) + ) + (block $block15 + (local.set $x3 + (i32.const 110) + ) + (local.set $y2 + (i32.const 111) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y2) + ) + ) + ) + ) + ) + (func $_memcpy (type $FUNCSIG$iiii) (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32) + (local $i4 i32) + (if + (i32.ge_s + (local.get $i3) + (i32.const 4096) + ) + (drop + (local.get $i1) + ) + ) + (local.set $i4 + (local.get $i1) + ) + (if + (i32.eq + (i32.and + (local.get $i1) + (i32.const 3) + ) + (i32.and + (local.get $i2) + (i32.const 3) + ) + ) + (block $block2 + (block $while-out$0 + (loop $while-in$1 + (if + (i32.eqz + (i32.and + (local.get $i1) + (i32.const 3) + ) + ) + (br $while-out$0) + ) + (block $block4 + (if + (i32.eqz + (local.get $i3) + ) + (return + (local.get $i4) + ) + ) + (i32.store8 + (local.get $i1) + (i32.load8_s + (local.get $i2) + ) + ) + (local.set $i1 + (i32.add + (local.get $i1) + (i32.const 1) + ) + ) + (local.set $i2 + (i32.add + (local.get $i2) + (i32.const 1) + ) + ) + (local.set $i3 + (i32.sub + (local.get $i3) + (i32.const 1) + ) + ) + ) + (br $while-in$1) + ) + ) + (block $while-out$2 + (loop $while-in$3 + (if + (i32.eqz + (i32.ge_s + (local.get $i3) + (i32.const 4) + ) + ) + (br $while-out$2) + ) + (block $block7 + (i32.store + (local.get $i1) + (i32.load + (local.get $i2) + ) + ) + (local.set $i1 + (i32.add + (local.get $i1) + (i32.const 4) + ) + ) + (local.set $i2 + (i32.add + (local.get $i2) + (i32.const 4) + ) + ) + (local.set $i3 + (i32.sub + (local.get $i3) + (i32.const 4) + ) + ) + ) + (br $while-in$3) + ) + ) + ) + ) + (block $while-out$4 + (loop $while-in$5 + (if + (i32.eqz + (i32.gt_s + (local.get $i3) + (i32.const 0) + ) + ) + (br $while-out$4) + ) + (block $block9 + (i32.store8 + (local.get $i1) + (i32.load8_s + (local.get $i2) + ) + ) + (local.set $i1 + (i32.add + (local.get $i1) + (i32.const 1) + ) + ) + (local.set $i2 + (i32.add + (local.get $i2) + (i32.const 1) + ) + ) + (local.set $i3 + (i32.sub + (local.get $i3) + (i32.const 1) + ) + ) + ) + (br $while-in$5) + ) + ) + (return + (local.get $i4) + ) + ) + (func $this-is-effective-i-tell-you (type $4) (param $x i32) + (if + (i32.const -1) + (block $block1 + (if + (i32.const 0) + (nop) + ) + (local.set $x + (i32.const 1) + ) + ) + (nop) + ) + (drop + (local.get $x) + ) + ) +) diff -Nru binaryen-108/test/passes/coalesce-locals.txt binaryen-99/test/passes/coalesce-locals.txt --- binaryen-108/test/passes/coalesce-locals.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/coalesce-locals.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1270 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $f64_i32_=>_i64 (func (param f64 i32) (result i64))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_f32_=>_none (func (param i32 f32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $none_=>_f64 (func (result f64))) + (import "env" "_emscripten_autodebug_i32" (func $_emscripten_autodebug_i32 (param i32 i32) (result i32))) + (import "env" "get" (func $get (result i32))) + (import "env" "set" (func $set (param i32))) + (memory $0 10) + (func $nothing-to-do + (local $0 i32) + (nop) + ) + (func $merge + (local $0 i32) + (nop) + ) + (func $leave-type + (local $0 i32) + (local $1 f32) + (nop) + ) + (func $leave-interfere + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $almost-interfere + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + (func $redundant-copy + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (nop) + (drop + (local.get $0) + ) + ) + (func $ineffective-store + (local $0 i32) + (drop + (i32.const 0) + ) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + (func $block + (local $0 i32) + (block $block0 + (local.set $0 + (i32.const 0) + ) + ) + (drop + (local.get $0) + ) + ) + (func $see-both-sides + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (block $block0 + (local.set $1 + (i32.const 0) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $see-br-and-ignore-dead + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (block $block + (br $block) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const -1) + ) + ) + (drop + (local.get $0) + ) + ) + (func $see-block-body + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (block $block + (local.set $1 + (i32.const 0) + ) + (drop + (local.get $1) + ) + (br $block) + ) + (drop + (local.get $0) + ) + ) + (func $zero-init + (local $0 i32) + (local $1 i32) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $multi + (local $0 i32) + (local $1 i32) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-else + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (func $if-else-parallel + (local $0 i32) + (if + (i32.const 0) + (block $block1 + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + (block $block3 + (local.set $0 + (i32.const 1) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (func $if-else-after + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-else-through + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-through + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-through2 + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (if + (i32.const 0) + (local.set $1 + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $if-through3 + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (func $if2 + (local $0 i32) + (local $1 i32) + (if + (local.tee $0 + (i32.const 0) + ) + (block $block1 + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (func $if3 + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (block $block1 + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + ) + ) + (drop + (local.get $1) + ) + ) + (func $if4 + (local $0 i32) + (if + (i32.const 0) + (block $block1 + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $0) + ) + (local.set $0 + (i32.const 1) + ) + ) + ) + (drop + (local.get $0) + ) + ) + (func $if5 + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $0) + ) + (local.set $1 + (i32.const 1) + ) + ) + ) + (drop + (local.get $1) + ) + ) + (func $loop + (local $0 i32) + (local $1 i32) + (loop $in + (drop + (local.get $0) + ) + (local.set $0 + (i32.const 0) + ) + (drop + (local.get $1) + ) + (br $in) + ) + ) + (func $interfere-in-dead + (local $0 i32) + (block $block + (br $block) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $interfere-in-dead2 + (local $0 i32) + (block $block + (unreachable) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $interfere-in-dead3 + (local $0 i32) + (block $block + (return) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $params (param $0 i32) (param $1 f32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (drop + (local.get $2) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + ) + (func $interfere-in-dead4 + (local $0 i32) + (local $1 i32) + (block $block + (br_if $block + (i32.const 0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (func $switch + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block $switch$def + (block $switch-case$1 + (block $switch-case$2 + (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def + (i32.const 100) + ) + (drop + (i32.const 0) + ) + ) + (drop + (local.get $0) + ) + ) + (drop + (local.get $1) + ) + ) + (drop + (local.get $2) + ) + ) + (func $greedy-can-be-happy + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $0 + (i32.const 100) + ) + (local.set $1 + (i32.const 101) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block5 + (local.set $0 + (i32.const 102) + ) + (local.set $1 + (i32.const 103) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $0 + (i32.const 104) + ) + (local.set $1 + (i32.const 105) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block10 + (local.set $0 + (i32.const 106) + ) + (local.set $1 + (i32.const 107) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $0 + (i32.const 108) + ) + (local.set $1 + (i32.const 109) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block15 + (local.set $0 + (i32.const 110) + ) + (local.set $1 + (i32.const 111) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + ) + ) + (func $greedy-can-be-sad + (local $0 i32) + (local $1 i32) + (local $2 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $0 + (i32.const 100) + ) + (local.set $1 + (i32.const 101) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (block $block5 + (local.set $0 + (i32.const 102) + ) + (local.set $2 + (i32.const 103) + ) + (drop + (local.get $0) + ) + (drop + (local.get $2) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $1 + (i32.const 104) + ) + (local.set $0 + (i32.const 105) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + ) + (block $block10 + (local.set $1 + (i32.const 106) + ) + (local.set $2 + (i32.const 107) + ) + (drop + (local.get $1) + ) + (drop + (local.get $2) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $2 + (i32.const 108) + ) + (local.set $0 + (i32.const 109) + ) + (drop + (local.get $2) + ) + (drop + (local.get $0) + ) + ) + (block $block15 + (local.set $2 + (i32.const 110) + ) + (local.set $1 + (i32.const 111) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + ) + ) + ) + ) + (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (i32.ge_s + (local.get $2) + (i32.const 4096) + ) + (drop + (local.get $0) + ) + ) + (local.set $3 + (local.get $0) + ) + (if + (i32.eq + (i32.and + (local.get $0) + (i32.const 3) + ) + (i32.and + (local.get $1) + (i32.const 3) + ) + ) + (block $block2 + (block $while-out$0 + (loop $while-in$1 + (if + (i32.eqz + (i32.and + (local.get $0) + (i32.const 3) + ) + ) + (br $while-out$0) + ) + (block $block4 + (if + (i32.eqz + (local.get $2) + ) + (return + (local.get $3) + ) + ) + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + ) + (br $while-in$1) + ) + ) + (block $while-out$2 + (loop $while-in$3 + (if + (i32.eqz + (i32.ge_s + (local.get $2) + (i32.const 4) + ) + ) + (br $while-out$2) + ) + (block $block7 + (i32.store + (local.get $0) + (i32.load + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 4) + ) + ) + ) + (br $while-in$3) + ) + ) + ) + ) + (block $while-out$4 + (loop $while-in$5 + (if + (i32.eqz + (i32.gt_s + (local.get $2) + (i32.const 0) + ) + ) + (br $while-out$4) + ) + (block $block9 + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + ) + (br $while-in$5) + ) + ) + (return + (local.get $3) + ) + ) + (func $this-is-effective-i-tell-you (param $0 i32) + (if + (i32.const -1) + (block $block1 + (if + (i32.const 0) + (nop) + ) + (local.set $0 + (i32.const 1) + ) + ) + (nop) + ) + (drop + (local.get $0) + ) + ) + (func $prefer-remove-copies1 + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (nop) + (local.set $1 + (i32.const 1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + (func $prefer-remove-copies2 + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 0) + ) + (nop) + (local.set $1 + (i32.const 1) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + ) + (func $in-unreachable + (local $0 i32) + (block $x + (return) + (drop + (i32.const 1) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + (block $y + (unreachable) + (drop + (i32.const 1) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + (block $z + (br $z) + (drop + (i32.const 1) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + (block $z14 + (br_table $z14 $z14 + (i32.const 100) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + ) + ) + (func $nop-in-unreachable + (local $0 i32) + (block $block + (unreachable) + (i32.store + (i32.const 0) + (i32.const 0) + ) + ) + ) + (func $loop-backedge + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.const 2) + ) + (block $out + (loop $while-in7 + (local.set $1 + (i32.const 0) + ) + (call $set + (local.get $1) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (if + (call $get) + (local.set $1 + (local.get $0) + ) + ) + (br_if $out + (local.get $1) + ) + (local.set $0 + (i32.const 100) + ) + (nop) + (br $while-in7) + ) + ) + ) + (func $if-copy1 + (local $0 i32) + (local $1 i32) + (loop $top + (local.set $0 + (if (result i32) + (i32.const 1) + (local.get $0) + (local.get $1) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (br $top) + ) + ) + (func $if-copy2 + (local $0 i32) + (local $1 i32) + (loop $top + (local.set $1 + (if (result i32) + (i32.const 1) + (local.get $0) + (local.get $1) + ) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (br $top) + ) + ) + (func $if-copy3 + (local $0 i32) + (local $1 i32) + (loop $top + (local.set $0 + (if (result i32) + (i32.const 1) + (unreachable) + (local.get $0) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (br $top) + ) + ) + (func $if-copy4 + (local $0 i32) + (local $1 i32) + (loop $top + (local.set $1 + (if (result i32) + (i32.const 1) + (unreachable) + (local.get $0) + ) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (br $top) + ) + ) + (func $if-copy-tee + (local $0 i32) + (local $1 i32) + (loop $top + (drop + (local.tee $0 + (if (result i32) + (i32.const 1) + (local.get $0) + (i32.const 2) + ) + ) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (br $top) + ) + ) + (func $tee_br (param $0 i32) (result i32) + (block $b + (return + (br $b) + ) + ) + (i32.const 1) + ) + (func $unused-tee-with-child-if-no-else (param $0 i32) + (loop $label$0 + (drop + (if + (br $label$0) + (nop) + ) + ) + ) + ) + (func $tee_if_with_unreachable_else (param $0 f64) (param $1 i32) (result i64) + (call $tee_if_with_unreachable_else + (local.tee $0 + (if (result f64) + (local.get $1) + (local.get $0) + (unreachable) + ) + ) + (f64.lt + (f64.const -128) + (local.get $0) + ) + ) + ) + (func $tee_if_with_unreachable_true (param $0 f64) (param $1 i32) (result i64) + (call $tee_if_with_unreachable_else + (local.tee $0 + (if (result f64) + (local.get $1) + (unreachable) + (local.get $0) + ) + ) + (f64.lt + (f64.const -128) + (local.get $0) + ) + ) + ) + (func $pick + (local $0 i32) + (nop) + (if + (i32.const 1) + (drop + (i32.const 1) + ) + ) + (nop) + (nop) + ) + (func $pick-2 + (local $0 i32) + (nop) + (if + (i32.const 1) + (drop + (i32.const 1) + ) + ) + (nop) + (nop) + ) + (func $many + (local $0 i32) + (nop) + (nop) + (nop) + (nop) + (if + (i32.const 1) + (drop + (i32.const 1) + ) + ) + (nop) + (if + (i32.const 1) + (drop + (i32.const 1) + ) + ) + (nop) + (nop) + (nop) + (local.set $0 + (i32.const 2) + ) + (nop) + (if + (i32.const 1) + (drop + (i32.const 1) + ) + ) + (nop) + (nop) + (nop) + (drop + (i32.const 2) + ) + (nop) + ) + (func $loop-copies (param $0 i32) (param $1 i32) + (loop $loop + (local.set $0 + (local.get $1) + ) + (local.set $1 + (local.get $0) + ) + (br_if $loop + (local.get $0) + ) + ) + ) + (func $proper-type (result f64) + (local $0 f64) + (local $1 i32) + (drop + (select + (i32.const 0) + (i32.const 1) + (local.get $1) + ) + ) + (local.get $0) + ) + (func $reuse-param (param $0 i32) (param $1 i32) (result i32) + (i32.add + (local.tee $0 + (i32.xor + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/coalesce-locals.wast binaryen-99/test/passes/coalesce-locals.wast --- binaryen-108/test/passes/coalesce-locals.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/coalesce-locals.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1225 @@ +(module + (memory 10) + (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $2 (func)) + (type $3 (func (param i32 f32))) + (type $4 (func (param i32))) + (import $_emscripten_autodebug_i32 "env" "_emscripten_autodebug_i32" (param i32 i32) (result i32)) + (import $get "env" "get" (result i32)) + (import $set "env" "set" (param i32)) + (func $nothing-to-do (type $2) + (local $x i32) + (nop) + ) + (func $merge (type $2) + (local $x i32) + (local $y i32) + (nop) + ) + (func $leave-type (type $2) + (local $x i32) + (local $y f32) + (nop) + ) + (func $leave-interfere (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 0) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $almost-interfere (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.const 0) + ) + (drop + (local.get $y) + ) + ) + (func $redundant-copy (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $ineffective-store (type $2) + (local $x i32) + (local.set $x + (i32.const 0) + ) + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + ) + (func $block (type $2) + (local $x i32) + (block $block0 + (local.set $x + (i32.const 0) + ) + ) + (drop + (local.get $x) + ) + ) + (func $see-both-sides (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (block $block0 + (local.set $y + (i32.const 0) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $see-br-and-ignore-dead (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (block $block + (br $block) + (local.set $y + (i32.const 0) + ) + (drop + (local.get $y) + ) + (local.set $x + (i32.const -1) + ) + ) + (drop + (local.get $x) + ) + ) + (func $see-block-body (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (block $block + (local.set $y + (i32.const 0) + ) + (drop + (local.get $y) + ) + (br $block) + ) + (drop + (local.get $x) + ) + ) + (func $zero-init (type $2) + (local $x i32) + (local $y i32) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $multi (type $2) + (local $x i32) + (local $y i32) + (local $z i32) + (drop + (local.get $y) + ) + (drop + (local.get $z) + ) + ) + (func $if-else (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $if-else-parallel (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + ) + (block $block3 + (local.set $y + (i32.const 1) + ) + (drop + (local.get $y) + ) + ) + ) + ) + (func $if-else-after (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 1) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-else-through (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-through (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (i32.const 1) + ) + (if + (i32.const 0) + (drop + (i32.const 1) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-through2 (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (if + (i32.const 0) + (local.set $y + (i32.const 1) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (func $if-through3 (type $2) + (local $x i32) + (local $y i32) + (local.set $x + (i32.const 0) + ) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + ) + (func $if2 (type $2) + (local $x i32) + (local $y i32) + (if + (local.tee $x + (i32.const 0) + ) + (block $block1 + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + ) + (func $if3 (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + ) + ) + (drop + (local.get $y) + ) + ) + (func $if4 (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (local.set $x + (i32.const 0) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.const 1) + ) + ) + ) + (drop + (local.get $y) + ) + ) + (func $if5 (type $2) + (local $x i32) + (local $y i32) + (if + (i32.const 0) + (block $block1 + (drop + (local.get $x) + ) + (local.set $y + (i32.const 1) + ) + ) + ) + (drop + (local.get $y) + ) + ) + (func $loop (type $2) + (local $x i32) + (local $y i32) + (loop $in + (drop + (local.get $x) + ) + (local.set $x + (i32.const 0) + ) + (drop + (local.get $y) + ) + (br $in) + ) + ) + (func $interfere-in-dead (type $2) + (local $x i32) + (local $y i32) + (block $block + (br $block) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $interfere-in-dead2 (type $2) + (local $x i32) + (local $y i32) + (block $block + (unreachable) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $interfere-in-dead3 (type $2) + (local $x i32) + (local $y i32) + (block $block + (return) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $params (type $3) (param $p i32) (param $q f32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (drop + (local.get $y) + ) + (drop + (local.get $z) + ) + (drop + (local.get $w) + ) + ) + (func $interfere-in-dead4 (type $2) + (local $x i32) + (local $y i32) + (block $block + (br_if $block + (i32.const 0) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $switch (type $2) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (block $switch$def + (block $switch-case$1 + (block $switch-case$2 + (br_table $switch-case$1 $switch-case$2 $switch-case$1 $switch-case$1 $switch$def + (i32.const 100) + ) + (drop + (local.get $x) + ) + ) + (drop + (local.get $y) + ) + ) + (drop + (local.get $z) + ) + ) + (drop + (local.get $w) + ) + ) + (func $greedy-can-be-happy (type $2) + (local $x1 i32) + (local $x2 i32) + (local $x3 i32) + (local $y1 i32) + (local $y2 i32) + (local $y3 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $x1 + (i32.const 100) + ) + (local.set $y2 + (i32.const 101) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y2) + ) + ) + (block $block5 + (local.set $x1 + (i32.const 102) + ) + (local.set $y3 + (i32.const 103) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y3) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $x2 + (i32.const 104) + ) + (local.set $y1 + (i32.const 105) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y1) + ) + ) + (block $block10 + (local.set $x2 + (i32.const 106) + ) + (local.set $y3 + (i32.const 107) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y3) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $x3 + (i32.const 108) + ) + (local.set $y1 + (i32.const 109) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y1) + ) + ) + (block $block15 + (local.set $x3 + (i32.const 110) + ) + (local.set $y2 + (i32.const 111) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y2) + ) + ) + ) + ) + ) + (func $greedy-can-be-sad (type $2) + (local $x1 i32) + (local $y1 i32) + (local $x2 i32) + (local $y2 i32) + (local $x3 i32) + (local $y3 i32) + (if + (i32.const 0) + (if + (i32.const 1) + (if + (i32.const 2) + (block $block3 + (local.set $x1 + (i32.const 100) + ) + (local.set $y2 + (i32.const 101) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y2) + ) + ) + (block $block5 + (local.set $x1 + (i32.const 102) + ) + (local.set $y3 + (i32.const 103) + ) + (drop + (local.get $x1) + ) + (drop + (local.get $y3) + ) + ) + ) + (if + (i32.const 3) + (block $block8 + (local.set $x2 + (i32.const 104) + ) + (local.set $y1 + (i32.const 105) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y1) + ) + ) + (block $block10 + (local.set $x2 + (i32.const 106) + ) + (local.set $y3 + (i32.const 107) + ) + (drop + (local.get $x2) + ) + (drop + (local.get $y3) + ) + ) + ) + ) + (if + (i32.const 4) + (block $block13 + (local.set $x3 + (i32.const 108) + ) + (local.set $y1 + (i32.const 109) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y1) + ) + ) + (block $block15 + (local.set $x3 + (i32.const 110) + ) + (local.set $y2 + (i32.const 111) + ) + (drop + (local.get $x3) + ) + (drop + (local.get $y2) + ) + ) + ) + ) + ) + (func $_memcpy (type $FUNCSIG$iiii) (param $i1 i32) (param $i2 i32) (param $i3 i32) (result i32) + (local $i4 i32) + (if + (i32.ge_s + (local.get $i3) + (i32.const 4096) + ) + (drop + (local.get $i1) + ) + ) + (local.set $i4 + (local.get $i1) + ) + (if + (i32.eq + (i32.and + (local.get $i1) + (i32.const 3) + ) + (i32.and + (local.get $i2) + (i32.const 3) + ) + ) + (block $block2 + (block $while-out$0 + (loop $while-in$1 + (if + (i32.eqz + (i32.and + (local.get $i1) + (i32.const 3) + ) + ) + (br $while-out$0) + ) + (block $block4 + (if + (i32.eqz + (local.get $i3) + ) + (return + (local.get $i4) + ) + ) + (i32.store8 + (local.get $i1) + (i32.load8_s + (local.get $i2) + ) + ) + (local.set $i1 + (i32.add + (local.get $i1) + (i32.const 1) + ) + ) + (local.set $i2 + (i32.add + (local.get $i2) + (i32.const 1) + ) + ) + (local.set $i3 + (i32.sub + (local.get $i3) + (i32.const 1) + ) + ) + ) + (br $while-in$1) + ) + ) + (block $while-out$2 + (loop $while-in$3 + (if + (i32.eqz + (i32.ge_s + (local.get $i3) + (i32.const 4) + ) + ) + (br $while-out$2) + ) + (block $block7 + (i32.store + (local.get $i1) + (i32.load + (local.get $i2) + ) + ) + (local.set $i1 + (i32.add + (local.get $i1) + (i32.const 4) + ) + ) + (local.set $i2 + (i32.add + (local.get $i2) + (i32.const 4) + ) + ) + (local.set $i3 + (i32.sub + (local.get $i3) + (i32.const 4) + ) + ) + ) + (br $while-in$3) + ) + ) + ) + ) + (block $while-out$4 + (loop $while-in$5 + (if + (i32.eqz + (i32.gt_s + (local.get $i3) + (i32.const 0) + ) + ) + (br $while-out$4) + ) + (block $block9 + (i32.store8 + (local.get $i1) + (i32.load8_s + (local.get $i2) + ) + ) + (local.set $i1 + (i32.add + (local.get $i1) + (i32.const 1) + ) + ) + (local.set $i2 + (i32.add + (local.get $i2) + (i32.const 1) + ) + ) + (local.set $i3 + (i32.sub + (local.get $i3) + (i32.const 1) + ) + ) + ) + (br $while-in$5) + ) + ) + (return + (local.get $i4) + ) + ) + (func $this-is-effective-i-tell-you (type $4) (param $x i32) + (if + (i32.const -1) + (block $block1 + (if + (i32.const 0) + (nop) + ) + (local.set $x + (i32.const 1) + ) + ) + (nop) + ) + (drop + (local.get $x) + ) + ) + (func $prefer-remove-copies1 (type $2) + (local $y i32) + (local $z i32) + (local $x i32) + (local.set $x + (i32.const 0) + ) + (local.set $y + (local.get $x) + ) + (local.set $z + (i32.const 1) + ) + (drop + (local.get $y) + ) + (drop + (local.get $z) + ) + ) + (func $prefer-remove-copies2 (type $2) + (local $y i32) + (local $z i32) + (local $x i32) + (local.set $x + (i32.const 0) + ) + (local.set $z + (local.get $x) + ) + (local.set $y + (i32.const 1) + ) + (drop + (local.get $y) + ) + (drop + (local.get $z) + ) + ) + (func $in-unreachable + (local $a i32) + (block $x + (return) + (local.set $a (i32.const 1)) + (drop (local.get $a)) + (local.set $a (local.get $a)) + ) + (block $y + (unreachable) + (local.set $a (i32.const 1)) + (drop (local.get $a)) + (local.set $a (local.get $a)) + ) + (block $z + (br $z) + (local.set $a (i32.const 1)) + (drop (local.get $a)) + (local.set $a (local.get $a)) + ) + (block $z + (br_table $z $z + (i32.const 100) + ) + (local.set $a (i32.const 1)) + (drop (local.get $a)) + (local.set $a (local.get $a)) + ) + ) + (func $nop-in-unreachable + (local $x i32) + (block + (unreachable) + (i32.store + (local.get $x) + (local.tee $x (i32.const 0)) + ) + ) + ) + (func $loop-backedge + (local $0 i32) ;; loop phi + (local $1 i32) ;; value for next loop iteration + (local $2 i32) ;; a local that might be merged with with $1, perhaps making us prefer it to removing a backedge copy + (local.set $0 + (i32.const 2) + ) + (block $out + (loop $while-in7 + (local.set $2 (i32.const 0)) ;; 2 interferes with 0 + (call $set (local.get $2)) + (local.set $1 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (if (call $get) + (local.set $2 (local.get $1)) ;; copy for 1/2 + ) + (br_if $out (local.get $2)) + (local.set $1 (i32.const 100)) + (local.set $0 (local.get $1)) ;; copy for 1/0, with extra weight should win the tie + (br $while-in7) + ) + ) + ) + (func $if-copy1 + (local $x i32) + (local $y i32) + (loop $top + (local.set $x + (if (result i32) + (i32.const 1) + (local.get $x) + (local.get $y) + ) + ) + (drop (local.get $x)) + (drop (local.get $y)) + (br $top) + ) + ) + (func $if-copy2 + (local $x i32) + (local $y i32) + (loop $top + (local.set $x + (if (result i32) + (i32.const 1) + (local.get $y) + (local.get $x) + ) + ) + (drop (local.get $x)) + (drop (local.get $y)) + (br $top) + ) + ) + (func $if-copy3 + (local $x i32) + (local $y i32) + (loop $top + (local.set $x + (if (result i32) + (i32.const 1) + (unreachable) + (local.get $x) + ) + ) + (drop (local.get $x)) + (drop (local.get $y)) + (br $top) + ) + ) + (func $if-copy4 + (local $x i32) + (local $y i32) + (loop $top + (local.set $x + (if (result i32) + (i32.const 1) + (unreachable) + (local.get $y) + ) + ) + (drop (local.get $x)) + (drop (local.get $y)) + (br $top) + ) + ) + (func $if-copy-tee + (local $x i32) + (local $y i32) + (loop $top + (drop + (local.tee $x + (if (result i32) + (i32.const 1) + (local.get $x) + (i32.const 2) + ) + ) + ) + (drop (local.get $x)) + (drop (local.get $y)) + (br $top) + ) + ) + (func $tee_br (param $x i32) (result i32) + (block $b + (return + (local.tee $x + (br $b) + ) + ) + ) + (i32.const 1) + ) + (func $unused-tee-with-child-if-no-else (param $0 i32) + (loop $label$0 + (drop + (local.tee $0 + (if + (br $label$0) + (nop) + ) + ) + ) + ) + ) + (func $tee_if_with_unreachable_else (param $0 f64) (param $1 i32) (result i64) + (call $tee_if_with_unreachable_else + (local.tee $0 + (if (result f64) + (local.get $1) + (local.get $0) + (unreachable) + ) + ) + (f64.lt + (f64.const -128) + (local.get $0) + ) + ) + ) + (func $tee_if_with_unreachable_true (param $0 f64) (param $1 i32) (result i64) + (call $tee_if_with_unreachable_else + (local.tee $0 + (if (result f64) + (local.get $1) + (unreachable) + (local.get $0) + ) + ) + (f64.lt + (f64.const -128) + (local.get $0) + ) + ) + ) + (func $pick + (local $x i32) + (local $y i32) + (local.set $x (local.get $y)) + (if (i32.const 1) + (local.set $x (i32.const 1)) + ) + (local.set $x (local.get $y)) + (local.set $x (local.get $y)) + ) + (func $pick-2 + (local $x i32) + (local $y i32) + (local.set $y (local.get $x)) + (if (i32.const 1) + (local.set $y (i32.const 1)) + ) + (local.set $y (local.get $x)) + (local.set $y (local.get $x)) + ) + (func $many + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $y (local.get $x)) + (local.set $z (local.get $y)) + (local.set $w (local.get $z)) + (local.set $x (local.get $z)) + (if (i32.const 1) + (local.set $y (i32.const 1)) + ) + (local.set $x (local.get $z)) + (if (i32.const 1) + (local.set $y (i32.const 1)) + ) + (local.set $y (local.get $x)) + (local.set $z (local.get $y)) + (local.set $w (local.get $z)) + (local.set $z (i32.const 2)) + (local.set $x (local.get $z)) + (if (i32.const 1) + (local.set $y (i32.const 1)) + ) + (local.set $y (local.get $x)) + (local.set $z (local.get $y)) + (local.set $w (local.get $z)) + (local.set $z (i32.const 2)) + (local.set $x (local.get $w)) + ) + (func $loop-copies (param $x i32) (param $y i32) + (loop $loop + (local.set $x (local.get $y)) + (local.set $y (local.get $x)) + (br_if $loop (local.get $x)) + ) + ) + (func $proper-type (result f64) + (local $var$0 i32) + (local $var$2 f64) + (local.set $var$0 + (select + (i32.const 0) + (i32.const 1) + (local.get $var$0) + ) + ) + (local.tee $var$2 ;; the locals will be reordered, this should be the f64 + (local.get $var$2) + ) + ) + (func $reuse-param (param $x i32) (param $y i32) (result i32) + (local $temp i32) + (i32.add + (local.tee $temp + (i32.xor + (i32.shr_s + (i32.shl + (local.get $x) ;; $x and $temp do not interfere + (i32.const 16) + ) + (i32.const 16) + ) + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (local.get $temp) + ) + ) +) diff -Nru binaryen-108/test/passes/code-folding_enable-threads.txt binaryen-99/test/passes/code-folding_enable-threads.txt --- binaryen-108/test/passes/code-folding_enable-threads.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/code-folding_enable-threads.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,206 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_f32 (func (result f32))) + (type $f32_=>_none (func (param f32))) + (memory $0 1 1) + (table $0 282 282 funcref) + (func $0 + (block $label$1 + (if + (i32.const 1) + (block + (block $label$3 + (call_indirect (type $f32_=>_none) + (block $label$4 + (br $label$3) + ) + (i32.const 105) + ) + ) + (nop) + ) + ) + ) + ) + (func $negative-zero (result f32) + (if (result f32) + (i32.const 0) + (block $label$0 (result f32) + (f32.const 0) + ) + (block $label$1 (result f32) + (f32.const -0) + ) + ) + ) + (func $negative-zero-b (result f32) + (drop + (i32.const 0) + ) + (block $label$0 (result f32) + (f32.const -0) + ) + ) + (func $negative-zero-c (result f32) + (drop + (i32.const 0) + ) + (block $label$0 (result f32) + (f32.const 0) + ) + ) + (func $break-target-outside-of-return-merged-code + (block $label$A + (if + (unreachable) + (block $block + (block $block0 + (block $label$B + (if + (unreachable) + (br_table $label$A $label$B + (unreachable) + ) + ) + ) + (return) + ) + ) + (block $block2 + (block $label$C + (if + (unreachable) + (br_table $label$A $label$C + (unreachable) + ) + ) + ) + (return) + ) + ) + ) + ) + (func $break-target-inside-all-good + (block $folding-inner0 + (block $label$A + (if + (unreachable) + (block $block + (block $block4 + (br $folding-inner0) + ) + ) + (block $block6 + (br $folding-inner0) + ) + ) + ) + ) + (block $label$B + (if + (unreachable) + (br_table $label$B $label$B + (unreachable) + ) + ) + ) + (return) + ) + (func $leave-inner-block-type + (block $label$1 + (drop + (block $label$2 + (block + (unreachable) + (unreachable) + ) + (br $label$1) + ) + ) + ) + (drop + (i32.const 1) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (memory $0 (shared 1 1)) + (export "func_2224" (func $0)) + (func $0 (result i32) + (local $var$0 i32) + (if (result i32) + (i32.const 0) + (i32.load offset=22 + (local.get $var$0) + ) + (i32.atomic.load offset=22 + (local.get $var$0) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (global $global$0 (mut i32) (i32.const 10)) + (func $determinism + (block $folding-inner0 + (block + (block $label$1 + (br_if $label$1 + (i32.const 1) + ) + (br $folding-inner0) + ) + (block $label$2 + (br_if $label$2 + (i32.const 0) + ) + (if + (global.get $global$0) + (block $block + (br $folding-inner0) + ) + ) + (unreachable) + ) + (if + (global.get $global$0) + (block $block1 + (br $folding-inner0) + ) + ) + (unreachable) + ) + ) + (global.set $global$0 + (i32.sub + (global.get $global$0) + (i32.const 1) + ) + ) + (unreachable) + ) + (func $careful-of-the-switch (param $0 i32) + (block $label$1 + (block $label$3 + (block $label$5 + (block $label$7 + (br_table $label$3 $label$7 + (i32.const 0) + ) + ) + (br $label$1) + ) + (block $label$8 + (br_table $label$3 $label$8 + (i32.const 0) + ) + ) + (br $label$1) + ) + (unreachable) + ) + ) +) diff -Nru binaryen-108/test/passes/code-folding_enable-threads.wast binaryen-99/test/passes/code-folding_enable-threads.wast --- binaryen-108/test/passes/code-folding_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/code-folding_enable-threads.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,223 @@ +(module + (type $13 (func (param f32))) + (table 282 282 funcref) + (memory $0 1 1) + (func $0 + (block $label$1 + (if + (i32.const 1) + (block $label$3 + (call_indirect (type $13) + (block $label$4 (result f32) ;; but this type may change dangerously + (nop) ;; fold this + (br $label$3) + ) + (i32.const 105) + ) + (nop) ;; with this + ) + ) + ) + ) + (func $negative-zero (result f32) + (if (result f32) + (i32.const 0) + (block $label$0 (result f32) + (f32.const 0) + ) + (block $label$1 (result f32) + (f32.const -0) + ) + ) + ) + (func $negative-zero-b (result f32) + (if (result f32) + (i32.const 0) + (block $label$0 (result f32) + (f32.const -0) + ) + (block $label$1 (result f32) + (f32.const -0) + ) + ) + ) + (func $negative-zero-c (result f32) + (if (result f32) + (i32.const 0) + (block $label$0 (result f32) + (f32.const 0) + ) + (block $label$1 (result f32) + (f32.const 0) + ) + ) + ) + (func $break-target-outside-of-return-merged-code + (block $label$A + (if + (unreachable) + (block + (block + (block $label$B + (if + (unreachable) + (br_table $label$A $label$B + (unreachable) + ) + ) + ) + (return) + ) + ) + (block + (block $label$C + (if + (unreachable) + (br_table $label$A $label$C ;; this all looks mergeable, but $label$A is outside + (unreachable) + ) + ) + ) + (return) + ) + ) + ) + ) + (func $break-target-inside-all-good + (block $label$A + (if + (unreachable) + (block + (block + (block $label$B + (if + (unreachable) + (br_table $label$B $label$B + (unreachable) + ) + ) + ) + (return) + ) + ) + (block + (block $label$C + (if + (unreachable) + (br_table $label$C $label$C ;; this all looks mergeable, and is, B ~~ C + (unreachable) + ) + ) + ) + (return) + ) + ) + ) + ) + (func $leave-inner-block-type + (block $label$1 + (drop + (block $label$2 (result i32) ;; leave this alone (otherwise, if we make it unreachable, we need to do more updating) + (br_if $label$2 + (unreachable) + (unreachable) + ) + (drop + (i32.const 1) + ) + (br $label$1) + ) + ) + (drop + (i32.const 1) + ) + ) + ) +) +(module + (memory $0 (shared 1 1)) + (export "func_2224" (func $0)) + (func $0 (result i32) + (local $var$0 i32) + (if (result i32) + (i32.const 0) + (i32.load offset=22 + (local.get $var$0) + ) + (i32.atomic.load offset=22 + (local.get $var$0) + ) + ) + ) +) +(module + (type $0 (func)) + (global $global$0 (mut i32) (i32.const 10)) + (func $determinism (; 0 ;) (type $0) + (block $label$1 + (br_if $label$1 + (i32.const 1) + ) + (global.set $global$0 + (i32.sub + (global.get $global$0) + (i32.const 1) + ) + ) + (unreachable) + ) + (block $label$2 + (br_if $label$2 + (i32.const 0) + ) + (if + (global.get $global$0) + (block + (global.set $global$0 + (i32.sub + (global.get $global$0) + (i32.const 1) + ) + ) + (unreachable) + ) + ) + (unreachable) + ) + (if + (global.get $global$0) + (block + (global.set $global$0 + (i32.sub + (global.get $global$0) + (i32.const 1) + ) + ) + (unreachable) + ) + ) + (unreachable) + ) + (func $careful-of-the-switch (param $0 i32) + (block $label$1 + (block $label$3 + (block $label$5 + (block $label$7 ;; this is block is equal to $label$8 when accounting for the internal 7/8 difference + (br_table $label$3 $label$7 ;; the reference to $label$3 must remain valid, cannot hoist out of it! + (i32.const 0) + ) + ) + (br $label$1) + ) + (block $label$8 + (br_table $label$3 $label$8 + (i32.const 0) + ) + ) + (br $label$1) + ) + (unreachable) + ) + ) +) + diff -Nru binaryen-108/test/passes/code-pushing_all-features.txt binaryen-99/test/passes/code-pushing_all-features.txt --- binaryen-108/test/passes/code-pushing_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/code-pushing_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,118 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (event $e (attr 0) (param i32)) + (func $cant-push-past-call + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (call $cant-push-past-call) + (drop + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $cant-push-past-throw + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (throw $e + (i32.const 0) + ) + (drop + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $can-push-past-throw-within-try + (local $x i32) + (block $out + (try + (do + (throw $e + (i32.const 0) + ) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (drop + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $cant-push-past-rethrow-within-catch + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (try + (do + (throw $e + (i32.const 0) + ) + ) + (catch + (rethrow + (pop exnref) + ) + ) + ) + (drop + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $push-past-br-on-exn + (local $x i32) + (local $y exnref) + (drop + (block $out (result i32) + (drop + (br_on_exn $out $e + (local.get $y) + ) + ) + (local.set $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/code-pushing_all-features.wast binaryen-99/test/passes/code-pushing_all-features.wast --- binaryen-108/test/passes/code-pushing_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/code-pushing_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,81 @@ +(module + (event $e (attr 0) (param i32)) + + (func $cant-push-past-call + (local $x i32) + (block $out + ;; This local.set cannot be pushed down, because the call below can throw + (local.set $x (i32.const 1)) + (call $cant-push-past-call) + (drop (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + + (func $cant-push-past-throw + (local $x i32) + (block $out + ;; This local.set cannot be pushed down, because there is 'throw' below + (local.set $x (i32.const 1)) + (throw $e (i32.const 0)) + (drop (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + + (func $can-push-past-throw-within-try + (local $x i32) + (block $out + ;; This local.set can be pushed down, because the 'throw' below is going + ;; to be caught by the inner catch + (local.set $x (i32.const 1)) + (try + (do + (throw $e (i32.const 0)) + ) + (catch + (drop (pop exnref)) + ) + ) + (drop (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + + (func $cant-push-past-rethrow-within-catch + (local $x i32) + (block $out + ;; This local.set cannot be pushed down, because there is 'rethrow' within + ;; the inner catch + (local.set $x (i32.const 1)) + (try + (do + (throw $e (i32.const 0)) + ) + (catch + (rethrow (pop exnref)) + ) + ) + (drop (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + + (func $push-past-br-on-exn + (local $x i32) + (local $y exnref) + (drop + (block $out (result i32) + (local.set $x (i32.const 1)) + (drop + (br_on_exn $out $e (local.get $y)) + ) + (local.get $x) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/code-pushing_ignore-implicit-traps.txt binaryen-99/test/passes/code-pushing_ignore-implicit-traps.txt --- binaryen-108/test/passes/code-pushing_ignore-implicit-traps.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/code-pushing_ignore-implicit-traps.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,460 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (memory $0 1) + (func $push1 + (local $x i32) + (block $out + (br_if $out + (i32.const 2) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $push2 + (local $x i32) + (local $y i32) + (block $out + (br_if $out + (i32.const 2) + ) + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 3) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $push1-twice + (local $x i32) + (block $out + (br_if $out + (i32.const 2) + ) + (br_if $out + (i32.const 3) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $push1-twiceb + (local $x i32) + (block $out + (br_if $out + (i32.const 2) + ) + (nop) + (br_if $out + (i32.const 3) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $push2-twice + (local $x i32) + (local $y i32) + (block $out + (br_if $out + (i32.const 2) + ) + (br_if $out + (i32.const 2) + ) + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 3) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $ignore-last + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + ) + ) + (func $ignore-last2 + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (nop) + (nop) + (br_if $out + (i32.const 2) + ) + ) + ) + (func $push-if + (local $x i32) + (block $out + (if + (i32.const 2) + (nop) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $push-dropped (result i32) + (local $x i32) + (block $out (result i32) + (drop + (br_if $out + (i32.const 2) + (i32.const 3) + ) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + (i32.const 4) + ) + ) + (func $push-past-stuff + (local $x i32) + (block $out + (call $push-past-stuff) + (drop + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $fail-then-push + (local $x i32) + (local $y i32) + (block $out + (local.set $x + (i32.const 1) + ) + (drop + (local.get $x) + ) + (br_if $out + (i32.const 2) + ) + (br_if $out + (i32.const 3) + ) + (local.set $y + (i32.const 1) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $used + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out + (local.get $x) + ) + (drop + (local.get $x) + ) + ) + ) + (func $not-sfa + (local $x i32) + (local.set $x + (i32.const 1) + ) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $not-sfa2 + (local $x i32) + (drop + (local.get $x) + ) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $used-out + (local $x i32) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + (drop + (local.get $x) + ) + ) + (func $value-might-interfere + (local $x i32) + (block $out + (br_if $out + (i32.const 2) + ) + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (drop + (local.get $x) + ) + ) + ) + (func $value-interferes + (local $x i32) + (block $out + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (i32.store + (i32.const 1) + (i32.const 3) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $value-interferes-accumulation + (local $x i32) + (block $out + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (nop) + (i32.store + (i32.const 1) + (i32.const 3) + ) + (nop) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + ) + ) + (func $value-interferes-in-pushpoint + (local $x i32) + (block $out + (local.set $x + (i32.load + (i32.const 0) + ) + ) + (if + (i32.const 1) + (call $value-interferes) + ) + (drop + (local.get $x) + ) + ) + ) + (func $values-might-interfere + (local $x i32) + (local $y i32) + (block $out + (local.set $x + (call $push-dropped) + ) + (local.set $y + (call $push-dropped) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $unpushed-interferes + (local $x i32) + (local $y i32) + (block $out + (local.set $x + (call $push-dropped) + ) + (local.set $y + (call $push-dropped) + ) + (br_if $out + (i32.const 2) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (drop + (local.get $y) + ) + ) + (func $unpushed-ignorable + (local $x i32) + (local $y i32) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out + (i32.const 2) + ) + (local.set $y + (i32.const 3) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (drop + (local.get $x) + ) + ) + (func $unpushed-ignorable-side-effect + (local $x i32) + (local $y i32) + (block $out + (local.set $x + (call $push-dropped) + ) + (br_if $out + (i32.const 2) + ) + (local.set $y + (i32.const 3) + ) + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + ) + (func $unpushed-side-effect-into-drop + (local $x i32) + (block $out + (local.set $x + (call $push-dropped) + ) + (br_if $out + (i32.const 1) + ) + (drop + (local.get $x) + ) + ) + ) + (func $unpushed-side-effect-into-if + (local $x i32) + (block $out + (local.set $x + (call $push-dropped) + ) + (br_if $out + (i32.const 1) + ) + (if + (local.get $x) + (nop) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/code-pushing_ignore-implicit-traps.wast binaryen-99/test/passes/code-pushing_ignore-implicit-traps.wast --- binaryen-108/test/passes/code-pushing_ignore-implicit-traps.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/code-pushing_ignore-implicit-traps.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,249 @@ +(module + (memory 1) + (func $push1 + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $push2 + (local $x i32) + (local $y i32) + (block $out + (local.set $x (i32.const 1)) + (local.set $y (i32.const 3)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + ) + (func $push1-twice + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + (br_if $out (i32.const 3)) + (drop (local.get $x)) + ) + ) + (func $push1-twiceb + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + (nop) + (br_if $out (i32.const 3)) + (drop (local.get $x)) + ) + ) + (func $push2-twice + (local $x i32) + (local $y i32) + (block $out + (local.set $x (i32.const 1)) + (local.set $y (i32.const 3)) + (br_if $out (i32.const 2)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + ) + (func $ignore-last + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + ) + ) + (func $ignore-last2 + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (nop) + (nop) + (br_if $out (i32.const 2)) + ) + ) + (func $push-if + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (if (i32.const 2) (nop)) + (drop (local.get $x)) + ) + ) + (func $push-dropped (result i32) + (local $x i32) + (block $out (result i32) + (local.set $x (i32.const 1)) + (drop (br_if $out (i32.const 2) (i32.const 3))) + (drop (local.get $x)) + (i32.const 4) + ) + ) + (func $push-past-stuff + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (call $push-past-stuff) + (drop (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $fail-then-push + (local $x i32) + (local $y i32) + (block $out + (local.set $x (i32.const 1)) + (drop (local.get $x)) + (br_if $out (i32.const 2)) + (local.set $y (i32.const 1)) + (br_if $out (i32.const 3)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + ) + ;; and now for stuff that should *not* be pushed + (func $used + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (local.get $x)) + (drop (local.get $x)) + ) + ) + (func $not-sfa + (local $x i32) + (local.set $x (i32.const 1)) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $not-sfa2 + (local $x i32) + (drop (local.get $x)) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $used-out + (local $x i32) + (block $out + (local.set $x (i32.const 1)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + (drop (local.get $x)) + ) + (func $value-might-interfere ;; but doesn't + (local $x i32) + (block $out + (local.set $x (i32.load (i32.const 0))) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $value-interferes + (local $x i32) + (block $out + (local.set $x (i32.load (i32.const 0))) + (i32.store (i32.const 1) (i32.const 3)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $value-interferes-accumulation + (local $x i32) + (block $out + (local.set $x (i32.load (i32.const 0))) + (nop) + (i32.store (i32.const 1) (i32.const 3)) + (nop) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + ) + ) + (func $value-interferes-in-pushpoint + (local $x i32) + (block $out + (local.set $x (i32.load (i32.const 0))) + (if (i32.const 1) + (call $value-interferes) + ) + (drop (local.get $x)) + ) + ) + (func $values-might-interfere ;; they don't, as we keep the order - but here their side effects prevent pushing + (local $x i32) + (local $y i32) + (block $out + (local.set $x (call $push-dropped)) + (local.set $y (call $push-dropped)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + ) + (func $unpushed-interferes + (local $x i32) + (local $y i32) + (block $out + (local.set $x (call $push-dropped)) + (local.set $y (call $push-dropped)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + (drop (local.get $y)) ;; $y can't be pushed, so x can't be + ) + (func $unpushed-ignorable + (local $x i32) + (local $y i32) + (block $out + (local.set $x (i32.const 1)) + (local.set $y (i32.const 3)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + (drop (local.get $x)) ;; $x can't be pushed, but y doesn't care + ) + (func $unpushed-ignorable-side-effect + (local $x i32) + (local $y i32) + (block $out + (local.set $x (call $push-dropped)) ;; $x can't be pushed, but y doesn't care + (local.set $y (i32.const 3)) + (br_if $out (i32.const 2)) + (drop (local.get $x)) + (drop (local.get $y)) + ) + ) + (func $unpushed-side-effect-into-drop + (local $x i32) + (block $out + (local.set $x (call $push-dropped)) + (br_if $out (i32.const 1)) + (drop (local.get $x)) + ) + ) + (func $unpushed-side-effect-into-if + (local $x i32) + (block $out + (local.set $x (call $push-dropped)) + (br_if $out (i32.const 1)) + (if + (local.get $x) + (nop) + ) + ) + ) +) + diff -Nru binaryen-108/test/passes/const-hoisting.txt binaryen-99/test/passes/const-hoisting.txt --- binaryen-108/test/passes/const-hoisting.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/const-hoisting.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,629 @@ +(module + (type $none_=>_none (func)) + (func $10-of-each + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (local.set $0 + (i32.const -1048577) + ) + (local.set $1 + (i32.const -1048576) + ) + (local.set $2 + (i32.const -8193) + ) + (local.set $3 + (i32.const 8192) + ) + (local.set $4 + (i32.const 1048575) + ) + (local.set $5 + (i32.const 1048576) + ) + ) + (block + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 63) + ) + (drop + (i32.const 64) + ) + (drop + (i32.const 8191) + ) + (drop + (local.get $3) + ) + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (i32.const -64) + ) + (drop + (i32.const -65) + ) + (drop + (i32.const -8192) + ) + (drop + (local.get $2) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + ) + ) + (func $floats-10-times + (local $0 f32) + (local $1 f64) + (block + (local.set $0 + (f32.const 0) + ) + (local.set $1 + (f64.const 0) + ) + ) + (block + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (func $too-few + (drop + (i32.const 8192) + ) + (drop + (i32.const 8192) + ) + (drop + (i32.const 8192) + ) + (drop + (i32.const 8192) + ) + (drop + (i32.const 8192) + ) + ) + (func $just-enough + (local $0 i32) + (block + (local.set $0 + (i32.const 8192) + ) + ) + (block + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + ) + ) + (func $too-few-b + (drop + (i32.const 1048576) + ) + (drop + (i32.const 1048576) + ) + (drop + (i32.const 1048576) + ) + ) + (func $enough-b + (local $0 i32) + (block + (local.set $0 + (i32.const 1048576) + ) + ) + (block + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + ) + ) + (func $too-few-c + (drop + (f32.const 0) + ) + (drop + (f32.const 0) + ) + (drop + (f32.const 0) + ) + ) + (func $enough-c + (local $0 f32) + (block + (local.set $0 + (f32.const 0) + ) + ) + (block + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + ) + ) + (func $too-few-d + (drop + (f64.const 0) + ) + ) + (func $enough-d + (local $0 f64) + (block + (local.set $0 + (f64.const 0) + ) + ) + (block + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/const-hoisting.wast binaryen-99/test/passes/const-hoisting.wast --- binaryen-108/test/passes/const-hoisting.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/const-hoisting.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,201 @@ +(module + (func $10-of-each + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + (drop (i32.const 0)) ;; 1 byte + (drop (i32.const 63)) ;; 1 byte + (drop (i32.const 64)) ;; 2 bytes + (drop (i32.const 8191)) ;; 2 bytes + (drop (i32.const 8192)) ;; 3 bytes + (drop (i32.const 1048575)) ;; 3 bytes + (drop (i32.const 1048576)) ;; 4 bytes + (drop (i32.const -64)) ;; 1 byte + (drop (i32.const -65)) ;; 2 bytes + (drop (i32.const -8192)) ;; 2 bytes + (drop (i32.const -8193)) ;; 3 bytes + (drop (i32.const -1048576)) ;; 3 bytes + (drop (i32.const -1048577)) ;; 4 bytes + ) + (func $floats-10-times + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + (drop (f32.const 0)) ;; 4 bytes + (drop (f64.const 0)) ;; 8 bytes + ) + (func $too-few + (drop (i32.const 8192)) ;; 3 bytes, need 6 appearances + (drop (i32.const 8192)) + (drop (i32.const 8192)) + (drop (i32.const 8192)) + (drop (i32.const 8192)) + ) + (func $just-enough + (drop (i32.const 8192)) ;; 3 bytes, need 6 appearances + (drop (i32.const 8192)) + (drop (i32.const 8192)) + (drop (i32.const 8192)) + (drop (i32.const 8192)) + (drop (i32.const 8192)) + ) + (func $too-few-b + (drop (i32.const 1048576)) ;; 4 bytes, need 4 appearances + (drop (i32.const 1048576)) + (drop (i32.const 1048576)) + ) + (func $enough-b + (drop (i32.const 1048576)) ;; 4 bytes, need 4 appearances + (drop (i32.const 1048576)) + (drop (i32.const 1048576)) + (drop (i32.const 1048576)) + ) + (func $too-few-c + (drop (f32.const 0)) ;; 4 bytes, need 4 appearances + (drop (f32.const 0)) + (drop (f32.const 0)) + ) + (func $enough-c + (drop (f32.const 0)) ;; 4 bytes, need 4 appearances + (drop (f32.const 0)) + (drop (f32.const 0)) + (drop (f32.const 0)) + ) + (func $too-few-d + (drop (f64.const 0)) ;; 8 bytes, need 2 appearances + ) + (func $enough-d + (drop (f64.const 0)) ;; 4 bytes, need 4 appearances + (drop (f64.const 0)) + ) +) + diff -Nru binaryen-108/test/passes/converge_O3_metrics.bin.txt binaryen-99/test/passes/converge_O3_metrics.bin.txt --- binaryen-108/test/passes/converge_O3_metrics.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/converge_O3_metrics.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,35 +1,35 @@ total + [events] : 0 [exports] : 2 - [funcs] : 6 + [funcs] : 8 [globals] : 1 [imports] : 3 [memory-data] : 28 [table-data] : 429 - [tables] : 0 - [tags] : 0 - [total] : 551 - [vars] : 2 - Binary : 12 - Block : 6 - Break : 3 - Call : 1 - CallIndirect : 4 - Const : 46 - Drop : 3 - GlobalSet : 1 - If : 2 - Load : 16 - LocalGet : 16 - LocalSet : 6 - Loop : 1 - RefFunc : 429 - Store : 5 + [total] : 129 + [vars] : 4 + binary : 12 + block : 8 + break : 3 + call : 3 + call_indirect : 4 + const : 45 + drop : 3 + global.get : 1 + global.set : 1 + if : 2 + load : 16 + local.get : 18 + local.set : 7 + loop : 1 + store : 5 (module (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 2948) "\03") (data (i32.const 6828) "\04") @@ -40,9 +40,9 @@ (data (i32.const 18732) "D\1b") (data (i32.const 18764) "`\0b") (import "env" "table" (table $timport$0 478 478 funcref)) + (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32))) (global $global$0 (mut i32) (i32.const 1)) - (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) (export "_main" (func $_main)) (export "_malloc" (func $_malloc)) (func $b0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) @@ -51,120 +51,18 @@ (func $_malloc (; has Stack IR ;) (param $0 i32) (result i32) (i32.const 0) ) - (func $_main (; has Stack IR ;) (result i32) - (local $0 i32) - (local $1 i32) - (local.set $0 - (i32.const 10888) - ) - (loop $label$3 - (br_if $label$3 - (i32.load8_s - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - ) - ) - ) - (local.set $1 - (i32.load offset=24 - (i32.add - (i32.load - (i32.sub - (i32.load - (i32.const 18100) - ) - (i32.const 12) - ) - ) - (i32.const 18100) - ) - ) - ) - (if - (local.tee $0 - (i32.sub - (local.get $0) - (i32.const 10888) - ) - ) - (block $label$2 - (br_if $label$2 - (call_indirect (type $i32_i32_i32_=>_i32) - (local.get $1) - (i32.const 10888) - (local.get $0) - (i32.add - (i32.load offset=48 - (i32.load - (local.get $1) - ) - ) - (i32.const 8) - ) - ) - ) - ) - ) - (block $label$1 - (br_if $label$1 - (if (result i32) - (i32.load - (i32.add - (local.tee $0 - (i32.load - (i32.add - (i32.load - (i32.sub - (i32.load - (i32.const 18100) - ) - (i32.const 12) - ) - ) - (i32.const 18124) - ) - ) - ) - (i32.const 24) - ) - ) - (i32.const 0) - (call_indirect (type $i32_i32_=>_i32) - (local.get $0) - (i32.const 10) - (i32.add - (i32.load offset=52 - (i32.load - (local.get $0) - ) - ) - (i32.const 422) - ) - ) - ) - ) - ) - (i32.const 0) - ) - (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (global.set $global$0 - (i32.const 32) - ) + (func $___stdio_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) (i32.store (i32.const 8) - (local.get $1) + (local.get $0) ) (i32.store (i32.const 12) - (local.get $2) + (local.get $1) ) (i32.store (local.tee $0 - (i32.const 32) + (global.get $global$0) ) (i32.const 1) ) @@ -180,119 +78,9 @@ ) (i32.const 1) ) - (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) - (i32.store8 - (i32.const 0) - (local.get $1) - ) - (drop - (call_indirect (type $i32_i32_i32_=>_i32) - (i32.const 0) - (i32.const 0) - (i32.const 1) - (i32.add - (i32.load offset=36 - (i32.load - (i32.add - (local.get $0) - (i32.const 32) - ) - ) - ) - (i32.const 8) - ) - ) - ) - (i32.const 0) - ) - (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (drop - (call_indirect (type $i32_i32_i32_=>_i32) - (i32.const 0) - (local.get $1) - (local.get $2) - (i32.add - (i32.load offset=36 - (i32.load offset=32 - (local.get $0) - ) - ) - (i32.const 8) - ) - ) - ) - (i32.const 0) - ) -) -total - [exports] : 2 - [funcs] : 6 - [globals] : 0 -1 - [imports] : 3 - [memory-data] : 28 - [table-data] : 429 - [tables] : 0 - [tags] : 0 - [total] : 547 -4 - [vars] : 2 - Binary : 12 - Block : 6 - Break : 3 - Call : 1 - CallIndirect : 4 - Const : 46 - Drop : 3 - If : 2 - Load : 16 - LocalGet : 14 -2 - LocalSet : 5 -1 - Loop : 1 - RefFunc : 429 - Store : 5 -(module - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $none_=>_i32 (func (result i32))) - (import "env" "memory" (memory $mimport$0 256 256)) - (data (i32.const 2948) "\03") - (data (i32.const 6828) "\04") - (data (i32.const 7028) "\0d\00\00\00\06") - (data (i32.const 10888) "hello, world!") - (data (i32.const 18100) "\b8\1a") - (data (i32.const 18128) ",I") - (data (i32.const 18732) "D\1b") - (data (i32.const 18764) "`\0b") - (import "env" "table" (table $timport$0 478 478 funcref)) - (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32))) - (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) - (export "_main" (func $_main)) - (export "_malloc" (func $_malloc)) - (func $b0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) - (i32.const 0) - ) - (func $_malloc (; has Stack IR ;) (param $0 i32) (result i32) - (i32.const 0) - ) (func $_main (; has Stack IR ;) (result i32) (local $0 i32) (local $1 i32) - (local.set $0 - (i32.const 10888) - ) - (loop $label$3 - (br_if $label$3 - (i32.load8_s - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - ) - ) - ) (local.set $1 (i32.load offset=24 (i32.add @@ -309,11 +97,28 @@ ) ) (if - (local.tee $0 - (i32.sub - (local.get $0) + (block (result i32) + (local.set $0 (i32.const 10888) ) + (loop $label$3 + (br_if $label$3 + (i32.load8_s + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + ) + ) + ) + (local.tee $0 + (i32.sub + (local.get $0) + (i32.const 10888) + ) + ) ) (block $label$2 (br_if $label$2 @@ -333,23 +138,40 @@ ) ) ) + (call $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc) + (i32.const 0) + ) + (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (global.set $global$0 + (i32.const 32) + ) + (call $___stdio_write + (local.get $1) + (local.get $2) + ) + ) + (func $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc (; has Stack IR ;) + (local $0 i32) + (local $1 i32) (block $label$1 (br_if $label$1 (if (result i32) (i32.load (i32.add - (local.tee $0 - (i32.load - (i32.add - (i32.load - (i32.sub - (i32.load - (i32.const 18100) + (local.tee $1 + (local.tee $0 + (i32.load + (i32.add + (i32.load + (i32.sub + (i32.load + (i32.const 18100) + ) + (i32.const 12) ) - (i32.const 12) ) + (i32.const 18124) ) - (i32.const 18124) ) ) ) @@ -358,7 +180,7 @@ ) (i32.const 0) (call_indirect (type $i32_i32_=>_i32) - (local.get $0) + (local.get $1) (i32.const 10) (i32.add (i32.load offset=52 @@ -372,32 +194,6 @@ ) ) ) - (i32.const 0) - ) - (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (i32.store - (i32.const 8) - (local.get $1) - ) - (i32.store - (i32.const 12) - (local.get $2) - ) - (i32.store - (i32.const 32) - (i32.const 1) - ) - (i32.store - (i32.const 40) - (i32.const 2) - ) - (drop - (call $import$0 - (i32.const 146) - (i32.const 32) - ) - ) - (i32.const 1) ) (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) (i32.store8 @@ -444,36 +240,37 @@ ) ) total + [events] : 0 [exports] : 2 - [funcs] : 6 - [globals] : 0 + [funcs] : 8 + [globals] : 1 [imports] : 3 [memory-data] : 28 [table-data] : 429 - [tables] : 0 - [tags] : 0 - [total] : 547 - [vars] : 2 - Binary : 12 - Block : 6 - Break : 3 - Call : 1 - CallIndirect : 4 - Const : 46 - Drop : 3 - If : 2 - Load : 16 - LocalGet : 14 - LocalSet : 5 - Loop : 1 - RefFunc : 429 - Store : 5 + [total] : 129 + [vars] : 4 + binary : 12 + block : 8 + break : 3 + call : 3 + call_indirect : 4 + const : 45 + drop : 3 + global.get : 1 + global.set : 1 + if : 2 + load : 16 + local.get : 18 + local.set : 7 + loop : 1 + store : 5 (module (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 2948) "\03") (data (i32.const 6828) "\04") @@ -484,8 +281,9 @@ (data (i32.const 18732) "D\1b") (data (i32.const 18764) "`\0b") (import "env" "table" (table $timport$0 478 478 funcref)) - (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32))) (elem (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) + (import "env" "___syscall146" (func $import$0 (param i32 i32) (result i32))) + (global $global$0 (mut i32) (i32.const 1)) (export "_main" (func $_main)) (export "_malloc" (func $_malloc)) (func $b0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) @@ -494,24 +292,36 @@ (func $_malloc (; has Stack IR ;) (param $0 i32) (result i32) (i32.const 0) ) - (func $_main (; has Stack IR ;) (result i32) - (local $0 i32) - (local $1 i32) - (local.set $0 - (i32.const 10888) + (func $___stdio_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (i32.store + (i32.const 8) + (local.get $0) ) - (loop $label$3 - (br_if $label$3 - (i32.load8_s - (local.tee $0 - (i32.add - (local.get $0) - (i32.const 1) - ) - ) - ) + (i32.store + (i32.const 12) + (local.get $1) + ) + (i32.store + (local.tee $0 + (global.get $global$0) ) + (i32.const 1) + ) + (i32.store offset=8 + (local.get $0) + (i32.const 2) ) + (drop + (call $import$0 + (i32.const 146) + (local.get $0) + ) + ) + (i32.const 1) + ) + (func $_main (; has Stack IR ;) (result i32) + (local $0 i32) + (local $1 i32) (local.set $1 (i32.load offset=24 (i32.add @@ -528,11 +338,28 @@ ) ) (if - (local.tee $0 - (i32.sub - (local.get $0) + (block (result i32) + (local.set $0 (i32.const 10888) ) + (loop $label$3 + (br_if $label$3 + (i32.load8_s + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + ) + ) + ) + (local.tee $0 + (i32.sub + (local.get $0) + (i32.const 10888) + ) + ) ) (block $label$2 (br_if $label$2 @@ -552,23 +379,40 @@ ) ) ) + (call $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc) + (i32.const 0) + ) + (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (global.set $global$0 + (i32.const 32) + ) + (call $___stdio_write + (local.get $1) + (local.get $2) + ) + ) + (func $__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEE3putEc (; has Stack IR ;) + (local $0 i32) + (local $1 i32) (block $label$1 (br_if $label$1 (if (result i32) (i32.load (i32.add - (local.tee $0 - (i32.load - (i32.add - (i32.load - (i32.sub - (i32.load - (i32.const 18100) + (local.tee $1 + (local.tee $0 + (i32.load + (i32.add + (i32.load + (i32.sub + (i32.load + (i32.const 18100) + ) + (i32.const 12) ) - (i32.const 12) ) + (i32.const 18124) ) - (i32.const 18124) ) ) ) @@ -577,7 +421,7 @@ ) (i32.const 0) (call_indirect (type $i32_i32_=>_i32) - (local.get $0) + (local.get $1) (i32.const 10) (i32.add (i32.load offset=52 @@ -591,32 +435,6 @@ ) ) ) - (i32.const 0) - ) - (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - (i32.store - (i32.const 8) - (local.get $1) - ) - (i32.store - (i32.const 12) - (local.get $2) - ) - (i32.store - (i32.const 32) - (i32.const 1) - ) - (i32.store - (i32.const 40) - (i32.const 2) - ) - (drop - (call $import$0 - (i32.const 146) - (i32.const 32) - ) - ) - (i32.const 1) ) (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) (i32.store8 diff -Nru binaryen-108/test/passes/dae_all-features.txt binaryen-99/test/passes/dae_all-features.txt --- binaryen-108/test/passes/dae_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dae_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,293 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $f64_=>_none (func (param f64))) + (table $0 2 2 funcref) + (elem (i32.const 0) $a9 $c8) + (export "a8" (func $a8)) + (func $a + (local $0 i32) + (local.set $0 + (i32.const 1) + ) + (nop) + ) + (func $b + (call $a) + ) + (func $a1 + (local $0 i32) + (local.set $0 + (i32.const 2) + ) + (unreachable) + ) + (func $b1 + (call $a1) + ) + (func $b11 + (call $a1) + ) + (func $a2 (param $x i32) + (drop + (local.get $x) + ) + ) + (func $b2 + (call $a2 + (i32.const 3) + ) + ) + (func $b22 + (call $a2 + (i32.const 4) + ) + ) + (func $a3 + (local $0 i32) + (drop + (i32.const -1) + ) + ) + (func $b3 + (call $a3) + ) + (func $b33 + (call $a3) + ) + (func $a4 (param $x i32) + (nop) + ) + (func $b4 + (call $a4 + (unreachable) + ) + ) + (func $b43 + (call $a4 + (i32.const 4) + ) + ) + (func $a5 + (local $0 f64) + (local $1 i32) + (local.set $0 + (f64.const 3.14159) + ) + (block + (local.set $1 + (i32.const 1) + ) + (block + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + ) + ) + ) + (func $b5 + (call $a5) + ) + (func $a6 (param $0 i32) + (local $1 f64) + (local.set $1 + (f64.const 3.14159) + ) + (block + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + ) + ) + (func $b6 + (call $a6 + (unreachable) + ) + ) + (func $a7 (param $0 f64) + (local $1 i32) + (local.set $1 + (i32.const 1) + ) + (block + (drop + (local.get $1) + ) + (drop + (local.get $0) + ) + ) + ) + (func $b7 + (call $a7 + (unreachable) + ) + ) + (func $a8 (param $x i32) + (nop) + ) + (func $b8 + (call $a8 + (i32.const 1) + ) + ) + (func $a9 (param $x i32) + (nop) + ) + (func $b9 + (call $a9 + (i32.const 1) + ) + ) + (func $a10 + (local $0 i32) + (local.set $0 + (i32.const 1) + ) + (block + (call $a10) + (call $a10) + ) + ) + (func $a11 + (local $0 i32) + (call $a11) + (call $a11) + ) + (func $a12 (param $x i32) + (drop + (local.get $x) + ) + (call $a12 + (i32.const 1) + ) + (call $a12 + (i32.const 2) + ) + ) + (func $c1 + (local $x i32) + (call $c2) + (call $c3) + (call $c3) + (drop + (call $c4) + ) + (local.set $x + (call $c4) + ) + (call $c5 + (unreachable) + ) + (call $c6) + (call $c7) + (drop + (call $c8) + ) + ) + (func $c2 + (drop + (i32.const 1) + ) + ) + (func $c3 + (drop + (i32.const 2) + ) + ) + (func $c4 (result i32) + (i32.const 3) + ) + (func $c5 (param $x i32) + (drop + (local.get $x) + ) + ) + (func $c6 + (unreachable) + ) + (func $c7 + (drop + (i32.const 4) + ) + (return) + ) + (func $c8 (result i32) + (i32.const 5) + ) +) +(module + (type $none_=>_none (func)) + (export "a" (func $0)) + (func $0 + (call $b) + ) + (func $b + (local $0 i32) + (drop + (block (result i32) + (local.set $0 + (i32.const 1) + ) + (local.get $0) + ) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (func $foo (param $x i32) (result i32) + (drop + (return_call $bar) + ) + (i32.const 42) + ) + (func $bar (result i32) + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (i32.const 7) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (table $0 1 1 funcref) + (func $foo (result i32) + (local $0 i32) + (local.set $0 + (i32.const 42) + ) + (drop + (return_call_indirect (type $none_=>_i32) + (i32.const 0) + ) + ) + ) + (func $bar + (drop + (call $foo) + ) + ) +) +(module + (type $funcref_i32_f64_=>_i64 (func (param funcref i32 f64) (result i64))) + (type $f32_=>_funcref (func (param f32) (result funcref))) + (export "export" (func $1)) + (func $0 (param $0 funcref) (param $1 i32) (param $2 f64) (result i64) + (nop) + (unreachable) + ) + (func $1 (param $0 f32) (result funcref) + (ref.func $0) + ) +) diff -Nru binaryen-108/test/passes/dae_all-features.wast binaryen-99/test/passes/dae_all-features.wast --- binaryen-108/test/passes/dae_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dae_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,174 @@ +(module + (export "a8" (func $a8)) + (table 2 2 funcref) + (elem (i32.const 0) $a9 $c8) + (func $a (param $x i32)) + (func $b + (call $a (i32.const 1)) ;; best case scenario + ) + (func $a1 (param $x i32) + (unreachable) + ) + (func $b1 + (call $a1 (i32.const 2)) ;; same value in both, so works + ) + (func $b11 + (call $a1 (i32.const 2)) + ) + (func $a2 (param $x i32) + (drop (local.get $x)) + ) + (func $b2 + (call $a2 (i32.const 3)) ;; different value! + ) + (func $b22 + (call $a2 (i32.const 4)) + ) + (func $a3 (param $x i32) + (drop (i32.const -1)) ;; diff value, but at least unused, so no need to send + ) + (func $b3 + (call $a3 (i32.const 3)) + ) + (func $b33 + (call $a3 (i32.const 4)) + ) + (func $a4 (param $x i32) ;; diff value, but with effects + ) + (func $b4 + (call $a4 (unreachable)) + ) + (func $b43 + (call $a4 (i32.const 4)) + ) + (func $a5 (param $x i32) (param $y f64) ;; optimize two + (drop (local.get $x)) + (drop (local.get $y)) + ) + (func $b5 + (call $a5 (i32.const 1) (f64.const 3.14159)) + ) + (func $a6 (param $x i32) (param $y f64) ;; optimize just one + (drop (local.get $x)) + (drop (local.get $y)) + ) + (func $b6 + (call $a6 (unreachable) (f64.const 3.14159)) + ) + (func $a7 (param $x i32) (param $y f64) ;; optimize just the other one + (drop (local.get $x)) + (drop (local.get $y)) + ) + (func $b7 + (call $a7 (i32.const 1) (unreachable)) + ) + (func $a8 (param $x i32)) ;; exported, do not optimize + (func $b8 + (call $a8 (i32.const 1)) + ) + (func $a9 (param $x i32)) ;; tabled, do not optimize + (func $b9 + (call $a9 (i32.const 1)) + ) + (func $a10 (param $x i32) ;; recursion + (call $a10 (i32.const 1)) + (call $a10 (i32.const 1)) + ) + (func $a11 (param $x i32) ;; partially successful recursion + (call $a11 (i32.const 1)) + (call $a11 (i32.const 2)) + ) + (func $a12 (param $x i32) ;; unsuccessful recursion + (drop (local.get $x)) + (call $a12 (i32.const 1)) + (call $a12 (i32.const 2)) + ) + ;; return values + (func $c1 + (local $x i32) + (drop (call $c2)) + (drop (call $c3)) + (drop (call $c3)) + (drop (call $c4)) + (local.set $x (call $c4)) + (drop (call $c5 (unreachable))) + (drop (call $c6)) + (drop (call $c7)) + (drop (call $c8)) + ) + (func $c2 (result i32) + (i32.const 1) + ) + (func $c3 (result i32) + (i32.const 2) + ) + (func $c4 (result i32) + (i32.const 3) + ) + (func $c5 (param $x i32) (result i32) + (local.get $x) + ) + (func $c6 (result i32) + (unreachable) + ) + (func $c7 (result i32) + (return (i32.const 4)) + ) + (func $c8 (result i32) + (i32.const 5) + ) +) +(module ;; both operations at once: remove params and return value + (func "a" + (drop + (call $b + (i32.const 1) + ) + ) + ) + (func $b (param $x i32) (result i32) + (local.get $x) + ) +) +(module ;; tail calls inhibit dropped result removal + (func $foo (param $x i32) (result i32) + (drop + (return_call $bar + (i32.const 0) + ) + ) + (i32.const 42) + ) + (func $bar (param $x i32) (result i32) + (i32.const 7) + ) +) +(module ;; indirect tail calls inhibit dropped result removal + (type $T (func (result i32))) + (table 1 1 funcref) + (func $foo (param $x i32) (result i32) + (drop + (return_call_indirect (type $T) + (i32.const 0) + ) + ) + ) + (func $bar + (drop + (call $foo + (i32.const 42) + ) + ) + ) +) +(module + (func $0 (param $0 funcref) (param $1 i32) (param $2 f64) (result i64) + (nop) + (unreachable) + ) + (func "export" (param $0 f32) (result funcref) + ;; a ref.func should prevent us from changing the type of a function, as it + ;; may escape + (ref.func $0) + ) +) diff -Nru binaryen-108/test/passes/dae-optimizing.txt binaryen-99/test/passes/dae-optimizing.txt --- binaryen-108/test/passes/dae-optimizing.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dae-optimizing.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,43 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $f64_f32_f32_f64_f32_i32_i32_f64_=>_i32 (func (param f64 f32 f32 f64 f32 i32 i32 f64) (result i32))) + (type $none_=>_f32 (func (result f32))) + (global $global$0 (mut i32) (i32.const 10)) + (func $0 (result i32) + (local $0 i32) + (local $1 i32) + (drop + (if (result f32) + (local.tee $0 + (i32.const 33554432) + ) + (loop $label$2 (result f32) + (if + (global.get $global$0) + (return + (local.get $0) + ) + ) + (local.set $0 + (local.get $1) + ) + (local.set $1 + (i32.const 0) + ) + (br_if $label$2 + (local.get $0) + ) + (f32.const 1) + ) + (call $1) + ) + ) + (i32.const -11) + ) + (func $1 (result f32) + (f32.const 0) + ) + (func $2 (param $0 f64) (param $1 f32) (param $2 f32) (param $3 f64) (param $4 f32) (param $5 i32) (param $6 i32) (param $7 f64) (result i32) + (call $0) + ) +) diff -Nru binaryen-108/test/passes/dae-optimizing.wast binaryen-99/test/passes/dae-optimizing.wast --- binaryen-108/test/passes/dae-optimizing.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dae-optimizing.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,60 @@ +(module + (type $0 (func (param f32) (result f32))) + (type $1 (func (param f64 f32 f32 f64 f32 i64 f64) (result i32))) + (type $2 (func (param f64 f32 f32 f64 f32 i32 i32 f64) (result i32))) + (global $global$0 (mut i32) (i32.const 10)) + (func $0 (; 0 ;) (type $1) (param $0 f64) (param $1 f32) (param $2 f32) (param $3 f64) (param $4 f32) (param $5 i64) (param $6 f64) (result i32) + (local $7 i32) + (local $8 i32) + (if + (local.tee $7 + (i32.const 33554432) + ) + (drop + (loop $label$2 (result f32) + (if + (global.get $global$0) + (return + (local.get $7) + ) + ) + (local.set $8 + (block $label$4 (result i32) + (drop + (local.tee $7 + (local.get $8) + ) + ) + (i32.const 0) + ) + ) + (br_if $label$2 + (local.get $7) + ) + (f32.const 1) + ) + ) + (drop + (call $1 + (f32.const 1) + ) + ) + ) + (i32.const -11) + ) + (func $1 (; 1 ;) (type $0) (param $0 f32) (result f32) + (f32.const 0) + ) + (func $2 (; 2 ;) (type $2) (param $0 f64) (param $1 f32) (param $2 f32) (param $3 f64) (param $4 f32) (param $5 i32) (param $6 i32) (param $7 f64) (result i32) + (call $0 + (f64.const 1) + (f32.const 1) + (f32.const 1) + (f64.const 1) + (f32.const 1) + (i64.const 1) + (f64.const 1) + ) + ) +) + diff -Nru binaryen-108/test/passes/dce_all-features.txt binaryen-99/test/passes/dce_all-features.txt --- binaryen-108/test/passes/dce_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dce_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,648 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $f32_i64_=>_none (func (param f32 i64))) + (type $f32_i64_=>_i32 (func (param f32 i64) (result i32))) + (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) + (memory $0 10) + (table $0 1 1 funcref) + (elem (i32.const 0) $call-me) + (global $x (mut i32) (i32.const 0)) + (func $call-me (param $0 i32) (param $1 i32) + (nop) + ) + (func $code-to-kill + (local $x i32) + (block $out + (br $out) + ) + (if + (i32.const 0) + (unreachable) + ) + (if + (i32.const 0) + (block $out3 + (return) + ) + ) + (block $out4 + (br_table $out4 $out4 $out4 $out4 + (i32.const 4) + ) + ) + (block $out5 + (br_if $out5 + (i32.const 3) + ) + (drop + (i32.const 0) + ) + ) + (if + (i32.const 0) + (block $block4 + (if + (i32.const 0) + (unreachable) + (unreachable) + ) + ) + ) + (if + (i32.const 0) + (unreachable) + ) + (if + (i32.const 0) + (unreachable) + ) + (if + (i32.const 0) + (unreachable) + ) + (block $out16 + (block $in + (br_if $out16 + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.const 0) + (block $block11 + (block $out18 + (block $in19 + (br_if $in19 + (i32.const 1) + ) + ) + (unreachable) + ) + ) + ) + (block $out20 + (block $in21 + (br_table $out20 $in21 + (i32.const 1) + ) + ) + (unreachable) + ) + (block $out22 + (block $in23 + (br_table $in23 $out22 + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.const 0) + (block $block13 + (block $out25 + (block $in26 + (br_table $in26 $in26 + (i32.const 1) + ) + ) + (unreachable) + ) + ) + ) + (if + (i32.const 0) + (block $block15 + (drop + (i32.const 10) + ) + (drop + (i32.const 42) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (unreachable) + ) + (block $out29 + (loop $in30 + (br_if $out29 + (i32.const 1) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block $block20 + (loop $in32 + (br_if $in32 + (i32.const 1) + ) + (unreachable) + ) + ) + ) + (if + (i32.const 1) + (block + (drop + (i32.const 123) + ) + (unreachable) + ) + ) + (if + (i32.const 2) + (unreachable) + ) + (if + (i32.const 3) + (unreachable) + ) + (if + (i32.const -1) + (block + (drop + (i32.const 123) + ) + (drop + (i32.const 456) + ) + (unreachable) + ) + ) + (if + (i32.const -2) + (block + (drop + (i32.const 139) + ) + (unreachable) + ) + ) + (if + (i32.const -3) + (block + (drop + (i32.const 246) + ) + (unreachable) + ) + ) + (if + (i32.const -4) + (unreachable) + ) + (if + (i32.const 11) + (unreachable) + ) + (if + (i32.const 22) + (unreachable) + ) + (if + (i32.const 33) + (block + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + (if + (i32.const 44) + (unreachable) + ) + (if + (i32.const 55) + (unreachable) + ) + (if + (i32.const 66) + (unreachable) + ) + (if + (i32.const 77) + (unreachable) + ) + (if + (i32.const 88) + (block + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + (if + (i32.const 99) + (unreachable) + ) + (if + (i32.const 100) + (block + (drop + (i32.const 123) + ) + (drop + (i32.const 456) + ) + (unreachable) + ) + ) + (if + (i32.const 101) + (block + (drop + (i32.const 123) + ) + (unreachable) + ) + ) + (if + (i32.const 102) + (unreachable) + ) + (drop + (i32.const 1337) + ) + ) + (func $killer + (unreachable) + ) + (func $target + (drop + (i32.const 2000) + ) + ) + (func $typed-block-none-then-unreachable (result i32) + (block $top-typed + (block $switch$0 + (return + (i32.const 0) + ) + ) + ) + ) + (func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32) + (block $switch$7 + (block $switch-default$10 + (block $switch-case$9 + (block $switch-case$8 + (br_table $switch-case$9 $switch-case$8 $switch-default$10 + (i32.const -1) + ) + ) + ) + (return + (local.get $$$0) + ) + ) + (return + (local.get $$$0) + ) + ) + ) + (func $global + (unreachable) + ) + (func $ret (result i32) + (return + (i32.const 0) + ) + ) + (func $unreachable-br (result i32) + (block $out (result i32) + (br $out + (i32.const 0) + ) + ) + ) + (func $unreachable-br-loop (result i32) + (loop $out + (br $out) + ) + ) + (func $unreachable-block-ends-switch (result i32) + (block $label$0 + (block $label$3 + (nop) + (unreachable) + ) + ) + ) + (func $unreachable-block-ends-br_if (result i32) + (block $label$0 + (block $label$2 + (nop) + (unreachable) + ) + ) + ) + (func $unreachable-brs-3 (result i32) + (block $label$0 (result i32) + (br $label$0 + (i32.const 18) + ) + ) + ) + (func $unreachable-brs-4 (param $var$0 i32) (result i32) + (drop + (i32.const 1) + ) + (block $label$0 + (block $label$1 + (block + (drop + (i32.const 4104) + ) + (unreachable) + ) + ) + ) + ) + (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) + (local $2 i64) + (if (result i64) + (i64.eqz + (local.get $var$0) + ) + (block $label$0 (result i64) + (local.get $var$1) + ) + (block $label$1 + (block + (drop + (i64.sub + (local.get $var$0) + (i64.const 1) + ) + ) + (block + (drop + (block $block (result i64) + (local.set $2 + (local.get $var$0) + ) + (nop) + (local.get $2) + ) + ) + (unreachable) + ) + ) + ) + ) + ) + (func $br-gone-means-block-type-changes-then-refinalize-at-end-is-too-late (param $var$0 i32) (result i32) + (block $label$0 + (block $block + (nop) + (unreachable) + ) + ) + ) + (func $br-with-unreachable-value-should-not-give-a-block-a-value (param $var$0 i32) (result i32) + (block $label$0 (result i32) + (block $block + (drop + (br_if $label$0 + (i32.const 8) + (local.get $var$0) + ) + ) + (unreachable) + ) + ) + ) + (func $replace-br-value-of-i32-with-unreachable (result i32) + (block $label$0 + (block $label$1 + (nop) + (unreachable) + ) + ) + ) + (func $shorten-block-requires-sync-refinalize (param $var$0 i32) (param $var$1 i32) + (unreachable) + ) + (func $block-with-type-but-is-unreachable (param $var$0 i32) (result i32) + (block $label$0 + (block $block + (nop) + (unreachable) + ) + ) + ) + (func $if-with-type-but-is-unreachable (param $var$0 i32) (result i32) + (block $label$0 + (if + (local.get $var$0) + (unreachable) + (unreachable) + ) + ) + ) + (func $unreachable-loop + (unreachable) + ) + (func $br-block-from-unary (result i32) + (block $label$6 (result i32) + (block $label$7 + (br $label$6 + (i32.const 8) + ) + ) + ) + ) + (func $replace-unary-with-br-child + (drop + (block $label$6 (result i32) + (br $label$6 + (i32.const 8) + ) + ) + ) + ) + (func $br_if-unreach-then-br_if-normal + (block $out + (nop) + (unreachable) + ) + ) + (func $replace-with-unreachable-affects-parent (param $var$0 f32) (param $var$1 i64) + (block $top + (block + (drop + (i64.const 0) + ) + (if + (block $block (result i32) + (call $replace-with-unreachable-affects-parent + (f32.const 1) + (i64.const -15917430362925035) + ) + (i32.const 1) + ) + (unreachable) + (unreachable) + ) + ) + ) + ) + (func $replace-block-changes-later-when-if-goes + (block $top + (global.set $x + (i32.const 0) + ) + (block $inner + (drop + (call $helper + (f32.const 1) + (i64.const -15917430362925035) + ) + ) + (unreachable) + ) + ) + ) + (func $helper (param $var$0 f32) (param $var$1 i64) (result i32) + (i32.const 0) + ) +) +(module + (type $none_=>_none (func)) + (global $global (mut f64) (f64.const 0)) + (func $0 + (if + (i32.const 0) + (unreachable) + (unreachable) + ) + ) +) +(module + (type $none_=>_none (func)) + (func $0 + (local $local f64) + (if + (i32.const 0) + (unreachable) + (unreachable) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (event $e (attr 0) (param)) + (func $foo + (nop) + ) + (func $try_unreachable + (try + (do + (unreachable) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (call $foo) + ) + (func $catch_unreachable + (try + (do + (nop) + ) + (catch + (unreachable) + ) + ) + (call $foo) + ) + (func $both_unreachable + (try + (do + (unreachable) + ) + (catch + (unreachable) + ) + ) + ) + (func $throw + (block $label$0 + (block $label$1 + (throw $e + ) + ) + ) + ) + (func $rethrow + (block $label$0 + (block $label$1 + (rethrow + (ref.null exn) + ) + ) + ) + ) + (func $unnecessary-concrete-block (result i32) + (block $foo + (nop) + (unreachable) + ) + ) + (func $necessary-concrete-block (result i32) + (block $foo (result i32) + (br $foo + (i32.const 1) + ) + ) + ) + (func $unnecessary-concrete-if (result i32) + (if + (i32.const 0) + (return + (i32.const 1) + ) + (unreachable) + ) + ) + (func $unnecessary-concrete-try (result i32) + (try + (do + (unreachable) + ) + (catch + (unreachable) + ) + ) + ) + (func $note-loss-of-if-children + (block $label$1 + (block $label$2 + (nop) + (unreachable) + ) + ) + ) + (func $note-loss-of-non-control-flow-children + (block $out + (block $block + (nop) + (unreachable) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/dce_all-features.wast binaryen-99/test/passes/dce_all-features.wast --- binaryen-108/test/passes/dce_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dce_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,870 @@ +(module + (memory 10) + (type $ii (func (param i32 i32))) + (type $1 (func)) + (table 1 1 funcref) + (elem (i32.const 0) $call-me) + (global $x (mut i32) (i32.const 0)) + (func $call-me (type $ii) (param $0 i32) (param $1 i32) + (nop) + ) + (func $code-to-kill (type $1) + (local $x i32) + (block $out + (br $out) + (drop + (i32.const 0) + ) + (if + (i32.const 1) + (drop + (i32.const 2) + ) + ) + (br_table $out $out $out $out + (i32.const 3) + ) + (call $code-to-kill) + ) + (if + (i32.const 0) + (block $out + (unreachable) + (drop + (i32.const 0) + ) + ) + ) + (if + (i32.const 0) + (block $out + (return) + (drop + (i32.const 0) + ) + ) + ) + (block $out + (br_table $out $out $out $out + (i32.const 4) + ) + (drop + (i32.const 0) + ) + ) + (block $out + (br_if $out + (i32.const 3) + ) + (drop + (i32.const 0) + ) + ) + (if + (i32.const 0) + (block $block4 + (if + (i32.const 0) + (block $out + (unreachable) + (drop + (i32.const 0) + ) + ) + (block $out + (unreachable) + (drop + (i32.const 0) + ) + ) + ) + (drop + (i32.const 0) + ) + ) + ) + (if + (i32.const 0) + (drop + (block $out (result i32) + (br $out + (unreachable) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (if + (i32.const 0) + (drop + (block $out (result i32) + (br_if $out + (unreachable) + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (if + (i32.const 0) + (drop + (block $out (result i32) + (br_if $out + (unreachable) + (unreachable) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (block $out + (block $in + (br_if $out + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.const 0) + (block $block11 + (block $out + (block $in + (br_if $in + (i32.const 1) + ) + ) + (unreachable) + ) + (drop + (i32.const 10) + ) + ) + ) + (block $out + (block $in + (br_table $out $in + (i32.const 1) + ) + ) + (unreachable) + ) + (block $out + (block $in + (br_table $in $out + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.const 0) + (block $block13 + (block $out + (block $in + (br_table $in $in + (i32.const 1) + ) + ) + (unreachable) + ) + (drop + (i32.const 10) + ) + ) + ) + (if + (i32.const 0) + (block $block15 + (drop + (i32.const 10) + ) + (drop + (i32.const 42) + ) + (unreachable) + (return + (unreachable) + ) + (unreachable) + (return) + ) + ) + (if + (i32.const 0) + (loop $loop-in18 + (unreachable) + ) + ) + (block $out + (loop $in + (br_if $out + (i32.const 1) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block $block20 + (loop $in + (br_if $in + (i32.const 1) + ) + (unreachable) + ) + (drop + (i32.const 10) + ) + ) + ) + (if + (i32.const 1) + (call $call-me + (i32.const 123) + (unreachable) + ) + ) + (if + (i32.const 2) + (call $call-me + (unreachable) + (i32.const 0) + ) + ) + (if + (i32.const 3) + (call $call-me + (unreachable) + (unreachable) + ) + ) + (if + (i32.const -1) + (call_indirect (type $ii) + (i32.const 123) + (i32.const 456) + (unreachable) + ) + ) + (if + (i32.const -2) + (call_indirect (type $ii) + (i32.const 139) + (unreachable) + (i32.const 0) + ) + ) + (if + (i32.const -3) + (call_indirect (type $ii) + (i32.const 246) + (unreachable) + (unreachable) + ) + ) + (if + (i32.const -4) + (call_indirect (type $ii) + (unreachable) + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 11) + (local.set $x + (unreachable) + ) + ) + (if + (i32.const 22) + (drop + (i32.load + (unreachable) + ) + ) + ) + (if + (i32.const 33) + (i32.store + (i32.const 0) + (unreachable) + ) + ) + (if + (i32.const 44) + (i32.store + (unreachable) + (i32.const 0) + ) + ) + (if + (i32.const 55) + (i32.store + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 66) + (drop + (i32.eqz + (unreachable) + ) + ) + ) + (if + (i32.const 77) + (drop + (i32.add + (unreachable) + (i32.const 0) + ) + ) + ) + (if + (i32.const 88) + (drop + (i32.add + (i32.const 0) + (unreachable) + ) + ) + ) + (if + (i32.const 99) + (i32.add + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 100) + (drop + (select + (i32.const 123) + (i32.const 456) + (unreachable) + ) + ) + ) + (if + (i32.const 101) + (drop + (select + (i32.const 123) + (unreachable) + (i32.const 456) + ) + ) + ) + (if + (i32.const 102) + (drop + (select + (unreachable) + (i32.const 123) + (i32.const 456) + ) + ) + ) + (drop + (i32.const 1337) + ) + ) + (func $killer (type $1) + (unreachable) + (drop + (i32.const 1000) + ) + ) + (func $target (type $1) + (drop + (i32.const 2000) + ) + ) + (func $typed-block-none-then-unreachable (result i32) + (block $top-typed (result i32) + (block $switch$0 ;; this looks like it can be broken to, so it gets type 'none' + (return + (i32.const 0) + ) + (br $switch$0) ;; this is not reachable, so dce cleans it up, changing $switch$0's type + ) + (return ;; and this is cleaned up as well, leaving $top-typed in need of a type change + (i32.const 1) + ) + ) + ) + (func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32) + (block $switch$7 + (block $switch-default$10 + (block $switch-case$9 + (block $switch-case$8 + (br_table $switch-case$9 $switch-case$8 $switch-default$10 + (i32.const -1) + ) + ) + ) + (return + (local.get $$$0) + ) + (br $switch$7) + ) + (return + (local.get $$$0) + ) + ) + (return + (i32.const 0) + ) + ) + (func $global + (unreachable) + (drop (global.get $x)) + (global.set $x (i32.const 1)) + ) + (func $ret (result i32) + (return + (i32.const 0) + ) + (nop) + (i32.const 0) + ) + (func $unreachable-br (result i32) + (block $out (result i32) + (br $out + (br $out (i32.const 0)) + ) + ) + ) + (func $unreachable-br-loop (result i32) + (loop $out + (br $out) + ) + ) + (func $unreachable-block-ends-switch (result i32) + (block $label$0 (result i32) + (block $label$3 + (nop) + (br_table $label$3 + (unreachable) + ) + (unreachable) + ) + (i32.const 19) + ) + ) + (func $unreachable-block-ends-br_if (result i32) + (block $label$0 (result i32) + (block $label$2 + (nop) + (br_if $label$2 + (unreachable) + ) + (unreachable) + ) + (i32.const 19) + ) + ) + (func $unreachable-brs-3 (result i32) + (block $label$0 (result i32) + (br $label$0 + (memory.grow + (br $label$0 + (i32.const 18) + ) + ) + ) + (i32.const 21) + ) + ) + (func $unreachable-brs-4 (param $var$0 i32) (result i32) + (i32.add + (i32.const 1) + (block $label$0 (result i32) + (br $label$0 + (block $label$1 (result i32) ;; this block is declared i32, but we can see it is unreachable + (drop + (br_if $label$0 + (i32.const 4104) + (unreachable) + ) + ) + (i32.const 4) + ) + ) + (i32.const 16) + ) + ) + ) + (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) + (local $2 i64) + (if (result i64) + (i64.eqz + (local.get $var$0) + ) + (block $label$0 (result i64) + (local.get $var$1) + ) + (block $label$1 (result i64) + (call $call-unreach + (i64.sub + (local.get $var$0) + (i64.const 1) + ) + (i64.mul + (block (result i64) + (local.set $2 + (local.get $var$0) + ) + (nop) + (local.get $2) + ) + (unreachable) + ) + ) + ) + ) + ) + (func $br-gone-means-block-type-changes-then-refinalize-at-end-is-too-late (param $var$0 i32) (result i32) + (block $label$0 (result i32) + (br $label$0 + (block (result i32) + (nop) + (drop + (br_if $label$0 + (unreachable) + (local.get $var$0) + ) + ) + (i32.const 4) + ) + ) + ) + ) + (func $br-with-unreachable-value-should-not-give-a-block-a-value (param $var$0 i32) (result i32) + (block $label$0 (result i32) + (br $label$0 + (block (result i32) ;; turns into unreachable when refinalized + (drop + (br_if $label$0 + (i32.const 8) + (local.get $var$0) + ) + ) + (unreachable) + ) + ) + (i32.const 16) + ) + ) + (func $replace-br-value-of-i32-with-unreachable (result i32) + (block $label$0 (result i32) + (br $label$0 + (block $label$1 (result i32) + (nop) + (unreachable) + ) + ) + ) + ) + (func $shorten-block-requires-sync-refinalize (param $var$0 i32) (param $var$1 i32) + (block $label$0 + (unreachable) + (if + (unreachable) + (br_if $label$0 + (local.get $var$1) + ) + ) + ) + ) + (func $block-with-type-but-is-unreachable (param $var$0 i32) (result i32) + (block $label$0 (result i32) + (br $label$0 + (block $block (result i32) + (nop) + (unreachable) + ) + ) + ) + ) + (func $if-with-type-but-is-unreachable (param $var$0 i32) (result i32) + (block $label$0 (result i32) + (br $label$0 + (if (result i32) + (local.get $var$0) + (unreachable) + (unreachable) + ) + ) + ) + ) + (func $unreachable-loop + (loop $label$2 + (unreachable) + (br $label$2) + ) + ) + (func $br-block-from-unary (result i32) + (block $label$6 (result i32) + (i32.ctz + (block $label$7 (result i32) + (br $label$6 + (i32.const 8) + ) + ) + ) + ) + ) + (func $replace-unary-with-br-child + (drop + (block $label$6 (result i32) + (i32.ctz + (br $label$6 + (i32.const 8) + ) + ) + ) + ) + ) + (func $br_if-unreach-then-br_if-normal + (block $out + (nop) + (br_if $out + (unreachable) + ) + (br_if $out + (i32.const 1) + ) + ) + ) + (func $replace-with-unreachable-affects-parent (param $var$0 f32) (param $var$1 i64) + (block $top + (drop + (f32.load offset=4 + (i64.ne + (i64.const 0) + (if (result i64) + (block (result i32) + (call $replace-with-unreachable-affects-parent + (f32.const 1) + (i64.const -15917430362925035) + ) + (i32.const 1) + ) + (unreachable) + (unreachable) + ) + ) + ) + ) + (nop) ;; this is not reachable due to the above code, so we replace it with unreachable. type should go to parent + ) + ) + (func $replace-block-changes-later-when-if-goes + (block $top ;; and so should this + (global.set $x + (i32.const 0) + ) + (drop + (f32.load offset=4 + (i64.ne + (block $inner (result i64) ;; this becomes unreachable + (drop + (call $helper + (f32.const 1) + (i64.const -15917430362925035) + ) + ) + (unreachable) + ) + (i64.const 0) + ) + ) + ) + (if + (i32.load16_s offset=22 align=1 + (i32.const 0) + ) + (br $top) ;; this keeps the block none after the inner block gets unreachable. but it will vanish into unreachable itself + (unreachable) + ) + ) + ) + (func $helper (param $var$0 f32) (param $var$1 i64) (result i32) + (i32.const 0) + ) +) +;; if goes to unreachable, need to propagate that up to the global.set +(module + (global $global (mut f64) (f64.const 0)) + (func $0 + (global.set $global + (if (result f64) + (i32.const 0) + (unreachable) + (unreachable) + ) + ) + ) +) +(module + (func $0 + (local $local f64) + (local.set $local + (if (result f64) + (i32.const 0) + (unreachable) + (unreachable) + ) + ) + ) +) + +;; Exception handling instruction support +;; If either try body or catch body is reachable, the whole try construct is +;; reachable +(module + (func $foo) + (event $e (attr 0)) + + (func $try_unreachable + (try + (do + (unreachable) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (call $foo) ;; shouldn't be dce'd + ) + + (func $catch_unreachable + (try + (do) + (catch + (unreachable) + ) + ) + (call $foo) ;; shouldn't be dce'd + ) + + (func $both_unreachable + (try + (do + (unreachable) + ) + (catch + (unreachable) + ) + ) + (call $foo) ;; should be dce'd + ) + + (func $throw + (drop + (block $label$0 (result externref) + (if + (i32.clz + (block $label$1 (result i32) + (throw $e) + ) + ) + (nop) + ) + (ref.null extern) + ) + ) + ) + + (func $rethrow + (drop + (block $label$0 (result externref) + (if + (i32.clz + (block $label$1 (result i32) + (rethrow + (ref.null exn) + ) + ) + ) + (nop) + ) + (ref.null extern) + ) + ) + ) + + (func $unnecessary-concrete-block (result i32) + (block $foo (result i32) ;; unnecessary type + (nop) + (unreachable) + ) + ) + (func $necessary-concrete-block (result i32) + (block $foo (result i32) + (br $foo (i32.const 1)) + (unreachable) + ) + ) + (func $unnecessary-concrete-if (result i32) + (if (result i32) ;; unnecessary type + (i32.const 0) + (return (i32.const 1)) + (unreachable) + ) + ) + (func $unnecessary-concrete-try (result i32) + (try (result i32) + (do + (unreachable) + ) + (catch + (unreachable) + ) + ) + ) + (func $note-loss-of-if-children + (block $label$1 + (if ;; begins unreachable - type never changes - but after the condition + ;; becomes unreachable, it will lose the children, which means no more + ;; br to the outer block, changing that type. + (block $label$2 (result i32) + (nop) + (unreachable) + ) + (unreachable) + (br $label$1) + ) + ) + ) + (func $note-loss-of-non-control-flow-children + (block $out + (drop + (i32.add + (block (result i32) + (nop) + (unreachable) + ) + (br $out) ;; when this is removed as dead, the block becomes unreachable + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/dce_vacuum_remove-unused-names.txt binaryen-99/test/passes/dce_vacuum_remove-unused-names.txt --- binaryen-108/test/passes/dce_vacuum_remove-unused-names.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dce_vacuum_remove-unused-names.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,25 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $i64_=>_i64 (func (param i64) (result i64))) + (type $f32_f32_=>_f32 (func (param f32 f32) (result f32))) + (func $__Z12serveroptionPc (result i32) + (return + (i32.const 0) + ) + ) + (func $drop-unreachable (param $var$0 f32) (param $var$1 f32) (result f32) + (unreachable) + ) + (func $set-unreachable (param $var$0 i64) (result i64) + (local $var$1 i64) + (local $var$2 i64) + (if + (i64.eq + (local.get $var$1) + (i64.const 0) + ) + (unreachable) + (unreachable) + ) + ) +) diff -Nru binaryen-108/test/passes/dce_vacuum_remove-unused-names.wast binaryen-99/test/passes/dce_vacuum_remove-unused-names.wast --- binaryen-108/test/passes/dce_vacuum_remove-unused-names.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dce_vacuum_remove-unused-names.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,51 @@ +(module + (func $__Z12serveroptionPc (result i32) + (block $switch$0 + (return + (i32.const 0) + ) + (br $switch$0) + ) + (return + (i32.const 0) + ) + ) + (func $drop-unreachable (param $var$0 f32) (param $var$1 f32) (result f32) + (block $label$0 (result f32) + (loop $label$2 + (drop + (unreachable) + ) + (unreachable) + ) + (local.get $var$1) + ) + ) + + (func $set-unreachable (param $var$0 i64) (result i64) + (local $var$1 i64) + (local $var$2 i64) + (block $label$0 (result i64) + (block $label$1 + (loop $label$2 + (if + (i64.eq + (local.get $var$1) + (i64.const 0) + ) + (unreachable) + (local.set $var$2 + (i64.mul + (unreachable) + (local.get $var$2) + ) + ) + ) + (br $label$2) + ) + ) + (local.get $var$2) + ) + ) +) + diff -Nru binaryen-108/test/passes/dealign64.passes binaryen-99/test/passes/dealign64.passes --- binaryen-108/test/passes/dealign64.passes 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dealign64.passes 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +dealign_enable-memory64 diff -Nru binaryen-108/test/passes/dealign64.txt binaryen-99/test/passes/dealign64.txt --- binaryen-108/test/passes/dealign64.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dealign64.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,33 @@ +(module + (type $none_=>_none (func)) + (memory $0 i64 1 1) + (func $test + (drop + (i32.load align=1 + (i64.const 4) + ) + ) + (drop + (i32.load align=1 + (i64.const 8) + ) + ) + (drop + (i32.load align=1 + (i64.const 12) + ) + ) + (i32.store align=1 + (i64.const 16) + (i32.const 28) + ) + (i32.store align=1 + (i64.const 20) + (i32.const 32) + ) + (i32.store align=1 + (i64.const 24) + (i32.const 36) + ) + ) +) diff -Nru binaryen-108/test/passes/dealign64.wast binaryen-99/test/passes/dealign64.wast --- binaryen-108/test/passes/dealign64.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dealign64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,11 @@ +(module + (memory $0 i64 1 1) + (func $test + (drop (i32.load (i64.const 4))) + (drop (i32.load align=1 (i64.const 8))) + (drop (i32.load align=2 (i64.const 12))) + (i32.store (i64.const 16) (i32.const 28)) + (i32.store align=1 (i64.const 20) (i32.const 32)) + (i32.store align=2 (i64.const 24) (i32.const 36)) + ) +) diff -Nru binaryen-108/test/passes/dealign.txt binaryen-99/test/passes/dealign.txt --- binaryen-108/test/passes/dealign.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dealign.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,33 @@ +(module + (type $none_=>_none (func)) + (memory $0 1 1) + (func $test + (drop + (i32.load align=1 + (i32.const 4) + ) + ) + (drop + (i32.load align=1 + (i32.const 8) + ) + ) + (drop + (i32.load align=1 + (i32.const 12) + ) + ) + (i32.store align=1 + (i32.const 16) + (i32.const 28) + ) + (i32.store align=1 + (i32.const 20) + (i32.const 32) + ) + (i32.store align=1 + (i32.const 24) + (i32.const 36) + ) + ) +) diff -Nru binaryen-108/test/passes/dealign.wast binaryen-99/test/passes/dealign.wast --- binaryen-108/test/passes/dealign.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/dealign.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,11 @@ +(module + (memory $0 1 1) + (func $test + (drop (i32.load (i32.const 4))) + (drop (i32.load align=1 (i32.const 8))) + (drop (i32.load align=2 (i32.const 12))) + (i32.store (i32.const 16) (i32.const 28)) + (i32.store align=1 (i32.const 20) (i32.const 32)) + (i32.store align=2 (i32.const 24) (i32.const 36)) + ) +) diff -Nru binaryen-108/test/passes/denan.txt binaryen-99/test/passes/denan.txt --- binaryen-108/test/passes/denan.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/denan.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,157 @@ +(module + (type $f32_=>_f32 (func (param f32) (result f32))) + (type $f64_=>_f64 (func (param f64) (result f64))) + (type $i32_f32_i64_f64_=>_none (func (param i32 f32 i64 f64))) + (type $f32_f64_=>_none (func (param f32 f64))) + (global $global$1 (mut f32) (f32.const 0)) + (global $global$2 (mut f32) (f32.const 12.34000015258789)) + (func $foo32 (param $x f32) (result f32) + (local.set $x + (call $deNan32 + (local.get $x) + ) + ) + (call $deNan32 + (call $foo32 + (local.get $x) + ) + ) + ) + (func $foo64 (param $x f64) (result f64) + (local.set $x + (call $deNan64 + (local.get $x) + ) + ) + (call $deNan64 + (call $foo64 + (local.get $x) + ) + ) + ) + (func $various (param $x i32) (param $y f32) (param $z i64) (param $w f64) + (local.set $y + (call $deNan32 + (local.get $y) + ) + ) + (local.set $w + (call $deNan64 + (local.get $w) + ) + ) + (nop) + ) + (func $ignore-local.get (param $f f32) (param $d f64) + (local.set $f + (call $deNan32 + (local.get $f) + ) + ) + (local.set $d + (call $deNan64 + (local.get $d) + ) + ) + (drop + (local.get $f) + ) + (drop + (local.get $d) + ) + (local.set $f + (local.get $f) + ) + (local.set $d + (local.get $d) + ) + (drop + (local.get $f) + ) + (drop + (local.get $d) + ) + (drop + (call $deNan32 + (f32.abs + (local.get $f) + ) + ) + ) + (drop + (call $deNan64 + (f64.abs + (local.get $d) + ) + ) + ) + (local.set $f + (call $deNan32 + (f32.abs + (local.get $f) + ) + ) + ) + (local.set $d + (call $deNan64 + (f64.abs + (local.get $d) + ) + ) + ) + (drop + (local.get $f) + ) + (drop + (local.get $d) + ) + ) + (func $tees (param $x f32) (result f32) + (local.set $x + (call $deNan32 + (local.get $x) + ) + ) + (local.tee $x + (local.tee $x + (local.tee $x + (local.tee $x + (local.get $x) + ) + ) + ) + ) + ) + (func $select (param $x f32) (result f32) + (local.set $x + (call $deNan32 + (local.get $x) + ) + ) + (select + (local.get $x) + (local.get $x) + (i32.const 1) + ) + ) + (func $deNan32 (param $0 f32) (result f32) + (if (result f32) + (f32.eq + (local.get $0) + (local.get $0) + ) + (local.get $0) + (f32.const 0) + ) + ) + (func $deNan64 (param $0 f64) (result f64) + (if (result f64) + (f64.eq + (local.get $0) + (local.get $0) + ) + (local.get $0) + (f64.const 0) + ) + ) +) diff -Nru binaryen-108/test/passes/denan.wast binaryen-99/test/passes/denan.wast --- binaryen-108/test/passes/denan.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/denan.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,37 @@ +(module + (global $global$1 (mut f32) (f32.const nan)) + (global $global$2 (mut f32) (f32.const 12.34)) + (func $foo32 (param $x f32) (result f32) + (call $foo32 (local.get $x)) + ) + (func $foo64 (param $x f64) (result f64) + (call $foo64 (local.get $x)) + ) + (func $various (param $x i32) (param $y f32) (param $z i64) (param $w f64) + ) + (func $ignore-local.get (param $f f32) (param $d f64) + (drop (local.get $f)) + (drop (local.get $d)) + (local.set $f (local.get $f)) + (local.set $d (local.get $d)) + (drop (local.get $f)) + (drop (local.get $d)) + (drop (f32.abs (local.get $f))) + (drop (f64.abs (local.get $d))) + (local.set $f (f32.abs (local.get $f))) + (local.set $d (f64.abs (local.get $d))) + (drop (local.get $f)) + (drop (local.get $d)) + ) + (func $tees (param $x f32) (result f32) + (local.tee $x + (local.tee $x + (local.tee $x + (local.tee $x + (local.get $x)))))) + (func $select (param $x f32) (result f32) + (select + (local.get $x) + (local.get $x) + (i32.const 1))) +) diff -Nru binaryen-108/test/passes/directize_all-features.txt binaryen-99/test/passes/directize_all-features.txt --- binaryen-108/test/passes/directize_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/directize_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,223 @@ +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call $foo + (local.get $x) + (local.get $y) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 4) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call $foo + (local.get $x) + (local.get $y) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 0) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call $foo + (local.get $x) + (local.get $y) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 0) $foo $foo $foo $foo $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call $foo + (local.get $x) + (local.get $y) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (import "env" "table" (table $table 5 5 funcref)) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $i32_i32_=>_none) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (export "tab" (table $0)) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $i32_i32_=>_none) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (global.get $g) $foo) + (global $g (mut i32) (i32.const 1)) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $i32_i32_=>_none) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) (param $z i32) + (call_indirect (type $i32_i32_=>_none) + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (block + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (unreachable) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (block + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (unreachable) + ) +) +(module + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (block + (drop + (local.get $x) + ) + (drop + (local.get $y) + ) + ) + (unreachable) + ) +) +(module + (type $i32_=>_none (func (param i32))) + (func $foo (param $0 i32) + (unreachable) + ) +) +(module + (type $none_=>_none (func)) + (table $0 8 8 funcref) + (func $0 + (block $block + (nop) + (block + (block + ) + (unreachable) + ) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (return_call $foo + (local.get $x) + (local.get $y) + ) + ) +) +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (func $foo (param $0 i32) (param $1 i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call $foo + (local.get $x) + (local.get $y) + ) + ) +) diff -Nru binaryen-108/test/passes/directize_all-features.wast binaryen-99/test/passes/directize_all-features.wast --- binaryen-108/test/passes/directize_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/directize_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,223 @@ +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +;; at table edges +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 4) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 4) + ) + ) +) +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 0) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 0) + ) + ) +) +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 0) $foo $foo $foo $foo $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 2) + ) + ) +) +;; imported table +(module + (type $ii (func (param i32 i32))) + (import "env" "table" (table $table 5 5 funcref)) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +;; exported table +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (export "tab" (table $0)) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +;; non-constant table offset +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (global $g (mut i32) (i32.const 1)) + (elem (global.get $g) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +;; non-constant call index +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) (param $z i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) +) +;; bad index +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 5) + ) + ) +) +;; missing index +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 2) + ) + ) +) +;; bad type +(module + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +;; no table +(module + (func $foo (param i32) + (unreachable) + ) +) +;; change types +(module + (type (func)) + (table $0 8 8 funcref) + (func $0 + (block ;; the type of this block will change + (nop) + (call_indirect (type 0) + (i32.const 15) + ) + ) + ) +) +(module ;; indirect tail call + (type $ii (func (param i32 i32))) + (table $0 5 5 funcref) + (elem (i32.const 1) $foo) + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (return_call_indirect (type $ii) + (local.get $x) + (local.get $y) + (i32.const 1) + ) + ) +) +;; call_ref +(module + (func $foo (param i32) (param i32) + (unreachable) + ) + (func $bar (param $x i32) (param $y i32) + (call_ref + (local.get $x) + (local.get $y) + (ref.func $foo) + ) + ) +) + diff -Nru binaryen-108/test/passes/duplicate-function-elimination_all-features.txt binaryen-99/test/passes/duplicate-function-elimination_all-features.txt --- binaryen-108/test/passes/duplicate-function-elimination_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/duplicate-function-elimination_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,6 @@ (module (type $none_=>_i32 (func (result i32))) (type $none_=>_funcref (func (result funcref))) - (elem declare func $0) (func $0 (result i32) (i32.const 0) ) @@ -11,24 +10,11 @@ ) (module (type $none_=>_none (func)) - (global $bar i32 (i32.const 0)) (memory $foo 16 16) + (global $bar i32 (i32.const 0)) (export "memory" (memory $foo)) (export "global" (global $bar)) (func $bar (nop) ) ) -(module - (type $func (func (result i32))) - (global $global$0 (ref $func) (ref.func $foo)) - (export "export" (func $2)) - (func $foo (result i32) - (unreachable) - ) - (func $2 (result i32) - (call_ref - (global.get $global$0) - ) - ) -) diff -Nru binaryen-108/test/passes/duplicate-function-elimination_all-features.wast binaryen-99/test/passes/duplicate-function-elimination_all-features.wast --- binaryen-108/test/passes/duplicate-function-elimination_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/duplicate-function-elimination_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -21,21 +21,3 @@ (func $foo ;; happens to share a name with the memory ) ) -;; renaming after deduplication must update ref.funcs in globals -(module - (type $func (func (result i32))) - (global $global$0 (ref $func) (ref.func $bar)) - ;; These two identical functions can be merged. The ref.func in the global must - ;; be updated accordingly. - (func $foo (result i32) - (unreachable) - ) - (func $bar (result i32) - (unreachable) - ) - (func "export" (result i32) - (call_ref - (global.get $global$0) - ) - ) -) diff -Nru binaryen-108/test/passes/duplicate-function-elimination_optimize-level=1.txt binaryen-99/test/passes/duplicate-function-elimination_optimize-level=1.txt --- binaryen-108/test/passes/duplicate-function-elimination_optimize-level=1.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/duplicate-function-elimination_optimize-level=1.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (nop) ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -18,7 +18,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -27,7 +27,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -41,7 +41,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 3 3 funcref) (elem (i32.const 0) $keep2 $keep2 $caller) @@ -57,7 +57,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2-after-two-passes (nop) @@ -70,7 +70,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep-4 (nop) @@ -86,9 +86,9 @@ ) ) (module - (type $2 (func)) - (type $3 (func (param i32))) - (type $S (func (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $keep4-similar-but-func-sig-differs (drop @@ -105,8 +105,8 @@ ) ) (module - (type $1 (func (param i32))) - (type $S (func (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $keep2-similar-but-func-sig-differs (param $i i32) (drop @@ -118,7 +118,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (nop) @@ -129,7 +129,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $block0 @@ -137,7 +137,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $block0 @@ -150,7 +150,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $block0 @@ -159,7 +159,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $block0 @@ -174,7 +174,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $block0 @@ -188,7 +188,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-since-block-names-do-not-matter (block $foo @@ -196,7 +196,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-since-block-names-do-not-matter (block $foo @@ -208,7 +208,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -232,7 +232,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -250,7 +250,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $foo @@ -261,7 +261,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -279,7 +279,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (loop $bar @@ -288,7 +288,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -312,7 +312,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -325,7 +325,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $foo @@ -347,14 +347,14 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (call $erase) ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2-but-in-theory-we-could-erase (call $keep2-but-in-theory-we-could-erase) @@ -364,7 +364,7 @@ ) ) (module - (type $FUNCSIG$v (func)) + (type $none_=>_none (func)) (import "env" "i" (func $i)) (import "env" "j" (func $j)) (memory $0 0) @@ -373,7 +373,7 @@ ) ) (module - (type $FUNCSIG$v (func)) + (type $none_=>_none (func)) (import "env" "i" (func $i)) (import "env" "j" (func $j)) (memory $0 0) @@ -385,45 +385,45 @@ ) ) (module - (type $T (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 2 2 funcref) (elem (i32.const 0) $erase $erase) (func $erase - (call_indirect (type $T) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) ) (module - (type $T (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 2 2 funcref) (elem (i32.const 0) $keep2 $other) (func $keep2 - (call_indirect (type $T) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) (func $other - (call_indirect (type $T) + (call_indirect (type $none_=>_none) (i32.const 1) ) ) ) (module - (type $S (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 2 2 funcref) (elem (i32.const 0) $keep2 $keep2) (func $keep2 - (call_indirect (type $S) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-even-locals-with-different-names (local $i i32) @@ -433,7 +433,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (local $i i32) @@ -449,7 +449,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-even-locals-with-different-names (local $i i32) @@ -459,7 +459,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (local $i i32) @@ -475,7 +475,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (local $i i32) @@ -491,7 +491,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $erase (drop @@ -507,7 +507,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -525,7 +525,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -543,7 +543,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -561,7 +561,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -579,7 +579,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -597,7 +597,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $erase (i32.store @@ -611,7 +611,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store offset=3 @@ -627,7 +627,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 offset=3 @@ -643,7 +643,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 @@ -659,7 +659,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 offset=3 @@ -675,7 +675,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 offset=3 @@ -691,7 +691,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -705,7 +705,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -719,7 +719,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -733,7 +733,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -747,7 +747,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -761,7 +761,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -775,7 +775,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -786,7 +786,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -804,7 +804,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -822,7 +822,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -834,7 +834,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -854,7 +854,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -874,7 +874,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -894,7 +894,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -907,7 +907,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -929,7 +929,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -951,7 +951,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -973,14 +973,14 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (return) ) ) (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $erase (result i32) (return @@ -989,7 +989,7 @@ ) ) (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $keep (result i32) (return @@ -1003,7 +1003,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -1012,7 +1012,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -1023,7 +1023,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -1041,7 +1041,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop diff -Nru binaryen-108/test/passes/duplicate-function-elimination_optimize-level=2.txt binaryen-99/test/passes/duplicate-function-elimination_optimize-level=2.txt --- binaryen-108/test/passes/duplicate-function-elimination_optimize-level=2.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/duplicate-function-elimination_optimize-level=2.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (nop) ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -18,7 +18,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -27,7 +27,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -41,7 +41,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 3 3 funcref) (elem (i32.const 0) $keep2 $keep2 $caller) @@ -57,7 +57,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2-after-two-passes (nop) @@ -67,7 +67,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep-4 (nop) @@ -83,9 +83,9 @@ ) ) (module - (type $2 (func)) - (type $3 (func (param i32))) - (type $S (func (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $keep4-similar-but-func-sig-differs (drop @@ -102,8 +102,8 @@ ) ) (module - (type $1 (func (param i32))) - (type $S (func (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $keep2-similar-but-func-sig-differs (param $i i32) (drop @@ -115,7 +115,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (nop) @@ -126,7 +126,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $block0 @@ -134,7 +134,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $block0 @@ -147,7 +147,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $block0 @@ -156,7 +156,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $block0 @@ -171,7 +171,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $block0 @@ -185,7 +185,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-since-block-names-do-not-matter (block $foo @@ -193,7 +193,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-since-block-names-do-not-matter (block $foo @@ -205,7 +205,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -229,7 +229,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -247,7 +247,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $foo @@ -258,7 +258,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -276,7 +276,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (loop $bar @@ -285,7 +285,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -309,7 +309,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (block $foo @@ -322,7 +322,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (block $foo @@ -344,14 +344,14 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (call $erase) ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2-but-in-theory-we-could-erase (call $keep2-but-in-theory-we-could-erase) @@ -361,7 +361,7 @@ ) ) (module - (type $FUNCSIG$v (func)) + (type $none_=>_none (func)) (import "env" "i" (func $i)) (import "env" "j" (func $j)) (memory $0 0) @@ -370,7 +370,7 @@ ) ) (module - (type $FUNCSIG$v (func)) + (type $none_=>_none (func)) (import "env" "i" (func $i)) (import "env" "j" (func $j)) (memory $0 0) @@ -382,45 +382,45 @@ ) ) (module - (type $T (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 2 2 funcref) (elem (i32.const 0) $erase $erase) (func $erase - (call_indirect (type $T) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) ) (module - (type $T (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 2 2 funcref) (elem (i32.const 0) $keep2 $other) (func $keep2 - (call_indirect (type $T) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) (func $other - (call_indirect (type $T) + (call_indirect (type $none_=>_none) (i32.const 1) ) ) ) (module - (type $S (func)) + (type $none_=>_none (func)) (memory $0 0) (table $0 2 2 funcref) (elem (i32.const 0) $keep2 $keep2) (func $keep2 - (call_indirect (type $S) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-even-locals-with-different-names (local $i i32) @@ -430,7 +430,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (local $i i32) @@ -446,7 +446,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase-even-locals-with-different-names (local $i i32) @@ -456,7 +456,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (local $i i32) @@ -472,7 +472,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (local $i i32) @@ -488,7 +488,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $erase (drop @@ -504,7 +504,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -522,7 +522,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -540,7 +540,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -558,7 +558,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -576,7 +576,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (drop @@ -594,7 +594,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $erase (i32.store @@ -608,7 +608,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store offset=3 @@ -624,7 +624,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 offset=3 @@ -640,7 +640,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 @@ -656,7 +656,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 offset=3 @@ -672,7 +672,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 10) (func $keep2 (i32.store16 offset=3 @@ -688,7 +688,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -702,7 +702,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -716,7 +716,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -730,7 +730,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -744,7 +744,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -758,7 +758,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -772,7 +772,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -783,7 +783,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -801,7 +801,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -819,7 +819,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -831,7 +831,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -851,7 +851,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -871,7 +871,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep2 (drop @@ -891,7 +891,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -904,7 +904,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -926,7 +926,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -948,7 +948,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -970,14 +970,14 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (return) ) ) (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $erase (result i32) (return @@ -986,7 +986,7 @@ ) ) (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 0) (func $keep (result i32) (return @@ -1000,7 +1000,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -1009,7 +1009,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $erase (drop @@ -1020,7 +1020,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop @@ -1038,7 +1038,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $keep (drop diff -Nru binaryen-108/test/passes/dwarf-local-order.bin.txt binaryen-99/test/passes/dwarf-local-order.bin.txt --- binaryen-108/test/passes/dwarf-local-order.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/dwarf-local-order.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,10 +1,10 @@ (module (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) - (global $global$0 (mut i32) (i32.const 5243904)) - (global $global$1 i32 (i32.const 1024)) (memory $0 256 256) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 5243904)) + (global $global$1 i32 (i32.const 1024)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "foo" (func $foo)) @@ -160,10 +160,10 @@ (module (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) - (global $global$0 (mut i32) (i32.const 5243904)) - (global $global$1 i32 (i32.const 1024)) (memory $0 256 256) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 5243904)) + (global $global$1 i32 (i32.const 1024)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "foo" (func $foo)) @@ -394,10 +394,10 @@ (module (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) - (global $global$0 (mut i32) (i32.const 5243904)) - (global $global$1 i32 (i32.const 1024)) (memory $0 256 256) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 5243904)) + (global $global$1 i32 (i32.const 1024)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "foo" (func $foo)) @@ -549,10 +549,10 @@ (module (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) - (global $global$0 (mut i32) (i32.const 5243904)) - (global $global$1 i32 (i32.const 1024)) (memory $0 256 256) (table $0 1 1 funcref) + (global $global$0 (mut i32) (i32.const 5243904)) + (global $global$1 i32 (i32.const 1024)) (export "memory" (memory $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "foo" (func $foo)) diff -Nru binaryen-108/test/passes/dwarf_with_exceptions.bin.txt binaryen-99/test/passes/dwarf_with_exceptions.bin.txt --- binaryen-108/test/passes/dwarf_with_exceptions.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/dwarf_with_exceptions.bin.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,544 +0,0 @@ -(module - (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "_Z3foov" (func $foo\28\29)) - (import "env" "__cxa_begin_catch" (func $__cxa_begin_catch (param i32) (result i32))) - (import "env" "__cxa_end_catch" (func $__cxa_end_catch)) - (import "env" "_ZSt9terminatev" (func $std::terminate\28\29)) - (global $__stack_pointer (mut i32) (i32.const 66560)) - (memory $0 2) - (tag $tag$0 (param i32)) - (export "memory" (memory $0)) - (func $__wasm_call_ctors - ) - (func $dwarf_with_exceptions\28\29 - (local $0 i32) - (local $1 i32) - ;; code offset: 0xe - (local.set $0 - ;; code offset: 0x8 - (global.get $__stack_pointer) - ) - ;; code offset: 0x10 - (try $label$9 - (do - ;; code offset: 0x12 - (call $foo\28\29) - ) - ;; code offset: 0x18 - (catch $tag$0 - ;; code offset: 0x1e - (local.set $1 - (pop i32) - ) - ;; code offset: 0x22 - (global.set $__stack_pointer - ;; code offset: 0x20 - (local.get $0) - ) - ;; code offset: 0x30 - (drop - ;; code offset: 0x2a - (call $__cxa_begin_catch - ;; code offset: 0x28 - (local.get $1) - ) - ) - ;; code offset: 0x31 - (try $label$8 - (do - ;; code offset: 0x33 - (call $foo\28\29) - ;; code offset: 0x3b - (global.set $__stack_pointer - ;; code offset: 0x39 - (local.get $0) - ) - ) - ;; code offset: 0x41 - (catch_all - ;; code offset: 0x42 - (try $label$7 - (do - ;; code offset: 0x44 - (call $__cxa_end_catch) - ) - ;; code offset: 0x4a - (catch $tag$0 - ;; code offset: 0x50 - (local.set $1 - (pop i32) - ) - ;; code offset: 0x54 - (global.set $__stack_pointer - ;; code offset: 0x52 - (local.get $0) - ) - ;; code offset: 0x5c - (call $__clang_call_terminate - ;; code offset: 0x5a - (local.get $1) - ) - ;; code offset: 0x62 - (unreachable) - ) - ;; code offset: 0x63 - (catch_all - ;; code offset: 0x64 - (call $std::terminate\28\29) - ;; code offset: 0x6a - (unreachable) - ) - ) - ;; code offset: 0x6c - (rethrow $label$8) - ) - ) - ;; code offset: 0x6f - (call $__cxa_end_catch) - ) - ) - ) - (func $__clang_call_terminate (param $0 i32) - ;; code offset: 0x81 - (drop - ;; code offset: 0x7b - (call $__cxa_begin_catch - ;; code offset: 0x79 - (local.get $0) - ) - ) - ;; code offset: 0x82 - (call $std::terminate\28\29) - ;; code offset: 0x88 - (unreachable) - ) - ;; custom section ".debug_info", size 63 - ;; custom section ".debug_abbrev", size 41 - ;; custom section ".debug_line", size 109 - ;; custom section ".debug_str", size 178 - ;; custom section "producers", size 134 - ;; features section: exception-handling -) -DWARF debug info -================ - -Contains section .debug_info (63 bytes) -Contains section .debug_abbrev (41 bytes) -Contains section .debug_line (109 bytes) -Contains section .debug_str (178 bytes) - -.debug_abbrev contents: -Abbrev table for offset: 0x00000000 -[1] DW_TAG_compile_unit DW_CHILDREN_yes - DW_AT_producer DW_FORM_strp - DW_AT_language DW_FORM_data2 - DW_AT_name DW_FORM_strp - DW_AT_stmt_list DW_FORM_sec_offset - DW_AT_comp_dir DW_FORM_strp - DW_AT_low_pc DW_FORM_addr - DW_AT_high_pc DW_FORM_data4 - -[2] DW_TAG_subprogram DW_CHILDREN_no - DW_AT_low_pc DW_FORM_addr - DW_AT_high_pc DW_FORM_data4 - DW_AT_frame_base DW_FORM_exprloc - DW_AT_linkage_name DW_FORM_strp - DW_AT_name DW_FORM_strp - DW_AT_decl_file DW_FORM_data1 - DW_AT_decl_line DW_FORM_data1 - DW_AT_external DW_FORM_flag_present - - -.debug_info contents: -0x00000000: Compile Unit: length = 0x0000003b version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000003f) - -0x0000000b: DW_TAG_compile_unit [1] * - DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = "clang version 13.0.0 (https://github.com/llvm/llvm-project 3c4c205060c9398da705eb71b63ddd8a04999de9)") - DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus_14) - DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000065] = "dwarf_with_exceptions.cpp") - DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) - DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000007f] = "/") - DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) - DW_AT_high_pc [DW_FORM_data4] (0x00000072) - -0x00000026: DW_TAG_subprogram [2] - DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) - DW_AT_high_pc [DW_FORM_data4] (0x00000072) - DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x0 +0, DW_OP_stack_value) - DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x00000081] = "_Z21dwarf_with_exceptionsv") - DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009c] = "dwarf_with_exceptions") - DW_AT_decl_file [DW_FORM_data1] ("/dwarf_with_exceptions.cpp") - DW_AT_decl_line [DW_FORM_data1] (2) - DW_AT_external [DW_FORM_flag_present] (true) - -0x0000003e: NULL - -.debug_line contents: -debug_line[0x00000000] -Line table prologue: - total_length: 0x00000069 - version: 4 - prologue_length: 0x00000031 - min_inst_length: 1 -max_ops_per_inst: 1 - default_is_stmt: 1 - line_base: -5 - line_range: 14 - opcode_base: 13 -standard_opcode_lengths[DW_LNS_copy] = 0 -standard_opcode_lengths[DW_LNS_advance_pc] = 1 -standard_opcode_lengths[DW_LNS_advance_line] = 1 -standard_opcode_lengths[DW_LNS_set_file] = 1 -standard_opcode_lengths[DW_LNS_set_column] = 1 -standard_opcode_lengths[DW_LNS_negate_stmt] = 0 -standard_opcode_lengths[DW_LNS_set_basic_block] = 0 -standard_opcode_lengths[DW_LNS_const_add_pc] = 0 -standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1 -standard_opcode_lengths[DW_LNS_set_prologue_end] = 0 -standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 -standard_opcode_lengths[DW_LNS_set_isa] = 1 -file_names[ 1]: - name: "dwarf_with_exceptions.cpp" - dir_index: 0 - mod_time: 0x00000000 - length: 0x00000000 -0x0000003b: 00 DW_LNE_set_address (0x0000000000000005) -0x00000042: 13 address += 0, line += 1 - 0x0000000000000005 2 0 1 0 0 is_stmt - -0x00000043: 05 DW_LNS_set_column (5) -0x00000045: 0a DW_LNS_set_prologue_end -0x00000046: ae address += 11, line += 2 - 0x0000000000000010 4 5 1 0 0 is_stmt prologue_end - -0x00000047: 05 DW_LNS_set_column (3) -0x00000049: 83 address += 8, line += 1 - 0x0000000000000018 5 3 1 0 0 is_stmt - -0x0000004a: 05 DW_LNS_set_column (5) -0x0000004c: 08 DW_LNS_const_add_pc (0x0000000000000011) -0x0000004d: 83 address += 8, line += 1 - 0x0000000000000031 6 5 1 0 0 is_stmt - -0x0000004e: 06 DW_LNS_negate_stmt -0x0000004f: 03 DW_LNS_advance_line (0) -0x00000051: 82 address += 8, line += 0 - 0x0000000000000039 0 5 1 0 0 - -0x00000052: 05 DW_LNS_set_column (3) -0x00000054: 06 DW_LNS_negate_stmt -0x00000055: 89 address += 8, line += 7 - 0x0000000000000041 7 3 1 0 0 is_stmt - -0x00000056: 06 DW_LNS_negate_stmt -0x00000057: 03 DW_LNS_advance_line (0) -0x00000059: 02 DW_LNS_advance_pc (42) -0x0000005b: 01 DW_LNS_copy - 0x000000000000006b 0 3 1 0 0 - - -0x0000005c: 27 address += 1, line += 7 - 0x000000000000006c 7 3 1 0 0 - -0x0000005d: 03 DW_LNS_advance_line (0) -0x0000005f: 2e address += 2, line += 0 - 0x000000000000006e 0 3 1 0 0 - -0x00000060: 27 address += 1, line += 7 - 0x000000000000006f 7 3 1 0 0 - -0x00000061: 03 DW_LNS_advance_line (0) -0x00000063: 66 address += 6, line += 0 - 0x0000000000000075 0 3 1 0 0 - -0x00000064: 05 DW_LNS_set_column (1) -0x00000066: 06 DW_LNS_negate_stmt -0x00000067: 28 address += 1, line += 8 - 0x0000000000000076 8 1 1 0 0 is_stmt - -0x00000068: 02 DW_LNS_advance_pc (1) -0x0000006a: 00 DW_LNE_end_sequence - 0x0000000000000077 8 1 1 0 0 is_stmt end_sequence - - -.debug_str contents: -0x00000000: "clang version 13.0.0 (https://github.com/llvm/llvm-project 3c4c205060c9398da705eb71b63ddd8a04999de9)" -0x00000065: "dwarf_with_exceptions.cpp" -0x0000007f: "/" -0x00000081: "_Z21dwarf_with_exceptionsv" -0x0000009c: "dwarf_with_exceptions" -DWARF debug info -================ - -Contains section .debug_info (63 bytes) -Contains section .debug_abbrev (41 bytes) -Contains section .debug_line (162 bytes) -Contains section .debug_str (178 bytes) - -.debug_abbrev contents: -Abbrev table for offset: 0x00000000 -[1] DW_TAG_compile_unit DW_CHILDREN_yes - DW_AT_producer DW_FORM_strp - DW_AT_language DW_FORM_data2 - DW_AT_name DW_FORM_strp - DW_AT_stmt_list DW_FORM_sec_offset - DW_AT_comp_dir DW_FORM_strp - DW_AT_low_pc DW_FORM_addr - DW_AT_high_pc DW_FORM_data4 - -[2] DW_TAG_subprogram DW_CHILDREN_no - DW_AT_low_pc DW_FORM_addr - DW_AT_high_pc DW_FORM_data4 - DW_AT_frame_base DW_FORM_exprloc - DW_AT_linkage_name DW_FORM_strp - DW_AT_name DW_FORM_strp - DW_AT_decl_file DW_FORM_data1 - DW_AT_decl_line DW_FORM_data1 - DW_AT_external DW_FORM_flag_present - - -.debug_info contents: -0x00000000: Compile Unit: length = 0x0000003b version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000003f) - -0x0000000b: DW_TAG_compile_unit [1] * - DW_AT_producer [DW_FORM_strp] ( .debug_str[0x00000000] = "clang version 13.0.0 (https://github.com/llvm/llvm-project 3c4c205060c9398da705eb71b63ddd8a04999de9)") - DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus_14) - DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000065] = "dwarf_with_exceptions.cpp") - DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000) - DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000007f] = "/") - DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) - DW_AT_high_pc [DW_FORM_data4] (0x00000040) - -0x00000026: DW_TAG_subprogram [2] - DW_AT_low_pc [DW_FORM_addr] (0x0000000000000005) - DW_AT_high_pc [DW_FORM_data4] (0x00000040) - DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_WASM_location 0x0 +0, DW_OP_stack_value) - DW_AT_linkage_name [DW_FORM_strp] ( .debug_str[0x00000081] = "_Z21dwarf_with_exceptionsv") - DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009c] = "dwarf_with_exceptions") - DW_AT_decl_file [DW_FORM_data1] ("/dwarf_with_exceptions.cpp") - DW_AT_decl_line [DW_FORM_data1] (2) - DW_AT_external [DW_FORM_flag_present] (true) - -0x0000003e: NULL - -.debug_line contents: -debug_line[0x00000000] -Line table prologue: - total_length: 0x0000009e - version: 4 - prologue_length: 0x00000031 - min_inst_length: 1 -max_ops_per_inst: 1 - default_is_stmt: 1 - line_base: -5 - line_range: 14 - opcode_base: 13 -standard_opcode_lengths[DW_LNS_copy] = 0 -standard_opcode_lengths[DW_LNS_advance_pc] = 1 -standard_opcode_lengths[DW_LNS_advance_line] = 1 -standard_opcode_lengths[DW_LNS_set_file] = 1 -standard_opcode_lengths[DW_LNS_set_column] = 1 -standard_opcode_lengths[DW_LNS_negate_stmt] = 0 -standard_opcode_lengths[DW_LNS_set_basic_block] = 0 -standard_opcode_lengths[DW_LNS_const_add_pc] = 0 -standard_opcode_lengths[DW_LNS_fixed_advance_pc] = 1 -standard_opcode_lengths[DW_LNS_set_prologue_end] = 0 -standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 -standard_opcode_lengths[DW_LNS_set_isa] = 1 -file_names[ 1]: - name: "dwarf_with_exceptions.cpp" - dir_index: 0 - mod_time: 0x00000000 - length: 0x00000000 -0x0000003b: 00 DW_LNE_set_address (0x0000000000000005) -0x00000042: 03 DW_LNS_advance_line (2) -0x00000044: 01 DW_LNS_copy - 0x0000000000000005 2 0 1 0 0 is_stmt - - -0x00000045: 00 DW_LNE_set_address (0x000000000000000e) -0x0000004c: 03 DW_LNS_advance_line (4) -0x0000004e: 05 DW_LNS_set_column (5) -0x00000050: 0a DW_LNS_set_prologue_end -0x00000051: 01 DW_LNS_copy - 0x000000000000000e 4 5 1 0 0 is_stmt prologue_end - - -0x00000052: 00 DW_LNE_set_address (0x0000000000000012) -0x00000059: 03 DW_LNS_advance_line (5) -0x0000005b: 05 DW_LNS_set_column (3) -0x0000005d: 01 DW_LNS_copy - 0x0000000000000012 5 3 1 0 0 is_stmt - - -0x0000005e: 00 DW_LNE_set_address (0x000000000000001f) -0x00000065: 03 DW_LNS_advance_line (6) -0x00000067: 05 DW_LNS_set_column (5) -0x00000069: 01 DW_LNS_copy - 0x000000000000001f 6 5 1 0 0 is_stmt - - -0x0000006a: 00 DW_LNE_set_address (0x000000000000003e) -0x00000071: 03 DW_LNS_advance_line (7) -0x00000073: 05 DW_LNS_set_column (3) -0x00000075: 06 DW_LNS_negate_stmt -0x00000076: 01 DW_LNS_copy - 0x000000000000003e 7 3 1 0 0 - - -0x00000077: 00 DW_LNE_set_address (0x0000000000000041) -0x0000007e: 01 DW_LNS_copy - 0x0000000000000041 7 3 1 0 0 - - -0x0000007f: 00 DW_LNE_set_address (0x0000000000000044) -0x00000086: 03 DW_LNS_advance_line (8) -0x00000088: 05 DW_LNS_set_column (1) -0x0000008a: 06 DW_LNS_negate_stmt -0x0000008b: 01 DW_LNS_copy - 0x0000000000000044 8 1 1 0 0 is_stmt - - -0x0000008c: 00 DW_LNE_set_address (0x0000000000000045) -0x00000093: 01 DW_LNS_copy - 0x0000000000000045 8 1 1 0 0 is_stmt - - -0x00000094: 00 DW_LNE_set_address (0x00000000ffffff64) -0x0000009b: 03 DW_LNS_advance_line (7) -0x0000009d: 05 DW_LNS_set_column (3) -0x0000009f: 00 DW_LNE_end_sequence - 0x00000000ffffff64 7 3 1 0 0 is_stmt end_sequence - - -.debug_str contents: -0x00000000: "clang version 13.0.0 (https://github.com/llvm/llvm-project 3c4c205060c9398da705eb71b63ddd8a04999de9)" -0x00000065: "dwarf_with_exceptions.cpp" -0x0000007f: "/" -0x00000081: "_Z21dwarf_with_exceptionsv" -0x0000009c: "dwarf_with_exceptions" -(module - (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (import "env" "_Z3foov" (func $foo\28\29)) - (import "env" "__cxa_begin_catch" (func $__cxa_begin_catch (param i32) (result i32))) - (import "env" "__cxa_end_catch" (func $__cxa_end_catch)) - (import "env" "_ZSt9terminatev" (func $std::terminate\28\29)) - (global $__stack_pointer (mut i32) (i32.const 66560)) - (memory $0 2) - (tag $tag$0 (param i32)) - (export "memory" (memory $0)) - (func $__wasm_call_ctors - ) - (func $dwarf_with_exceptions\28\29 - (local $0 i32) - (local $1 i32) - ;; code offset: 0xc - (local.set $0 - ;; code offset: 0xa - (global.get $__stack_pointer) - ) - ;; code offset: 0xe - (try $label$9 - (do - ;; code offset: 0x10 - (call $foo\28\29) - ) - ;; code offset: 0x12 - (catch $tag$0 - ;; code offset: 0x14 - (local.set $1 - (pop i32) - ) - ;; code offset: 0x18 - (global.set $__stack_pointer - ;; code offset: 0x16 - (local.get $0) - ) - ;; code offset: 0x1e - (drop - ;; code offset: 0x1c - (call $__cxa_begin_catch - ;; code offset: 0x1a - (local.get $1) - ) - ) - ;; code offset: 0x1f - (try $label$8 - (do - ;; code offset: 0x21 - (call $foo\28\29) - ;; code offset: 0x25 - (global.set $__stack_pointer - ;; code offset: 0x23 - (local.get $0) - ) - ) - ;; code offset: 0x27 - (catch_all - ;; code offset: 0x28 - (try $label$7 - (do - ;; code offset: 0x2a - (call $__cxa_end_catch) - ) - ;; code offset: 0x2c - (catch $tag$0 - ;; code offset: 0x2e - (local.set $1 - (pop i32) - ) - ;; code offset: 0x32 - (global.set $__stack_pointer - ;; code offset: 0x30 - (local.get $0) - ) - ;; code offset: 0x36 - (call $__clang_call_terminate - ;; code offset: 0x34 - (local.get $1) - ) - ;; code offset: 0x38 - (unreachable) - ) - ;; code offset: 0x39 - (catch_all - ;; code offset: 0x3a - (call $std::terminate\28\29) - ;; code offset: 0x3c - (unreachable) - ) - ) - ;; code offset: 0x3e - (rethrow $label$8) - ) - ) - ;; code offset: 0x41 - (call $__cxa_end_catch) - ) - ) - ) - (func $__clang_call_terminate (param $0 i32) - ;; code offset: 0x4b - (drop - ;; code offset: 0x49 - (call $__cxa_begin_catch - ;; code offset: 0x47 - (local.get $0) - ) - ) - ;; code offset: 0x4c - (call $std::terminate\28\29) - ;; code offset: 0x4e - (unreachable) - ) - ;; custom section ".debug_info", size 63 - ;; custom section ".debug_abbrev", size 41 - ;; custom section ".debug_line", size 162 - ;; custom section ".debug_str", size 178 - ;; custom section "producers", size 134 - ;; features section: exception-handling -) diff -Nru binaryen-108/test/passes/dwarf_with_exceptions.cpp binaryen-99/test/passes/dwarf_with_exceptions.cpp --- binaryen-108/test/passes/dwarf_with_exceptions.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/dwarf_with_exceptions.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -void foo(); -void dwarf_with_exceptions() { - try { - foo(); - } catch (...) { - foo(); - } -} -// How to generate dwarf_with_exceptions.wasm: -// $ clang++ -std=c++14 --target=wasm32-unknown-unknown -g -fwasm-exceptions \ -// -Xclang -disable-O0-optnone -c -S -emit-llvm -// dwarf_with_exceptions.cpp -o temp.ll -// $ opt -S -mem2reg -simplifycfg temp.ll -o dwarf_with_exceptions.ll -// Remove some personal info from dwarf_with_exceptions.ll -// $ llc -exception-model=wasm -mattr=+exception-handling -filetype=obj \ -// dwarf_with_exceptions.ll -o dwarf_with_exceptions.o -// $ wasm-ld --no-entry --no-gc-sections --allow-undefined \ -// dwarf_with_exceptions.o -o dwarf_with_exceptions.wasm diff -Nru binaryen-108/test/passes/dwarf_with_exceptions.passes binaryen-99/test/passes/dwarf_with_exceptions.passes --- binaryen-108/test/passes/dwarf_with_exceptions.passes 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/dwarf_with_exceptions.passes 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -print_dwarfdump_roundtrip_dwarfdump_g Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/passes/dwarf_with_exceptions.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/passes/dwarf_with_exceptions.wasm differ diff -Nru binaryen-108/test/passes/emit-js-wrapper=a.js.txt binaryen-99/test/passes/emit-js-wrapper=a.js.txt --- binaryen-108/test/passes/emit-js-wrapper=a.js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/emit-js-wrapper=a.js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,11 +1,11 @@ (module - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_f32_f64_=>_none (func (param i32 i32 i32 f32 f64))) (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) (type $i32_f32_f64_=>_none (func (param i32 f32 f64))) - (type $i32_f32_f64_=>_i64 (func (param i32 f32 f64) (result i64))) - (type $i32_i32_i32_f32_f64_=>_none (func (param i32 i32 i32 f32 f64))) (type $i32_f32_f64_=>_i32 (func (param i32 f32 f64) (result i32))) + (type $i32_f32_f64_=>_i64 (func (param i32 f32 f64) (result i64))) (import "env" "setTempRet0" (func $setTempRet0 (param i32))) (memory $0 256 256) (export "add" (func $add)) diff -Nru binaryen-108/test/passes/emit-js-wrapper=a.js.wast.js binaryen-99/test/passes/emit-js-wrapper=a.js.wast.js --- binaryen-108/test/passes/emit-js-wrapper=a.js.wast.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/emit-js-wrapper=a.js.wast.js 2021-01-07 20:01:06.000000000 +0000 @@ -30,8 +30,7 @@ ret += Number(x).toString(); break; } - // For anything else, just print the type. - default: ret += type; break; + default: throw 'what?'; } return ret; } diff -Nru binaryen-108/test/passes/extract-function_pass-arg=extract@foo.txt binaryen-99/test/passes/extract-function_pass-arg=extract@foo.txt --- binaryen-108/test/passes/extract-function_pass-arg=extract@foo.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/extract-function_pass-arg=extract@foo.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,9 @@ +(module + (type $none_=>_none (func)) + (import "env" "bar" (func $bar)) + (import "env" "other" (func $other)) + (export "foo" (func $foo)) + (func $foo + (call $bar) + ) +) diff -Nru binaryen-108/test/passes/extract-function_pass-arg=extract@foo.wast binaryen-99/test/passes/extract-function_pass-arg=extract@foo.wast --- binaryen-108/test/passes/extract-function_pass-arg=extract@foo.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/extract-function_pass-arg=extract@foo.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,12 @@ +(module + (func $foo + (call $bar) + ) + (func $bar + (call $foo) + ) + (func $other + (drop (i32.const 1)) + ) +) + diff -Nru binaryen-108/test/passes/fannkuch0_dwarf.bin.txt binaryen-99/test/passes/fannkuch0_dwarf.bin.txt --- binaryen-108/test/passes/fannkuch0_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fannkuch0_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -5193,8 +5193,8 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "Wrong argument.\n\00Pfannkuchen(%d) = %d.\n\00%d\00\n\00") (import "env" "__indirect_function_table" (table $timport$0 1 funcref)) diff -Nru binaryen-108/test/passes/fannkuch3_dwarf.bin.txt binaryen-99/test/passes/fannkuch3_dwarf.bin.txt --- binaryen-108/test/passes/fannkuch3_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fannkuch3_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -4792,9 +4792,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "Pfannkuchen(%d) = %d.\n\00%d\00Wrong argument.\00") (import "env" "__indirect_function_table" (table $timport$0 1 funcref)) diff -Nru binaryen-108/test/passes/fannkuch3_manyopts_dwarf.bin.txt binaryen-99/test/passes/fannkuch3_manyopts_dwarf.bin.txt --- binaryen-108/test/passes/fannkuch3_manyopts_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fannkuch3_manyopts_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -4700,9 +4700,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "Pfannkuchen(%d) = %d.\n\00%d\00Wrong argument.\00") (import "env" "malloc" (func $malloc (param i32) (result i32))) @@ -5711,11 +5711,11 @@ ;; code offset: 0x30a (if ;; code offset: 0x309 - (i32.gt_s + (i32.ge_s ;; code offset: 0x305 (local.get $2) ;; code offset: 0x307 - (i32.const 0) + (i32.const 1) ) (block ;; code offset: 0x30c @@ -6578,11 +6578,11 @@ ;; code offset: 0x5a8 (if ;; code offset: 0x5a7 - (i32.gt_s + (i32.ge_s ;; code offset: 0x5a3 (local.get $2) ;; code offset: 0x5a5 - (i32.const 0) + (i32.const 1) ) (block ;; code offset: 0x5aa diff -Nru binaryen-108/test/passes/fib2_dwarf.bin.txt binaryen-99/test/passes/fib2_dwarf.bin.txt --- binaryen-108/test/passes/fib2_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fib2_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -614,8 +614,8 @@ 00000000 (module (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (import "env" "__indirect_function_table" (table $timport$0 1 funcref)) diff -Nru binaryen-108/test/passes/fib2_emptylocspan_dwarf.bin.txt binaryen-99/test/passes/fib2_emptylocspan_dwarf.bin.txt --- binaryen-108/test/passes/fib2_emptylocspan_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fib2_emptylocspan_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -614,8 +614,8 @@ 00000000 (module (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (import "env" "__indirect_function_table" (table $timport$0 1 funcref)) diff -Nru binaryen-108/test/passes/flatten_all-features.txt binaryen-99/test/passes/flatten_all-features.txt --- binaryen-108/test/passes/flatten_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,2445 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_f32 (func (result f32))) + (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) + (type $none_=>_anyref (func (result anyref))) + (memory $0 10) + (table $0 1 1 funcref) + (elem (i32.const 0) $call-me) + (global $x (mut i32) (i32.const 0)) + (func $a1 + (local $0 i32) + (local.set $0 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (drop + (local.get $0) + ) + ) + (func $a2 (result i32) + (local $0 i32) + (local.set $0 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (return + (local.get $0) + ) + ) + (func $a3 (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block $block + (local.set $0 + (i32.const 1) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (i32.add + (i32.const 0) + (local.get $1) + ) + ) + (return + (local.get $2) + ) + ) + (func $a4 + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block $block + (local.set $0 + (i32.const 1) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (i32.add + (i32.const 0) + (local.get $1) + ) + ) + (drop + (local.get $2) + ) + ) + (func $a5 (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block $block + (local.set $0 + (i32.const 0) + ) + ) + (local.set $1 + (local.get $0) + ) + (block $block0 + (local.set $2 + (i32.const 1) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $4 + (i32.add + (local.get $1) + (local.get $3) + ) + ) + (return + (local.get $4) + ) + ) + (func $a6 (result i32) + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $block + (local.set $x + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + (local.set $2 + (local.get $1) + ) + ) + (local.set $3 + (local.get $2) + ) + (block $block1 + (local.set $x + (i32.const 1) + ) + (local.set $4 + (local.get $x) + ) + (local.set $5 + (local.get $4) + ) + ) + (local.set $6 + (local.get $5) + ) + (local.set $7 + (i32.add + (local.get $3) + (local.get $6) + ) + ) + (return + (local.get $7) + ) + ) + (func $a7 (result i32) + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block $block + (block $block2 + (local.set $x + (i32.const 0) + ) + (local.set $1 + (local.get $x) + ) + (local.set $2 + (local.get $1) + ) + ) + (local.set $3 + (local.get $2) + ) + (block $block3 + (local.set $x + (i32.const 1) + ) + (local.set $4 + (local.get $x) + ) + (local.set $5 + (local.get $4) + ) + ) + (local.set $6 + (local.get $5) + ) + (local.set $7 + (i32.add + (local.get $3) + (local.get $6) + ) + ) + (local.set $8 + (local.get $7) + ) + ) + (local.set $9 + (local.get $8) + ) + (return + (local.get $9) + ) + ) + (func $a8 (result i32) + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block $outer + (block $inner + (block $block + (local.set $1 + (i32.const -1) + ) + (br $inner) + (unreachable) + (local.set $2 + (i32.const 0) + ) + (br $outer) + (unreachable) + (local.set $3 + (i32.const 1) + ) + ) + (local.set $4 + (local.get $3) + ) + (block $block4 + (local.set $2 + (i32.const 2) + ) + (br $outer) + (unreachable) + (local.set $x + (i32.const 3) + ) + (local.set $5 + (local.get $x) + ) + (local.set $6 + (local.get $5) + ) + ) + (local.set $7 + (local.get $6) + ) + (local.set $8 + (i32.add + (local.get $4) + (local.get $7) + ) + ) + (local.set $1 + (local.get $8) + ) + ) + (local.set $9 + (local.get $1) + ) + (local.set $2 + (local.get $9) + ) + ) + (local.set $10 + (local.get $2) + ) + (return + (local.get $10) + ) + ) + (func $a9 (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (loop $outer + (loop $inner + (block + (br_if $outer + (i32.const -1) + ) + (local.set $0 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (local.set $1 + (local.get $0) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $2) + ) + ) + (local.set $4 + (local.get $3) + ) + (local.set $5 + (local.get $4) + ) + ) + (local.set $6 + (local.get $5) + ) + (return + (local.get $6) + ) + ) + (func $a10 (result i32) + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block $outer + (local.set $1 + (i32.const 0) + ) + (br_if $outer + (i32.const 1) + ) + (local.set $2 + (local.get $1) + ) + (drop + (local.get $2) + ) + (local.set $x + (i32.const 2) + ) + (local.set $3 + (local.get $x) + ) + (local.set $1 + (local.get $3) + ) + (br_if $outer + (i32.const 3) + ) + (local.set $4 + (local.get $1) + ) + (drop + (local.get $4) + ) + (local.set $x + (i32.const 5) + ) + (local.set $5 + (local.get $x) + ) + (local.set $1 + (i32.const 4) + ) + (br_if $outer + (local.get $5) + ) + (local.set $6 + (local.get $1) + ) + (drop + (local.get $6) + ) + (local.set $x + (i32.const 6) + ) + (local.set $7 + (local.get $x) + ) + (local.set $x + (i32.const 7) + ) + (local.set $8 + (local.get $x) + ) + (local.set $1 + (local.get $7) + ) + (br_if $outer + (local.get $8) + ) + (local.set $9 + (local.get $1) + ) + (drop + (local.get $9) + ) + (local.set $1 + (i32.const 8) + ) + (br $outer) + (unreachable) + ) + (local.set $10 + (local.get $1) + ) + (return + (local.get $10) + ) + ) + (func $a11 + (if + (i32.const 0) + (drop + (i32.const 1) + ) + ) + ) + (func $a12 (result i32) + (local $0 i32) + (local $1 i32) + (if + (i32.const 0) + (local.set $0 + (i32.const 1) + ) + (local.set $0 + (i32.const 2) + ) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $a13 (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block $x + (block + (local.set $0 + (i32.const 2) + ) + (local.set $1 + (local.get $0) + ) + (br_table $x + (i32.const 0) + ) + (if + (unreachable) + (local.set $2 + (i32.const 0) + ) + (local.set $2 + (i32.const 1) + ) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $1 + (local.get $3) + ) + ) + (local.set $4 + (local.get $1) + ) + (return + (local.get $4) + ) + ) + (func $a14 (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block $block + (local.set $0 + (i32.const 7) + ) + (local.set $1 + (local.get $0) + ) + (br_table $block + (i32.const 1) + ) + (select + (i32.const 0) + (i32.const 1) + (unreachable) + ) + (unreachable) + ) + (local.set $2 + (local.get $1) + ) + (return + (local.get $2) + ) + ) + (func $a15 + (local $0 i32) + (local $1 f32) + (local $2 f32) + (block + (local.set $0 + (i32.load16_u + (i32.const 53) + ) + ) + (if + (local.get $0) + (block + (unreachable) + (unreachable) + ) + (block + (block $label$3 + (unreachable) + (unreachable) + ) + (local.set $2 + (local.get $1) + ) + (drop + (local.get $2) + ) + ) + ) + ) + (unreachable) + ) + (func $a16 (result i32) + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $label$1 + (local.set $x + (i32.const 1) + ) + (local.set $1 + (local.get $x) + ) + (block $label$2 + (local.set $x + (i32.const 0) + ) + (local.set $2 + (i32.const 0) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $4 + (i32.eqz + (local.get $3) + ) + ) + (local.set $5 + (local.get $1) + ) + (br_if $label$1 + (local.get $4) + ) + (local.set $6 + (local.get $5) + ) + (drop + (local.get $6) + ) + (local.set $5 + (i32.const 0) + ) + ) + (local.set $7 + (local.get $5) + ) + (return + (local.get $7) + ) + ) + (func $a17 (result f32) + (local $var$0 f32) + (local $1 f32) + (local $2 f32) + (local $3 f32) + (local $4 f32) + (local $5 f32) + (local.set $1 + (local.get $var$0) + ) + (local.set $var$0 + (f32.const -137438953472) + ) + (local.set $2 + (local.get $var$0) + ) + (local.set $3 + (local.get $var$0) + ) + (local.set $4 + (select + (local.get $2) + (local.get $3) + (i32.const 0) + ) + ) + (local.set $5 + (f32.max + (local.get $1) + (local.get $4) + ) + ) + (return + (local.get $5) + ) + ) + (func $a18 (result i32) + (local $0 i32) + (local $1 i32) + (block $label$1 + (unreachable) + (local.set $0 + (i32.const 1) + ) + (br_if $label$1 + (unreachable) + ) + (unreachable) + (drop + (unreachable) + ) + (i32.load + (unreachable) + ) + (unreachable) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $a19 (result f32) + (block $label$0 + (block $label$1 + (unreachable) + (return + (f32.const 4289944320) + ) + (select + (unreachable) + (unreachable) + (i32.const 65535) + ) + (drop + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (func $call-me (param $0 i32) (param $1 i32) + (nop) + ) + (func $code-to-kill + (local $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block $out + (br $out) + (unreachable) + (drop + (i32.const 0) + ) + (if + (i32.const 1) + (drop + (i32.const 2) + ) + ) + (br_table $out $out $out $out + (i32.const 3) + ) + (unreachable) + (call $code-to-kill) + ) + (if + (i32.const 0) + (block + (block $out1 + (unreachable) + (unreachable) + (drop + (i32.const 0) + ) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block + (block $out3 + (return) + (unreachable) + (drop + (i32.const 0) + ) + ) + (unreachable) + ) + ) + (block $out4 + (br_table $out4 $out4 $out4 $out4 + (i32.const 4) + ) + (unreachable) + (drop + (i32.const 0) + ) + ) + (block $out5 + (br_if $out5 + (i32.const 3) + ) + (drop + (i32.const 0) + ) + ) + (if + (i32.const 0) + (block + (block $block4 + (if + (i32.const 0) + (block + (block $out8 + (unreachable) + (unreachable) + (drop + (i32.const 0) + ) + ) + (unreachable) + ) + (block + (block $out9 + (unreachable) + (unreachable) + (drop + (i32.const 0) + ) + ) + (unreachable) + ) + ) + (unreachable) + (drop + (i32.const 0) + ) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block + (block $out11 + (unreachable) + (unreachable) + (unreachable) + (drop + (i32.const 0) + ) + (unreachable) + (unreachable) + ) + (local.set $2 + (local.get $1) + ) + (drop + (local.get $2) + ) + ) + ) + (if + (i32.const 0) + (block + (block $out13 + (unreachable) + (unreachable) + (unreachable) + (drop + (i32.const 0) + ) + (unreachable) + (unreachable) + ) + (local.set $4 + (local.get $3) + ) + (drop + (local.get $4) + ) + ) + ) + (if + (i32.const 0) + (block + (block $out15 + (unreachable) + (unreachable) + (unreachable) + (unreachable) + (drop + (i32.const 0) + ) + (unreachable) + (unreachable) + ) + (local.set $6 + (local.get $5) + ) + (drop + (local.get $6) + ) + ) + ) + (block $out16 + (block $in + (br_if $out16 + (i32.const 1) + ) + ) + (unreachable) + (unreachable) + ) + (if + (i32.const 0) + (block + (block $block11 + (block $out18 + (block $in19 + (br_if $in19 + (i32.const 1) + ) + ) + (unreachable) + (unreachable) + ) + (unreachable) + (drop + (i32.const 10) + ) + ) + (unreachable) + ) + ) + (block $out20 + (block $in21 + (br_table $out20 $in21 + (i32.const 1) + ) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (block $out22 + (block $in23 + (br_table $in23 $out22 + (i32.const 1) + ) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (if + (i32.const 0) + (block + (block $block13 + (block $out25 + (block $in26 + (br_table $in26 $in26 + (i32.const 1) + ) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (unreachable) + (drop + (i32.const 10) + ) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block + (block $block15 + (drop + (i32.const 10) + ) + (drop + (i32.const 42) + ) + (unreachable) + (unreachable) + (unreachable) + (return + (unreachable) + ) + (unreachable) + (unreachable) + (unreachable) + (return) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block + (loop $loop-in18 + (unreachable) + (unreachable) + ) + (unreachable) + ) + ) + (block $out29 + (loop $in30 + (block + (br_if $out29 + (i32.const 1) + ) + (unreachable) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (if + (i32.const 0) + (block + (block $block20 + (loop $in32 + (block + (br_if $in32 + (i32.const 1) + ) + (unreachable) + (unreachable) + ) + (unreachable) + ) + (unreachable) + (drop + (i32.const 10) + ) + ) + (unreachable) + ) + ) + (if + (i32.const 1) + (block + (unreachable) + (call $call-me + (i32.const 123) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 2) + (block + (unreachable) + (call $call-me + (unreachable) + (i32.const 0) + ) + (unreachable) + ) + ) + (if + (i32.const 3) + (block + (unreachable) + (unreachable) + (call $call-me + (unreachable) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const -1) + (block + (unreachable) + (call_indirect (type $i32_i32_=>_none) + (i32.const 123) + (i32.const 456) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const -2) + (block + (unreachable) + (call_indirect (type $i32_i32_=>_none) + (i32.const 139) + (unreachable) + (i32.const 0) + ) + (unreachable) + ) + ) + (if + (i32.const -3) + (block + (unreachable) + (unreachable) + (call_indirect (type $i32_i32_=>_none) + (i32.const 246) + (unreachable) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const -4) + (block + (unreachable) + (unreachable) + (unreachable) + (call_indirect (type $i32_i32_=>_none) + (unreachable) + (unreachable) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 11) + (block + (unreachable) + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 22) + (block + (unreachable) + (i32.load + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 33) + (block + (unreachable) + (i32.store + (i32.const 0) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 44) + (block + (unreachable) + (i32.store + (unreachable) + (i32.const 0) + ) + (unreachable) + ) + ) + (if + (i32.const 55) + (block + (unreachable) + (unreachable) + (i32.store + (unreachable) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 66) + (block + (unreachable) + (i32.eqz + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 77) + (block + (unreachable) + (i32.add + (unreachable) + (i32.const 0) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 88) + (block + (unreachable) + (i32.add + (i32.const 0) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 99) + (block + (unreachable) + (unreachable) + (i32.add + (unreachable) + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 100) + (block + (unreachable) + (select + (i32.const 123) + (i32.const 456) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 101) + (block + (unreachable) + (select + (i32.const 123) + (unreachable) + (i32.const 456) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (if + (i32.const 102) + (block + (unreachable) + (select + (unreachable) + (i32.const 123) + (i32.const 456) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (drop + (i32.const 1337) + ) + ) + (func $killer + (block + (unreachable) + (unreachable) + (drop + (i32.const 1000) + ) + ) + (unreachable) + ) + (func $target + (drop + (i32.const 2000) + ) + ) + (func $typed-block-none-then-unreachable (result i32) + (local $0 i32) + (local $1 i32) + (block $top-typed + (block $switch$0 + (return + (i32.const 0) + ) + (unreachable) + (br $switch$0) + (unreachable) + ) + (return + (i32.const 1) + ) + (unreachable) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $typed-block-remove-br-changes-type (param $$$0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block + (block $switch$7 + (block $switch-default$10 + (block $switch-case$9 + (block $switch-case$8 + (br_table $switch-case$9 $switch-case$8 $switch-default$10 + (i32.const -1) + ) + (unreachable) + ) + ) + (local.set $1 + (local.get $$$0) + ) + (return + (local.get $1) + ) + (unreachable) + (br $switch$7) + (unreachable) + ) + (local.set $2 + (local.get $$$0) + ) + (return + (local.get $2) + ) + (unreachable) + ) + (return + (i32.const 0) + ) + (unreachable) + ) + (local.set $4 + (local.get $3) + ) + (return + (local.get $4) + ) + ) + (func $global + (local $0 i32) + (block + (unreachable) + (unreachable) + (local.set $0 + (global.get $x) + ) + (drop + (local.get $0) + ) + (global.set $x + (i32.const 1) + ) + ) + (unreachable) + ) + (func $ret (result i32) + (local $0 i32) + (local $1 i32) + (block + (return + (i32.const 0) + ) + (unreachable) + (nop) + (local.set $0 + (i32.const 0) + ) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $unreachable-br (result i32) + (local $0 i32) + (local $1 i32) + (block $out + (local.set $0 + (i32.const 0) + ) + (br $out) + (unreachable) + (unreachable) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $unreachable-br-loop (result i32) + (loop $out + (br $out) + (unreachable) + ) + (unreachable) + ) + (func $unreachable-block-ends-switch (result i32) + (local $0 i32) + (local $1 i32) + (block $label$0 + (block $label$3 + (nop) + (unreachable) + (br_table $label$3 + (unreachable) + ) + (unreachable) + (unreachable) + (unreachable) + ) + (local.set $0 + (i32.const 19) + ) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $unreachable-block-ends-br_if (result i32) + (local $0 i32) + (local $1 i32) + (block $label$0 + (block $label$2 + (nop) + (unreachable) + (br_if $label$2 + (unreachable) + ) + (unreachable) + (unreachable) + (unreachable) + ) + (local.set $0 + (i32.const 19) + ) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $unreachable-brs-3 (result i32) + (local $0 i32) + (local $1 i32) + (block $label$0 + (local.set $0 + (i32.const 18) + ) + (br $label$0) + (memory.grow + (unreachable) + ) + (unreachable) + (unreachable) + (local.set $0 + (i32.const 21) + ) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $unreachable-brs-4 (param $var$0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block $label$0 + (block $label$1 + (unreachable) + (local.set $1 + (i32.const 4104) + ) + (br_if $label$0 + (unreachable) + ) + (unreachable) + (drop + (unreachable) + ) + (unreachable) + (local.set $2 + (i32.const 4) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $1 + (local.get $3) + ) + (br $label$0) + (unreachable) + (local.set $1 + (i32.const 16) + ) + ) + (local.set $4 + (local.get $1) + ) + (local.set $5 + (i32.add + (i32.const 1) + (local.get $4) + ) + ) + (return + (local.get $5) + ) + ) + (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) + (local $2 i64) + (local $3 i64) + (local $4 i32) + (local $5 i64) + (local $6 i64) + (local $7 i64) + (local $8 i64) + (local $9 i64) + (local $10 i64) + (local $11 i64) + (local $12 i64) + (local $13 i64) + (local $14 i64) + (local $15 i64) + (local $16 i64) + (local $17 i64) + (block + (local.set $3 + (local.get $var$0) + ) + (local.set $4 + (i64.eqz + (local.get $3) + ) + ) + (if + (local.get $4) + (block + (block $label$0 + (local.set $5 + (local.get $var$1) + ) + (local.set $6 + (local.get $5) + ) + ) + (local.set $7 + (local.get $6) + ) + (local.set $16 + (local.get $7) + ) + ) + (block + (block $label$1 + (local.set $8 + (local.get $var$0) + ) + (local.set $9 + (i64.sub + (local.get $8) + (i64.const 1) + ) + ) + (block $block + (local.set $10 + (local.get $var$0) + ) + (local.set $2 + (local.get $10) + ) + (nop) + (local.set $11 + (local.get $2) + ) + (local.set $12 + (local.get $11) + ) + ) + (local.set $13 + (local.get $12) + ) + (unreachable) + (i64.mul + (local.get $13) + (unreachable) + ) + (call $call-unreach + (local.get $9) + (unreachable) + ) + (unreachable) + ) + (local.set $15 + (local.get $14) + ) + (local.set $16 + (local.get $15) + ) + ) + ) + ) + (local.set $17 + (local.get $16) + ) + (return + (local.get $17) + ) + ) + (func $test-flatten + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 i32) + (local $24 i32) + (local $25 i32) + (local $26 i32) + (local $27 i32) + (local $28 i32) + (local $29 i32) + (local $30 i32) + (local $31 i32) + (local $32 i32) + (local $33 i32) + (local $34 i32) + (local $35 i32) + (local $36 i32) + (local $37 i32) + (local $38 i32) + (local $39 i32) + (block $out + (local.set $0 + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (local.get $0) + ) + (br $out) + (i32.add + (i32.const 1) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + (br $out) + (i32.add + (unreachable) + (i32.const 1) + ) + (drop + (unreachable) + ) + (unreachable) + (br_table $out $out $out $out + (i32.const 3) + ) + (i32.add + (i32.const 1) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + (block $block + (drop + (i32.const 2) + ) + (drop + (i32.const 3) + ) + (local.set $1 + (i32.const 4) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (i32.add + (i32.const 1) + (local.get $2) + ) + ) + (drop + (local.get $3) + ) + (block $in + (block $switch-in + (local.set $4 + (i32.const 2) + ) + (local.set $5 + (local.get $4) + ) + (local.set $6 + (local.get $4) + ) + (br_table $in $switch-in $in + (i32.const 777) + ) + (unreachable) + ) + (local.set $7 + (local.get $6) + ) + (drop + (local.get $7) + ) + (local.set $5 + (i32.const 3) + ) + (br $in) + (unreachable) + (local.set $5 + (i32.const 4) + ) + ) + (local.set $8 + (local.get $5) + ) + (local.set $9 + (i32.add + (i32.const 1) + (local.get $8) + ) + ) + (drop + (local.get $9) + ) + (loop $loop-in + (local.set $10 + (i32.const 5) + ) + ) + (local.set $11 + (local.get $10) + ) + (local.set $12 + (i32.add + (i32.const 1) + (local.get $11) + ) + ) + (drop + (local.get $12) + ) + (if + (i32.const 6) + (local.set $13 + (i32.const 7) + ) + (local.set $13 + (i32.const 8) + ) + ) + (local.set $14 + (local.get $13) + ) + (local.set $15 + (i32.add + (i32.const 1) + (local.get $14) + ) + ) + (drop + (local.get $15) + ) + (local.set $16 + (select + (i32.const 9) + (i32.const 10) + (i32.const 11) + ) + ) + (drop + (local.get $16) + ) + (br $out) + (select + (unreachable) + (i32.const 10) + (i32.const 11) + ) + (drop + (unreachable) + ) + (unreachable) + (br $out) + (select + (i32.const 9) + (unreachable) + (i32.const 11) + ) + (drop + (unreachable) + ) + (unreachable) + (br $out) + (select + (i32.const 9) + (i32.const 10) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + (if + (i32.const 11) + (local.set $17 + (i32.const 12) + ) + (local.set $17 + (i32.const 13) + ) + ) + (local.set $18 + (local.get $17) + ) + (local.set $19 + (select + (local.get $18) + (i32.const 9) + (i32.const 10) + ) + ) + (drop + (local.get $19) + ) + (if + (i32.const 11) + (local.set $20 + (i32.const 12) + ) + (local.set $20 + (i32.const 13) + ) + ) + (local.set $21 + (local.get $20) + ) + (local.set $22 + (select + (i32.const 9) + (local.get $21) + (i32.const 10) + ) + ) + (drop + (local.get $22) + ) + (if + (i32.const 11) + (local.set $23 + (i32.const 12) + ) + (local.set $23 + (i32.const 13) + ) + ) + (local.set $24 + (local.get $23) + ) + (local.set $25 + (select + (i32.const 9) + (i32.const 10) + (local.get $24) + ) + ) + (drop + (local.get $25) + ) + (if + (i32.const 11) + (local.set $26 + (i32.const 12) + ) + (local.set $26 + (i32.const 13) + ) + ) + (local.set $27 + (local.get $26) + ) + (if + (i32.const 15) + (local.set $28 + (i32.const 16) + ) + (local.set $28 + (i32.const 17) + ) + ) + (local.set $29 + (local.get $28) + ) + (local.set $30 + (select + (local.get $27) + (i32.const 14) + (local.get $29) + ) + ) + (drop + (local.get $30) + ) + (return) + (i32.add + (i32.const 1) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + (unreachable) + (i32.add + (i32.const 1) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + (block + (if + (i32.const 5) + (local.set $31 + (i32.const 6) + ) + (local.set $31 + (i32.const 7) + ) + ) + (local.set $32 + (local.get $31) + ) + (if + (local.get $32) + (local.set $35 + (i32.const 8) + ) + (block + (if + (i32.const 9) + (local.set $33 + (i32.const 10) + ) + (local.set $33 + (i32.const 11) + ) + ) + (local.set $34 + (local.get $33) + ) + (local.set $35 + (local.get $34) + ) + ) + ) + ) + (local.set $36 + (local.get $35) + ) + (drop + (local.get $36) + ) + (block $temp + (local.set $37 + (i32.const 1) + ) + (br_if $temp + (i32.const 2) + ) + (local.set $38 + (local.get $37) + ) + (local.set $37 + (local.get $38) + ) + ) + (local.set $39 + (local.get $37) + ) + (drop + (local.get $39) + ) + ) + ) + (func $flatten-return-value (result i32) + (local $0 i32) + (local $1 i32) + (block + (return + (i32.const 2) + ) + (i32.add + (i32.const 1) + (unreachable) + ) + (drop + (unreachable) + ) + (unreachable) + (local.set $0 + (i32.const 3) + ) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + (func $unbug + (local $12 i32) + (local $432 i32) + (local $430 i32) + (local $431 i32) + (local $9 i32) + (local $5 i32) + (local $433 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (block $block + (block + (local.set $7 + (local.get $12) + ) + (local.set $8 + (i32.eq + (local.get $7) + (i32.const 65535) + ) + ) + (if + (local.get $8) + (block $block44 + (block $label$78 + (local.set $430 + (i32.const 0) + ) + ) + (local.set $9 + (local.get $430) + ) + (local.set $432 + (local.get $9) + ) + ) + (block $block45 + (block $label$79 + (local.set $10 + (local.get $9) + ) + (local.set $11 + (local.get $5) + ) + (local.set $12 + (local.get $12) + ) + (local.set $13 + (i32.mul + (local.get $12) + (i32.const 12) + ) + ) + (local.set $14 + (i32.add + (local.get $11) + (local.get $13) + ) + ) + (local.set $15 + (i32.load16_u offset=2 + (local.get $14) + ) + ) + (local.set $16 + (i32.lt_u + (local.get $10) + (local.get $15) + ) + ) + (local.set $431 + (local.get $16) + ) + ) + (local.set $17 + (local.get $431) + ) + (local.set $432 + (local.get $17) + ) + ) + ) + ) + (local.set $433 + (i32.const 1) + ) + (local.set $18 + (local.get $432) + ) + (local.set $19 + (local.get $433) + ) + (local.set $20 + (i32.xor + (local.get $18) + (local.get $19) + ) + ) + (local.set $21 + (local.get $20) + ) + ) + (local.set $22 + (local.get $21) + ) + (drop + (local.get $22) + ) + ) + (func $outer-block-typed (param $var$0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block $block + (block $label$0 + (local.set $1 + (i32.const 16) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (i32.add + (i32.const 1) + (local.get $2) + ) + ) + (local.set $4 + (local.get $3) + ) + ) + (local.set $5 + (local.get $4) + ) + (return + (local.get $5) + ) + ) + (func $nested-br_if-with-value (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block $label$0 + (block $block + (local.set $1 + (local.get $0) + ) + (local.set $2 + (local.get $1) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $4 + (i32.const 0) + ) + (br_if $label$0 + (local.get $3) + ) + (local.set $5 + (local.get $4) + ) + (drop + (local.get $5) + ) + (local.set $4 + (i32.const 1) + ) + ) + (local.set $6 + (local.get $4) + ) + (return + (local.get $6) + ) + ) + (func $switch-unreachable + (block $label$3 + (unreachable) + (br_table $label$3 + (unreachable) + ) + (unreachable) + ) + ) + (func $br_if_order (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block $outer + (block $inner + (local.set $1 + (i32.const 0) + ) + (br_if $outer + (i32.const 1) + ) + (local.set $2 + (local.get $1) + ) + (block $block + (local.set $3 + (i32.const -16) + ) + ) + (local.set $4 + (local.get $3) + ) + (local.set $5 + (call $br_if_order + (local.get $4) + ) + ) + (local.set $6 + (local.get $2) + ) + (br_if $inner + (local.get $5) + ) + (local.set $7 + (local.get $6) + ) + (local.set $6 + (local.get $7) + ) + ) + (local.set $8 + (local.get $6) + ) + (local.set $1 + (local.get $8) + ) + ) + (local.set $9 + (local.get $1) + ) + (return + (local.get $9) + ) + ) + (func $tees (param $x i32) (param $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $2 + (local.get $x) + ) + (drop + (local.get $2) + ) + (unreachable) + (unreachable) + (drop + (unreachable) + ) + (unreachable) + (local.set $x + (i32.const 2) + ) + (local.set $3 + (local.get $x) + ) + (local.set $y + (local.get $3) + ) + (local.set $4 + (local.get $y) + ) + (drop + (local.get $4) + ) + ) + (unreachable) + ) + (func $return (param $x i32) (result i32) + (local $1 i32) + (local.set $1 + (i32.sub + (i32.const 1) + (i32.const 2) + ) + ) + (return + (local.get $1) + ) + (unreachable) + ) + (func $subtype (result anyref) + (local $0 externref) + (local $1 anyref) + (local $2 externref) + (local $3 externref) + (local $4 externref) + (local $5 externref) + (local $6 externref) + (local $7 anyref) + (block $label0 + (block $block + (local.set $1 + (ref.null extern) + ) + (local.set $2 + (ref.null extern) + ) + (br_if $label0 + (i32.const 0) + ) + (local.set $3 + (local.get $2) + ) + (local.set $0 + (local.get $3) + ) + (local.set $4 + (local.get $0) + ) + (local.set $5 + (local.get $4) + ) + ) + (local.set $6 + (local.get $5) + ) + (local.set $1 + (local.get $6) + ) + ) + (local.set $7 + (local.get $1) + ) + (return + (local.get $7) + ) + ) +) +(module + (type $i64_f32_=>_none (func (param i64 f32))) + (type $none_=>_i32 (func (result i32))) + (export "test" (func $1)) + (func $0 (param $0 i64) (param $1 f32) + (nop) + ) + (func $1 (result i32) + (unreachable) + (return + (i32.const -111) + ) + (call $0 + (unreachable) + (unreachable) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/flatten_all-features.wast binaryen-99/test/passes/flatten_all-features.wast --- binaryen-108/test/passes/flatten_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1057 @@ +(module + (type $ii (func (param i32 i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (type $3 (func (param i32) (result i32))) + (type $4 (func (param i64 i64) (result i64))) + (global $x (mut i32) (i32.const 0)) + (table 1 1 funcref) + (elem (i32.const 0) $call-me) + (memory $0 10) + (func $a1 + (drop (i32.add (i32.const 0) (i32.const 1))) + ) + (func $a2 (result i32) + (i32.add (i32.const 0) (i32.const 1)) + ) + (func $a3 (result i32) + (i32.add + (i32.const 0) + (block (result i32) + (i32.const 1) + ) + ) + ) + (func $a4 + (drop + (i32.add + (i32.const 0) + (block (result i32) + (i32.const 1) + ) + ) + ) + ) + (func $a5 (result i32) + (i32.add + (block (result i32) + (i32.const 0) + ) + (block (result i32) + (i32.const 1) + ) + ) + ) + (func $a6 (result i32) + (local $x i32) + (i32.add + (block (result i32) + (local.tee $x + (i32.const 0) + ) + ) + (block (result i32) + (local.tee $x + (i32.const 1) + ) + ) + ) + ) + (func $a7 (result i32) + (local $x i32) + (block (result i32) + (i32.add + (block (result i32) + (local.tee $x + (i32.const 0) + ) + ) + (block (result i32) + (local.tee $x + (i32.const 1) + ) + ) + ) + ) + ) + (func $a8 (result i32) + (local $x i32) + (block $outer (result i32) + (block $inner (result i32) + (i32.add + (block (result i32) + (br $inner + (i32.const -1) + ) + (br $outer + (i32.const 0) + ) + (i32.const 1) + ) + (block (result i32) + (br $outer + (i32.const 2) + ) + (local.tee $x + (i32.const 3) + ) + ) + ) + ) + ) + ) + (func $a9 (result i32) + (loop $outer (result i32) + (loop $inner (result i32) + (br_if $outer (i32.const -1)) + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + ) + ) + (func $a10 (result i32) + (local $x i32) + (block $outer (result i32) + (drop (br_if $outer (i32.const 0) (i32.const 1))) + (drop (br_if $outer (local.tee $x (i32.const 2)) (i32.const 3))) + (drop (br_if $outer (i32.const 4) (local.tee $x (i32.const 5)))) + (drop (br_if $outer (local.tee $x (i32.const 6)) (local.tee $x (i32.const 7)))) + (br $outer (i32.const 8)) + ) + ) + (func $a11 + (if (i32.const 0) + (drop (i32.const 1)) + ) + ) + (func $a12 (result i32) + (if (result i32) (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + ) + (func $a13 (result i32) + (block $x i32 + (if i32 + (br_table $x (i32.const 2) (i32.const 0)) + (i32.const 0) + (i32.const 1) + ) + ) + ) + (func $a14 (result i32) + (block i32 + (select + (i32.const 0) (i32.const 1) (br_table 0 (i32.const 7) (i32.const 1)) + ) + ) + ) + (func $a15 + (if + (i32.load16_u + (i32.const 53) + ) + (unreachable) + (drop + (block $label$3 (result f32) + (unreachable) + ) + ) + ) + ) + (func $a16 (result i32) + (local $x i32) + (block $label$1 (result i32) + (drop + (br_if $label$1 + (local.tee $x ;; set here, then it is undone later, but this value is used, not the contents of $x! + (i32.const 1) + ) + (i32.eqz ;; 0 into 1, so take the br_if + (block $label$2 (result i32) + (local.set $x + (i32.const 0) ;; undo the above tee + ) + (i32.const 0) + ) + ) + ) + ) + (i32.const 0) + ) + ) + (func $a17 (result f32) + (local $var$0 f32) + (f32.max + (local.get $var$0) + (select + (local.tee $var$0 + (f32.const -137438953472) + ) + (local.get $var$0) + (i32.const 0) + ) + ) + ) + (func $a18 (result i32) + (block $label$1 (result i32) + (i32.load16_s + (drop ;; an unreachable drop. one we move its contents outside, it should stay unreachable + (br_if $label$1 + (i32.const 1) + (unreachable) + ) + ) + ) + ) + ) + (func $a19 (result f32) + (block $label$0 + (block $label$1 + (drop + (select + (unreachable) ;; move this out, so it happens before the return + (return + (f32.const 4289944320) + ) + (i32.const 65535) + ) + ) + ) + ) + ) + (func $call-me (param $0 i32) (param $1 i32) + (nop) + ) + (func $code-to-kill + (local $x i32) + (block $out + (br $out) + (drop + (i32.const 0) + ) + (if + (i32.const 1) + (drop + (i32.const 2) + ) + ) + (br_table $out $out $out $out + (i32.const 3) + ) + (call $code-to-kill) + ) + (if + (i32.const 0) + (block $out1 + (unreachable) + (drop + (i32.const 0) + ) + ) + ) + (if + (i32.const 0) + (block $out3 + (return) + (drop + (i32.const 0) + ) + ) + ) + (block $out4 + (br_table $out4 $out4 $out4 $out4 + (i32.const 4) + ) + (drop + (i32.const 0) + ) + ) + (block $out5 + (br_if $out5 + (i32.const 3) + ) + (drop + (i32.const 0) + ) + ) + (if + (i32.const 0) + (block $block4 + (if + (i32.const 0) + (block $out8 + (unreachable) + (drop + (i32.const 0) + ) + ) + (block $out9 + (unreachable) + (drop + (i32.const 0) + ) + ) + ) + (drop + (i32.const 0) + ) + ) + ) + (if + (i32.const 0) + (drop + (block $out11 (result i32) + (br $out11 + (unreachable) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (if + (i32.const 0) + (drop + (block $out13 (result i32) + (br_if $out13 + (unreachable) + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (if + (i32.const 0) + (drop + (block $out15 (result i32) + (br_if $out15 + (unreachable) + (unreachable) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (block $out16 + (block $in + (br_if $out16 + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.const 0) + (block $block11 + (block $out18 + (block $in19 + (br_if $in19 + (i32.const 1) + ) + ) + (unreachable) + ) + (drop + (i32.const 10) + ) + ) + ) + (block $out20 + (block $in21 + (br_table $out20 $in21 + (i32.const 1) + ) + ) + (unreachable) + ) + (block $out22 + (block $in23 + (br_table $in23 $out22 + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (i32.const 0) + (block $block13 + (block $out25 + (block $in26 + (br_table $in26 $in26 + (i32.const 1) + ) + ) + (unreachable) + ) + (drop + (i32.const 10) + ) + ) + ) + (if + (i32.const 0) + (block $block15 + (drop + (i32.const 10) + ) + (drop + (i32.const 42) + ) + (unreachable) + (return + (unreachable) + ) + (unreachable) + (return) + ) + ) + (if + (i32.const 0) + (loop $loop-in18 + (unreachable) + ) + ) + (block $out29 + (loop $in30 + (br_if $out29 + (i32.const 1) + ) + (unreachable) + ) + ) + (if + (i32.const 0) + (block $block20 + (loop $in32 + (br_if $in32 + (i32.const 1) + ) + (unreachable) + ) + (drop + (i32.const 10) + ) + ) + ) + (if + (i32.const 1) + (call $call-me + (i32.const 123) + (unreachable) + ) + ) + (if + (i32.const 2) + (call $call-me + (unreachable) + (i32.const 0) + ) + ) + (if + (i32.const 3) + (call $call-me + (unreachable) + (unreachable) + ) + ) + (if + (i32.const -1) + (call_indirect (type $ii) + (i32.const 123) + (i32.const 456) + (unreachable) + ) + ) + (if + (i32.const -2) + (call_indirect (type $ii) + (i32.const 139) + (unreachable) + (i32.const 0) + ) + ) + (if + (i32.const -3) + (call_indirect (type $ii) + (i32.const 246) + (unreachable) + (unreachable) + ) + ) + (if + (i32.const -4) + (call_indirect (type $ii) + (unreachable) + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 11) + (local.set $x + (unreachable) + ) + ) + (if + (i32.const 22) + (drop + (i32.load + (unreachable) + ) + ) + ) + (if + (i32.const 33) + (i32.store + (i32.const 0) + (unreachable) + ) + ) + (if + (i32.const 44) + (i32.store + (unreachable) + (i32.const 0) + ) + ) + (if + (i32.const 55) + (i32.store + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 66) + (drop + (i32.eqz + (unreachable) + ) + ) + ) + (if + (i32.const 77) + (drop + (i32.add + (unreachable) + (i32.const 0) + ) + ) + ) + (if + (i32.const 88) + (drop + (i32.add + (i32.const 0) + (unreachable) + ) + ) + ) + (if + (i32.const 99) + (i32.add + (unreachable) + (unreachable) + ) + ) + (if + (i32.const 100) + (drop + (select + (i32.const 123) + (i32.const 456) + (unreachable) + ) + ) + ) + (if + (i32.const 101) + (drop + (select + (i32.const 123) + (unreachable) + (i32.const 456) + ) + ) + ) + (if + (i32.const 102) + (drop + (select + (unreachable) + (i32.const 123) + (i32.const 456) + ) + ) + ) + (drop + (i32.const 1337) + ) + ) + (func $killer (type $1) + (unreachable) + (drop + (i32.const 1000) + ) + ) + (func $target (type $1) + (drop + (i32.const 2000) + ) + ) + (func $typed-block-none-then-unreachable (type $2) (result i32) + (block $top-typed (result i32) + (block $switch$0 + (return + (i32.const 0) + ) + (br $switch$0) + ) + (return + (i32.const 1) + ) + ) + ) + (func $typed-block-remove-br-changes-type (type $3) (param $$$0 i32) (result i32) + (block $switch$7 + (block $switch-default$10 + (block $switch-case$9 + (block $switch-case$8 + (br_table $switch-case$9 $switch-case$8 $switch-default$10 + (i32.const -1) + ) + ) + ) + (return + (local.get $$$0) + ) + (br $switch$7) + ) + (return + (local.get $$$0) + ) + ) + (return + (i32.const 0) + ) + ) + (func $global (type $1) + (unreachable) + (drop + (global.get $x) + ) + (global.set $x + (i32.const 1) + ) + ) + (func $ret (type $2) (result i32) + (return + (i32.const 0) + ) + (nop) + (i32.const 0) + ) + (func $unreachable-br (type $2) (result i32) + (block $out (result i32) + (br $out + (br $out + (i32.const 0) + ) + ) + ) + ) + (func $unreachable-br-loop (type $2) (result i32) + (loop $out + (br $out) + ) + ) + (func $unreachable-block-ends-switch (type $2) (result i32) + (block $label$0 (result i32) + (block $label$3 + (nop) + (br_table $label$3 + (unreachable) + ) + (unreachable) + ) + (i32.const 19) + ) + ) + (func $unreachable-block-ends-br_if (result i32) + (block $label$0 (result i32) + (block $label$2 + (nop) + (br_if $label$2 + (unreachable) + ) + (unreachable) + ) + (i32.const 19) + ) + ) + (func $unreachable-brs-3 (result i32) + (block $label$0 (result i32) + (br $label$0 + (memory.grow + (br $label$0 + (i32.const 18) + ) + ) + ) + (i32.const 21) + ) + ) + (func $unreachable-brs-4 (param $var$0 i32) (result i32) + (i32.add + (i32.const 1) + (block $label$0 (result i32) + (br $label$0 + (block $label$1 (result i32) + (drop + (br_if $label$0 + (i32.const 4104) + (unreachable) + ) + ) + (i32.const 4) + ) + ) + (i32.const 16) + ) + ) + ) + (func $call-unreach (param $var$0 i64) (param $var$1 i64) (result i64) + (local $2 i64) + (if (result i64) + (i64.eqz + (local.get $var$0) + ) + (block $label$0 (result i64) + (local.get $var$1) + ) + (block $label$1 (result i64) + (call $call-unreach + (i64.sub + (local.get $var$0) + (i64.const 1) + ) + (i64.mul + (block $block (result i64) + (local.set $2 + (local.get $var$0) + ) + (nop) + (local.get $2) + ) + (unreachable) + ) + ) + ) + ) + ) + + ;; flatten-specific + (func $test-flatten + (block $out + (drop (i32.add (i32.const 1) (i32.const 2))) + (drop (i32.add (i32.const 1) (br $out))) + (drop (i32.add (br $out) (i32.const 1))) + (drop (i32.add (i32.const 1) (br_table $out $out $out $out (i32.const 3)))) + (drop (i32.add (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop (i32.const 3)) + (i32.const 4) + ) + )) + (drop (i32.add (i32.const 1) + (block $in (result i32) + (drop + (block $switch-in (result i32) + (br_table $in $switch-in $in (i32.const 2) (i32.const 777)) + ) + ) + (br $in (i32.const 3)) + (i32.const 4) + ) + )) + (drop (i32.add (i32.const 1) + (loop (result i32) + (i32.const 5) + ) + )) + (drop (i32.add (i32.const 1) + (if (result i32) + (i32.const 6) + (i32.const 7) + (i32.const 8) + ) + )) + (drop + (select + (i32.const 9) + (i32.const 10) + (i32.const 11) + ) + ) + (drop + (select + (br $out) + (i32.const 10) + (i32.const 11) + ) + ) + (drop + (select + (i32.const 9) + (br $out) + (i32.const 11) + ) + ) + (drop + (select + (i32.const 9) + (i32.const 10) + (br $out) + ) + ) + (drop + (select + (if (result i32) + (i32.const 11) + (i32.const 12) + (i32.const 13) + ) + (i32.const 9) + (i32.const 10) + ) + ) + (drop + (select + (i32.const 9) + (if (result i32) + (i32.const 11) + (i32.const 12) + (i32.const 13) + ) + (i32.const 10) + ) + ) + (drop + (select + (i32.const 9) + (i32.const 10) + (if (result i32) + (i32.const 11) + (i32.const 12) + (i32.const 13) + ) + ) + ) + (drop + (select + (if (result i32) + (i32.const 11) + (i32.const 12) + (i32.const 13) + ) + (i32.const 14) + (if (result i32) + (i32.const 15) + (i32.const 16) + (i32.const 17) + ) + ) + ) + (drop (i32.add (i32.const 1) (return))) + (drop (i32.add (i32.const 1) (unreachable))) + (drop + (if (result i32) + (if (result i32) + (i32.const 5) + (i32.const 6) + (i32.const 7) + ) + (i32.const 8) + (if (result i32) + (i32.const 9) + (i32.const 10) + (i32.const 11) + ) + ) + ) + (drop + (block $temp (result i32) + (br_if $temp + (i32.const 1) + (i32.const 2) + ) + ) + ) + ) + ) + (func $flatten-return-value (result i32) + (drop (i32.add (i32.const 1) (return (i32.const 2)))) + (i32.const 3) + ) + (func $unbug + (local $12 i32) + (local $432 i32) + (local $430 i32) + (local $431 i32) + (local $9 i32) + (local $5 i32) + (local $433 i32) + (drop + (block (result i32) + (if + (i32.eq + (local.get $12) + (i32.const 65535) + ) + (block + (block $label$78 + (local.set $430 + (i32.const 0) + ) + ) + (local.set $432 + (local.get $430) + ) + ) + (block + (block $label$79 + (local.set $431 + (i32.lt_u + (local.get $9) + (i32.load16_u offset=2 + (i32.add + (local.get $5) + (i32.mul + (local.get $12) + (i32.const 12) + ) + ) + ) + ) + ) + ) + (local.set $432 + (local.get $431) + ) + ) + ) + (local.set $433 + (i32.const 1) + ) + (i32.xor + (local.get $432) + (local.get $433) + ) + ) + ) + ) + (func $outer-block-typed (type $3) (param $var$0 i32) (result i32) + (block (result i32) + (i32.add + (i32.const 1) + (block $label$0 (result i32) + (i32.const 16) + ) + ) + ) + ) + (func $nested-br_if-with-value (result i32) + (local $0 i32) + (block $label$0 (result i32) + (drop + (br_if $label$0 + (i32.const 0) + (block (result i32) + (local.get $0) + ) + ) + ) + (i32.const 1) + ) + ) + (func $switch-unreachable + (block $label$3 + (br_table $label$3 + (unreachable) + ) + ) + ) + (func $br_if_order (param $x i32) (result i32) + (block $outer (result i32) + (block $inner (result i32) + (br_if $inner + (br_if $outer + (i32.const 0) + (i32.const 1) + ) + (call $br_if_order + (block (result i32) + (i32.const -16) + ) + ) + ) + ) + ) + ) + (func $tees (param $x i32) (param $y i32) + (drop (local.tee $x (i32.const 1))) + (drop (local.tee $x (unreachable))) + (drop (local.tee $y (local.tee $x (i32.const 2)))) + ) + (func $return (param $x i32) (result i32) + (return (i32.sub (i32.const 1) (i32.const 2))) + ) + + ;; subtypes + + ;; br_if leaves a value on the stack if not taken, which later can be the last + ;; element of the enclosing innermost block and flow out. So in case br_if + ;; targets an outer branch whose return type is a supertype of the br_if's + ;; value type, we need the value to be set into two locals: one with the outer + ;; block's type, and one with its value type. + (func $subtype (result anyref) + (local $0 externref) + (block $label0 (result anyref) + (block (result externref) + (local.tee $0 + (br_if $label0 + (ref.null extern) + (i32.const 0) + ) + ) + ) + ) + ) +) +(module + (func $0 (param $0 i64) (param $1 f32) + (nop) + ) + (func "test" (result i32) + (call $0 + (unreachable) ;; the unreachable should be handled properly, and not be + ;; reordered with the return + (return + (i32.const -111) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten.bin.txt binaryen-99/test/passes/flatten.bin.txt --- binaryen-108/test/passes/flatten.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/flatten.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,13 +1,13 @@ (module + (type $i64_f32_f64_i32_i32_=>_none (func (param i64 f32 f64 i32 i32))) (type $none_=>_i32 (func (result i32))) - (type $none_=>_i64 (func (result i64))) - (type $none_=>_f32 (func (result f32))) - (type $none_=>_f64 (func (result f64))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i64 (func (result i64))) (type $i64_=>_i64 (func (param i64) (result i64))) + (type $none_=>_f32 (func (result f32))) (type $f32_=>_f32 (func (param f32) (result f32))) + (type $none_=>_f64 (func (result f64))) (type $f64_=>_f64 (func (param f64) (result f64))) - (type $i64_f32_f64_i32_i32_=>_none (func (param i64 f32 f64 i32 i32))) (type $i64_f32_f64_i32_i32_=>_f64 (func (param i64 f32 f64 i32 i32) (result f64))) (export "type-local-i32" (func $0)) (export "type-local-i64" (func $1)) diff -Nru binaryen-108/test/passes/flatten_dfo_O3_enable-threads.txt binaryen-99/test/passes/flatten_dfo_O3_enable-threads.txt --- binaryen-108/test/passes/flatten_dfo_O3_enable-threads.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_dfo_O3_enable-threads.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,50 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $f64_=>_f64 (func (param f64) (result f64))) + (type $i64_i32_=>_f64 (func (param i64 i32) (result f64))) + (memory $0 (shared 1 1)) + (export "one" (func $0)) + (export "two" (func $1)) + (export "use-var" (func $2)) + (export "bad1" (func $3)) + (export "only-dfo" (func $4)) + (export "dfo-tee-get" (func $5)) + (func $0 (; has Stack IR ;) + (block $label$3 + (br_if $label$3 + (i32.load + (i32.const 3060) + ) + ) + ) + (unreachable) + ) + (func $1 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) + (func $2 (; has Stack IR ;) (param $0 i64) (param $1 i32) (result f64) + (loop $label$8 + (br_if $label$8 + (local.get $1) + ) + ) + (unreachable) + ) + (func $3 (; has Stack IR ;) + (i32.store + (i32.const 1) + (i32.const -16384) + ) + ) + (func $4 (; has Stack IR ;) (param $0 f64) (result f64) + (local $1 i32) + (loop $label$1 + (br $label$1) + ) + ) + (func $5 (; has Stack IR ;) (result i32) + (i32.const 1) + ) +) diff -Nru binaryen-108/test/passes/flatten_dfo_O3_enable-threads.wast binaryen-99/test/passes/flatten_dfo_O3_enable-threads.wast --- binaryen-108/test/passes/flatten_dfo_O3_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_dfo_O3_enable-threads.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,203 @@ +(module + (memory $0 (shared 1 1)) + (func "one" + (loop $label$2 + (br_if $label$2 + (block $label$3 (result i32) + (drop + (br_if $label$3 + (i32.const 0) + (i32.load + (i32.const 3060) + ) + ) + ) + (i32.const 0) + ) + ) + ) + (unreachable) + ) + (func "two" (param $var$0 i32) (param $var$1 i32) (result i32) + (nop) + (nop) + (nop) + (nop) + (nop) + (if + (i32.const 0) + (i32.store8 + (i32.const 8) + (block $label$2 (result i32) + (drop + (br_if $label$2 + (i32.const 1) + (i32.const 0) + ) + ) + (if + (i32.const 0) + (drop + (br_if $label$2 + (i32.const 1) + (i32.const 1) + ) + ) + ) + (block $label$4 + (br_if $label$4 + (i32.const 0) + ) + (br_if $label$4 + (i32.const 0) + ) + (drop + (br_if $label$2 + (i32.const 1) + (i32.const 0) + ) + ) + ) + (i32.const 6704) + ) + ) + ) + (nop) + (i32.const 0) + ) + (func "use-var" (param $var$0 i64) (param $var$1 i32) (result f64) + (local $var$2 i32) + (block $label$1 + (br_table $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 $label$1 + (i32.wrap_i64 + (if (result i64) + (i32.const 0) + (i64.const 1) + (if (result i64) + (if (result i32) + (i32.const 0) + (unreachable) + (block $label$6 (result i32) + (block $label$7 + (loop $label$8 + (br_if $label$8 + (br_if $label$6 + (local.tee $var$2 + (block $label$9 (result i32) + (local.get $var$1) + ) + ) + (i32.const 0) + ) + ) + (loop $label$10 + (if + (i32.const 0) + (local.set $var$2 + (local.get $var$1) + ) + ) + ) + (drop + (i32.eqz + (local.get $var$2) + ) + ) + ) + ) + (unreachable) + ) + ) + (unreachable) + (i64.const 1) + ) + ) + ) + ) + ) + (unreachable) + ) + (func "bad1" + (local $var$2 i32) + (local $var$4 i32) + (block $label$1 + (loop $label$2 + (local.set $var$4 + (if (result i32) + (i32.const 0) + (block (result i32) + (local.set $var$4 + (local.tee $var$2 + (i32.xor + (i32.const 0) + (i32.const -1) + ) + ) + ) + (i32.const 0) + ) + (block (result i32) + (local.set $var$4 + (local.tee $var$2 + (i32.xor + (i32.const 0) + (i32.const -1) + ) + ) + ) + (i32.const 0) + ) + ) + ) + (i32.store + (i32.const 1) + (i32.shl + (local.get $var$2) + (i32.const 14) + ) + ) + ) + ) + ) + (func "only-dfo" (param $var$0 f64) (result f64) + (local $var$1 i32) + (local $var$2 i32) + (loop $label$1 + (if + (local.tee $var$1 + (local.tee $var$2 + (local.get $var$1) + ) + ) + (if + (local.get $var$2) + (i64.atomic.store32 offset=3 + (i32.and + (local.get $var$1) ;; only dfo can figure out that this is 0 + (i32.const 15) + ) + (i64.const -32768) + ) + ) + ) + (br $label$1) + ) + ) + (func "dfo-tee-get" (result i32) + (local $0 i32) + (if (result i32) + (local.tee $0 + (i32.const 1) + ) + (loop $label$2 (result i32) + (select + (i32.const 1) + (i32.const -1709605511) + (local.get $0) + ) + ) + (unreachable) + ) + ) +) + diff -Nru binaryen-108/test/passes/flatten_i64-to-i32-lowering.txt binaryen-99/test/passes/flatten_i64-to-i32-lowering.txt --- binaryen-108/test/passes/flatten_i64-to-i32-lowering.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_i64-to-i32-lowering.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,572 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (type $none_=>_i64 (func (result i64))) + (import "env" "func" (func $import (result i64))) + (memory $0 1 1) + (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) + (func $defined (result i32) + (local $0 i32) + (local $0$hi i32) + (local $i64toi32_i32$0 i32) + (local $i64toi32_i32$1 i32) + (local $i64toi32_i32$2 i32) + (local $i64toi32_i32$3 i32) + (local $i64toi32_i32$4 i32) + (local $i64toi32_i32$5 i32) + (block + (local.set $0 + (block (result i32) + (local.set $i64toi32_i32$2 + (block (result i32) + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.const 1) + ) + ) + (local.set $i64toi32_i32$3 + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 2) + ) + ) + (local.set $i64toi32_i32$4 + (i32.add + (local.get $i64toi32_i32$2) + (local.get $i64toi32_i32$3) + ) + ) + (local.set $i64toi32_i32$5 + (i32.add + (local.get $i64toi32_i32$0) + (local.get $i64toi32_i32$1) + ) + ) + (if + (i32.lt_u + (local.get $i64toi32_i32$4) + (local.get $i64toi32_i32$3) + ) + (local.set $i64toi32_i32$5 + (i32.add + (local.get $i64toi32_i32$5) + (i32.const 1) + ) + ) + ) + (local.get $i64toi32_i32$4) + ) + ) + (local.set $0$hi + (local.get $i64toi32_i32$5) + ) + ) + (block + (local.set $i64toi32_i32$2 + (block (result i32) + (local.set $i64toi32_i32$5 + (local.get $0$hi) + ) + (local.get $0) + ) + ) + (global.set $i64toi32_i32$HIGH_BITS + (local.get $i64toi32_i32$5) + ) + (return + (local.get $i64toi32_i32$2) + ) + ) + ) + (func $unreachable-select-i64 (result i32) + (local $i64toi32_i32$0 i32) + (unreachable) + (block + (drop + (block (result i32) + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.const 1) + ) + ) + (unreachable) + (drop + (i32.const 2) + ) + ) + (unreachable) + ) + (func $unreachable-select-i64-b (result i32) + (local $i64toi32_i32$0 i32) + (unreachable) + (block + (unreachable) + (drop + (block (result i32) + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.const 3) + ) + ) + (drop + (i32.const 4) + ) + ) + (unreachable) + ) + (func $unreachable-select-i64-c (result i32) + (local $i64toi32_i32$0 i32) + (local $i64toi32_i32$1 i32) + (unreachable) + (block + (drop + (block (result i32) + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.const 5) + ) + ) + (drop + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 6) + ) + ) + (unreachable) + ) + (unreachable) + ) + (func $mem + (local $0 i32) + (local $0$hi i32) + (local $1 i32) + (local $1$hi i32) + (local $2 i32) + (local $2$hi i32) + (local $3 i32) + (local $3$hi i32) + (local $4 i32) + (local $4$hi i32) + (local $i64toi32_i32$0 i32) + (local $i64toi32_i32$1 i32) + (local $i64toi32_i32$2 i32) + (block + (local.set $0 + (block (result i32) + (local.set $i64toi32_i32$2 + (i32.const 0) + ) + (local.set $i64toi32_i32$0 + (i32.load + (local.get $i64toi32_i32$2) + ) + ) + (local.set $i64toi32_i32$1 + (i32.load offset=4 + (local.get $i64toi32_i32$2) + ) + ) + (local.get $i64toi32_i32$0) + ) + ) + (local.set $0$hi + (local.get $i64toi32_i32$1) + ) + ) + (drop + (block (result i32) + (local.set $i64toi32_i32$1 + (local.get $0$hi) + ) + (local.get $0) + ) + ) + (block + (local.set $1 + (block (result i32) + (local.set $i64toi32_i32$2 + (i32.const 0) + ) + (local.set $i64toi32_i32$1 + (i32.load + (local.get $i64toi32_i32$2) + ) + ) + (local.set $i64toi32_i32$0 + (i32.load offset=4 + (local.get $i64toi32_i32$2) + ) + ) + (local.get $i64toi32_i32$1) + ) + ) + (local.set $1$hi + (local.get $i64toi32_i32$0) + ) + ) + (drop + (block (result i32) + (local.set $i64toi32_i32$0 + (local.get $1$hi) + ) + (local.get $1) + ) + ) + (block + (local.set $2 + (block (result i32) + (local.set $i64toi32_i32$2 + (i32.const 0) + ) + (local.set $i64toi32_i32$0 + (i32.load align=2 + (local.get $i64toi32_i32$2) + ) + ) + (local.set $i64toi32_i32$1 + (i32.load offset=4 align=2 + (local.get $i64toi32_i32$2) + ) + ) + (local.get $i64toi32_i32$0) + ) + ) + (local.set $2$hi + (local.get $i64toi32_i32$1) + ) + ) + (drop + (block (result i32) + (local.set $i64toi32_i32$1 + (local.get $2$hi) + ) + (local.get $2) + ) + ) + (block + (local.set $3 + (block (result i32) + (local.set $i64toi32_i32$2 + (i32.const 0) + ) + (local.set $i64toi32_i32$1 + (i32.load align=1 + (local.get $i64toi32_i32$2) + ) + ) + (local.set $i64toi32_i32$0 + (i32.load offset=4 align=1 + (local.get $i64toi32_i32$2) + ) + ) + (local.get $i64toi32_i32$1) + ) + ) + (local.set $3$hi + (local.get $i64toi32_i32$0) + ) + ) + (drop + (block (result i32) + (local.set $i64toi32_i32$0 + (local.get $3$hi) + ) + (local.get $3) + ) + ) + (block + (local.set $4 + (block (result i32) + (local.set $i64toi32_i32$2 + (i32.const 0) + ) + (local.set $i64toi32_i32$0 + (i32.load + (local.get $i64toi32_i32$2) + ) + ) + (local.set $i64toi32_i32$1 + (i32.load offset=4 + (local.get $i64toi32_i32$2) + ) + ) + (local.get $i64toi32_i32$0) + ) + ) + (local.set $4$hi + (local.get $i64toi32_i32$1) + ) + ) + (drop + (block (result i32) + (local.set $i64toi32_i32$1 + (local.get $4$hi) + ) + (local.get $4) + ) + ) + (block + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.store + (local.get $i64toi32_i32$0) + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 1) + ) + ) + (i32.store offset=4 + (local.get $i64toi32_i32$0) + (local.get $i64toi32_i32$1) + ) + ) + (block + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.store + (local.get $i64toi32_i32$0) + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 2) + ) + ) + (i32.store offset=4 + (local.get $i64toi32_i32$0) + (local.get $i64toi32_i32$1) + ) + ) + (block + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.store align=2 + (local.get $i64toi32_i32$0) + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 3) + ) + ) + (i32.store offset=4 align=2 + (local.get $i64toi32_i32$0) + (local.get $i64toi32_i32$1) + ) + ) + (block + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.store align=1 + (local.get $i64toi32_i32$0) + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 4) + ) + ) + (i32.store offset=4 align=1 + (local.get $i64toi32_i32$0) + (local.get $i64toi32_i32$1) + ) + ) + (block + (local.set $i64toi32_i32$0 + (i32.const 0) + ) + (i32.store + (local.get $i64toi32_i32$0) + (block (result i32) + (local.set $i64toi32_i32$1 + (i32.const 0) + ) + (i32.const 5) + ) + ) + (i32.store offset=4 + (local.get $i64toi32_i32$0) + (local.get $i64toi32_i32$1) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) + (global $f (mut i32) (i32.const -1412567121)) + (global $g (mut i32) (global.get $f)) + (global $f$hi (mut i32) (i32.const 305419896)) + (global $g$hi (mut i32) (global.get $f$hi)) + (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) + (export "exp" (func $1)) + (export "unreach" (func $2)) + (func $call (param $0 i32) (param $0$hi i32) + (nop) + ) + (func $1 + (local $0 i32) + (local $0$hi i32) + (local $i64toi32_i32$0 i32) + (block + (local.set $0 + (block (result i32) + (local.set $i64toi32_i32$0 + (global.get $f$hi) + ) + (global.get $f) + ) + ) + (local.set $0$hi + (local.get $i64toi32_i32$0) + ) + ) + (call $call + (block (result i32) + (local.set $i64toi32_i32$0 + (local.get $0$hi) + ) + (local.get $0) + ) + (local.get $i64toi32_i32$0) + ) + (block + (global.set $f + (block (result i32) + (local.set $i64toi32_i32$0 + (i32.const 287454020) + ) + (i32.const 1432778632) + ) + ) + (global.set $f$hi + (local.get $i64toi32_i32$0) + ) + ) + ) + (func $2 + (local $0 i32) + (local $0$hi i32) + (local $1 i32) + (local $1$hi i32) + (local $i64toi32_i32$0 i32) + (block $label$1 + (unreachable) + (unreachable) + ) + (block + (local.set $1 + (block (result i32) + (local.set $i64toi32_i32$0 + (local.get $0$hi) + ) + (local.get $0) + ) + ) + (local.set $1$hi + (local.get $i64toi32_i32$0) + ) + ) + (block + (global.set $f + (block (result i32) + (local.set $i64toi32_i32$0 + (local.get $1$hi) + ) + (local.get $1) + ) + ) + (global.set $f$hi + (local.get $i64toi32_i32$0) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) + (global $f (mut i32) (i32.const -1412567121)) + (global $g (mut i32) (global.get $f)) + (global $f$hi (mut i32) (i32.const 305419896)) + (global $g$hi (mut i32) (global.get $f$hi)) + (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) + (export "exp" (func $1)) + (func $call (param $0 i32) (param $0$hi i32) + (nop) + ) + (func $1 + (local $0 i32) + (local $0$hi i32) + (local $i64toi32_i32$0 i32) + (block + (local.set $0 + (block (result i32) + (local.set $i64toi32_i32$0 + (global.get $f$hi) + ) + (global.get $f) + ) + ) + (local.set $0$hi + (local.get $i64toi32_i32$0) + ) + ) + (call $call + (block (result i32) + (local.set $i64toi32_i32$0 + (local.get $0$hi) + ) + (local.get $0) + ) + (local.get $i64toi32_i32$0) + ) + (block + (global.set $f + (block (result i32) + (local.set $i64toi32_i32$0 + (i32.const 287454020) + ) + (i32.const 1432778632) + ) + ) + (global.set $f$hi + (local.get $i64toi32_i32$0) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (table $0 37 funcref) + (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) + (func $0 + (unreachable) + (block + (unreachable) + (drop + (f64.const 1) + ) + (drop + (i32.const -32768) + ) + (drop + (i32.const 20) + ) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/flatten_i64-to-i32-lowering.wast binaryen-99/test/passes/flatten_i64-to-i32-lowering.wast --- binaryen-108/test/passes/flatten_i64-to-i32-lowering.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_i64-to-i32-lowering.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,77 @@ +(module + (memory 1 1) + (import "env" "func" (func $import (result i64))) + (func $defined (result i64) + (i64.add (i64.const 1) (i64.const 2)) + ) + (func $unreachable-select-i64 (result i64) + (select + (i64.const 1) + (unreachable) + (i32.const 2) + ) + ) + (func $unreachable-select-i64-b (result i64) + (select + (unreachable) + (i64.const 3) + (i32.const 4) + ) + ) + (func $unreachable-select-i64-c (result i64) + (select + (i64.const 5) + (i64.const 6) + (unreachable) + ) + ) + (func $mem + (drop (i64.load align=8 (i32.const 0))) + (drop (i64.load align=4 (i32.const 0))) + (drop (i64.load align=2 (i32.const 0))) + (drop (i64.load align=1 (i32.const 0))) + (drop (i64.load (i32.const 0))) + (i64.store align=8 (i32.const 0) (i64.const 1)) + (i64.store align=4 (i32.const 0) (i64.const 2)) + (i64.store align=2 (i32.const 0) (i64.const 3)) + (i64.store align=1 (i32.const 0) (i64.const 4)) + (i64.store (i32.const 0) (i64.const 5)) + ) +) +(module + (global $f (mut i64) (i64.const 0x12345678ABCDEFAF)) + (global $g (mut i64) (global.get $f)) + (func $call (param i64)) + (func "exp" + (call $call (global.get $f)) + (global.set $f (i64.const 0x1122334455667788)) + ) + (func "unreach" + (global.set $f + (block $label$1 (result i64) + (unreachable) + ) + ) + ) +) +(module + (global $f (mut i64) (i64.const 0x12345678ABCDEFAF)) + (global $g (mut i64) (global.get $f)) + (func $call (param i64)) + (func "exp" + (call $call (global.get $f)) + (global.set $f (i64.const 0x1122334455667788)) + ) +) +(module + (type $i64_f64_i32_=>_none (func (param i64 f64 i32))) + (table $0 37 funcref) + (func $0 + (call_indirect (type $i64_f64_i32_=>_none) + (unreachable) + (f64.const 1) + (i32.const -32768) + (i32.const 20) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_local-cse_all-features.txt binaryen-99/test/passes/flatten_local-cse_all-features.txt --- binaryen-108/test/passes/flatten_local-cse_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_local-cse_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,815 @@ +(module + (type $none_=>_none (func)) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $f64_f64_i32_=>_f32 (func (param f64 f64 i32) (result f32))) + (memory $0 100 100) + (func $basics + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local.set $2 + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (local.get $2) + ) + (local.set $3 + (local.get $2) + ) + (drop + (local.get $2) + ) + (if + (i32.const 0) + (nop) + ) + (local.set $4 + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (local.get $4) + ) + (local.set $5 + (local.get $x) + ) + (local.set $6 + (local.get $y) + ) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (drop + (local.get $7) + ) + (local.set $8 + (local.get $x) + ) + (local.set $9 + (local.get $y) + ) + (local.set $10 + (local.get $7) + ) + (drop + (local.get $7) + ) + (local.set $11 + (local.get $x) + ) + (local.set $12 + (local.get $y) + ) + (local.set $13 + (local.get $7) + ) + (drop + (local.get $7) + ) + (call $basics) + (local.set $14 + (local.get $x) + ) + (local.set $15 + (local.get $y) + ) + (local.set $16 + (local.get $7) + ) + (drop + (local.get $7) + ) + (local.set $x + (i32.const 100) + ) + (local.set $17 + (local.get $x) + ) + (local.set $18 + (local.get $y) + ) + (local.set $19 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (drop + (local.get $19) + ) + ) + (func $recursive1 + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local.set $2 + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + (local.set $3 + (i32.add + (i32.const 1) + (local.get $2) + ) + ) + (drop + (local.get $3) + ) + (local.set $4 + (local.get $2) + ) + (local.set $5 + (local.get $3) + ) + (drop + (local.get $3) + ) + (local.set $6 + (local.get $2) + ) + (drop + (local.get $2) + ) + ) + (func $recursive2 + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local.set $2 + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + (local.set $3 + (i32.add + (i32.const 1) + (local.get $2) + ) + ) + (drop + (local.get $3) + ) + (local.set $4 + (local.get $2) + ) + (drop + (local.get $2) + ) + (local.set $5 + (local.get $2) + ) + (local.set $6 + (local.get $3) + ) + (drop + (local.get $3) + ) + ) + (func $self + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $2 + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $4 + (i32.add + (local.get $2) + (local.get $2) + ) + ) + (drop + (local.get $4) + ) + (local.set $5 + (local.get $2) + ) + (drop + (local.get $2) + ) + ) + (func $loads + (local $0 i32) + (local $1 i32) + (local.set $0 + (i32.load + (i32.const 10) + ) + ) + (drop + (local.get $0) + ) + (local.set $1 + (i32.load + (i32.const 10) + ) + ) + (drop + (local.get $1) + ) + ) + (func $8 (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (block $label$0 + (local.set $4 + (local.get $var$1) + ) + (local.set $5 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (local.set $var$2 + (local.get $5) + ) + (local.set $6 + (local.get $var$2) + ) + (local.set $7 + (local.get $var$2) + ) + (local.set $8 + (i32.load + (local.get $var$2) + ) + ) + (local.set $var$2 + (i32.const 74) + ) + (local.set $9 + (local.get $var$2) + ) + (local.set $10 + (i32.xor + (local.get $var$2) + (i32.const -1) + ) + ) + (local.set $11 + (i32.and + (local.get $8) + (local.get $10) + ) + ) + (i32.store + (local.get $5) + (local.get $11) + ) + (local.set $12 + (local.get $var$1) + ) + (local.set $13 + (local.get $5) + ) + (local.set $var$1 + (local.get $5) + ) + (local.set $14 + (local.get $var$1) + ) + (local.set $15 + (local.get $var$1) + ) + (local.set $16 + (i32.load + (local.get $var$1) + ) + ) + (local.set $17 + (local.get $var$2) + ) + (local.set $18 + (i32.and + (local.get $var$2) + (i32.const 8) + ) + ) + (local.set $19 + (i32.or + (local.get $16) + (local.get $18) + ) + ) + (i32.store + (local.get $var$1) + (local.get $19) + ) + (local.set $20 + (i32.const 0) + ) + ) + (local.set $21 + (local.get $20) + ) + (return + (local.get $20) + ) + ) + (func $loop1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (block + (local.set $2 + (local.get $y) + ) + (local.set $x + (local.get $y) + ) + (local.set $3 + (local.get $x) + ) + (local.set $y + (local.get $x) + ) + (local.set $4 + (local.get $x) + ) + (local.set $x + (local.get $x) + ) + (local.set $5 + (local.get $x) + ) + (local.set $y + (local.get $x) + ) + (local.set $6 + (local.get $x) + ) + (return + (local.get $x) + ) + (unreachable) + ) + (local.set $8 + (local.get $7) + ) + (return + (local.get $7) + ) + ) + (func $loop2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $3 + (local.get $y) + ) + (local.set $x + (local.get $y) + ) + (local.set $4 + (local.get $z) + ) + (local.set $y + (local.get $z) + ) + (local.set $5 + (local.get $x) + ) + (local.set $z + (local.get $x) + ) + (local.set $6 + (local.get $y) + ) + (local.set $x + (local.get $y) + ) + (local.set $7 + (local.get $z) + ) + (local.set $y + (local.get $z) + ) + (local.set $8 + (local.get $x) + ) + (local.set $z + (local.get $x) + ) + (local.set $9 + (local.get $x) + ) + (return + (local.get $x) + ) + (unreachable) + ) + (local.set $11 + (local.get $10) + ) + (return + (local.get $10) + ) + ) + (func $loop3 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (local.set $3 + (local.get $y) + ) + (local.set $x + (local.get $y) + ) + (local.set $4 + (local.get $z) + ) + (local.set $y + (local.get $z) + ) + (local.set $5 + (local.get $y) + ) + (local.set $z + (local.get $y) + ) + (local.set $6 + (local.get $y) + ) + (local.set $y + (local.get $y) + ) + (local.set $7 + (local.get $y) + ) + (local.set $z + (local.get $y) + ) + (local.set $8 + (local.get $y) + ) + (return + (local.get $y) + ) + (unreachable) + ) + (local.set $10 + (local.get $9) + ) + (return + (local.get $9) + ) + ) + (func $handle-removing (param $var$0 f64) (param $var$1 f64) (param $var$2 i32) (result f32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 f32) + (local $7 f32) + (block + (local.set $var$2 + (i32.const 32767) + ) + (local.set $3 + (local.get $var$2) + ) + (local.set $var$2 + (i32.const 1024) + ) + (local.set $4 + (local.get $var$2) + ) + (local.set $5 + (select + (local.get $3) + (local.get $var$2) + (i32.const -2147483648) + ) + ) + (local.set $var$2 + (local.get $5) + ) + (local.set $6 + (f32.const 1) + ) + ) + (local.set $7 + (local.get $6) + ) + (return + (local.get $6) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i64_f32_i32_=>_none (func (param i64 f32 i32))) + (type $i32_f64_=>_i32 (func (param i32 f64) (result i32))) + (table $0 23 23 funcref) + (global $global$0 (mut i32) (i32.const 10)) + (export "func_1_invoker" (func $1)) + (export "func_6" (func $2)) + (func $0 (param $var$0 i64) (param $var$1 f32) (param $var$2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block $label$1 + (local.set $3 + (i32.const 128) + ) + (br_if $label$1 + (i32.const 0) + ) + (local.set $4 + (local.get $3) + ) + (local.set $3 + (i32.const 0) + ) + (br_if $label$1 + (local.get $4) + ) + (local.set $5 + (local.get $3) + ) + (drop + (local.get $3) + ) + (local.set $3 + (i32.const -14051) + ) + ) + (local.set $6 + (local.get $3) + ) + (if + (local.get $3) + (global.set $global$0 + (i32.const 0) + ) + ) + ) + (func $1 + (call $0 + (i64.const 1125899906842624) + (f32.const -nan:0x7fc91a) + (i32.const -46) + ) + ) + (func $2 (param $var$0 i32) (param $var$1 f64) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block + (block + (local.set $2 + (global.get $global$0) + ) + (if + (local.get $2) + (block + (unreachable) + (unreachable) + ) + ) + ) + (local.set $3 + (i32.const 0) + ) + ) + (local.set $4 + (local.get $3) + ) + (return + (local.get $3) + ) + ) +) +(module + (type $i32_=>_none (func (param i32))) + (import "env" "out" (func $out (param i32))) + (func $each-pass-must-clear (param $var$0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local.set $1 + (local.get $var$0) + ) + (local.set $2 + (i32.eqz + (local.get $var$0) + ) + ) + (call $out + (local.get $2) + ) + (local.set $3 + (local.get $var$0) + ) + (local.set $4 + (local.get $2) + ) + (call $out + (local.get $2) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $none_=>_i64 (func (result i64))) + (global $glob (mut i32) (i32.const 1)) + (func $i64-shifts (result i64) + (local $temp i64) + (local $1 i64) + (local $2 i64) + (local $3 i64) + (local $4 i64) + (local $5 i64) + (block + (local.set $1 + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (local.set $temp + (local.get $1) + ) + (local.set $temp + (i64.const 9999) + ) + (local.set $2 + (local.get $1) + ) + (local.set $temp + (local.get $1) + ) + (local.set $3 + (local.get $temp) + ) + (local.set $4 + (local.get $temp) + ) + ) + (local.set $5 + (local.get $temp) + ) + (return + (local.get $temp) + ) + ) + (func $global + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local.set $2 + (global.get $glob) + ) + (local.set $x + (local.get $2) + ) + (local.set $3 + (local.get $x) + ) + (local.set $y + (local.get $x) + ) + (local.set $4 + (local.get $x) + ) + (local.set $y + (local.get $x) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $none_=>_anyref (func (result anyref))) + (func $subtype-test (result anyref) + (local $0 funcref) + (local $1 funcref) + (local $2 anyref) + (local $3 anyref) + (block + (nop) + (loop $label$1 + (local.set $0 + (ref.null func) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (local.get $0) + ) + ) + (local.set $3 + (local.get $2) + ) + (return + (local.get $2) + ) + ) + (func $test + (local $0 anyref) + (local $1 funcref) + (local $2 funcref) + (block $label$1 + (local.set $0 + (ref.null func) + ) + (local.set $1 + (ref.null func) + ) + ) + (local.set $2 + (local.get $1) + ) + (drop + (local.get $1) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_local-cse_all-features.wast binaryen-99/test/passes/flatten_local-cse_all-features.wast --- binaryen-108/test/passes/flatten_local-cse_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_local-cse_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,316 @@ +(module + (memory 100 100) + (func $basics + (local $x i32) + (local $y i32) + (drop + (i32.add (i32.const 1) (i32.const 2)) + ) + (drop + (i32.add (i32.const 1) (i32.const 2)) + ) + (if (i32.const 0) (nop)) + (drop ;; we can't do this yet, non-linear + (i32.add (i32.const 1) (i32.const 2)) + ) + (drop + (i32.add (local.get $x) (local.get $y)) + ) + (drop + (i32.add (local.get $x) (local.get $y)) + ) + (drop + (i32.add (local.get $x) (local.get $y)) + ) + (call $basics) ;; side effects, but no matter for our locals + (drop + (i32.add (local.get $x) (local.get $y)) + ) + (local.set $x (i32.const 100)) + (drop ;; x was changed! + (i32.add (local.get $x) (local.get $y)) + ) + ) + (func $recursive1 + (local $x i32) + (local $y i32) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (func $recursive2 + (local $x i32) + (local $y i32) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + (drop + (i32.add + (i32.const 1) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + ) + (func $self + (local $x i32) + (local $y i32) + (drop + (i32.add + (i32.add + (i32.const 2) + (i32.const 3) + ) + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.const 2) + (i32.const 3) + ) + ) + ) + (func $loads + (drop + (i32.load (i32.const 10)) + ) + (drop + (i32.load (i32.const 10)) ;; implicit traps, sad + ) + ) + (func $8 (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (block $label$0 (result i32) + (i32.store + (local.tee $var$2 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (i32.and + (i32.load + (local.get $var$2) + ) + (i32.xor + (local.tee $var$2 + (i32.const 74) + ) + (i32.const -1) + ) + ) + ) + (i32.store + (local.tee $var$1 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $var$1) + ) + (i32.and + (local.get $var$2) + (i32.const 8) + ) + ) + ) + (i32.const 0) + ) + ) + (func $loop1 (param $x i32) (param $y i32) (result i32) + (local.set $x (local.get $y)) + (local.set $y (local.get $x)) + (local.set $x (local.get $y)) + (local.set $y (local.get $x)) + (return (local.get $y)) + ) + (func $loop2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local.set $x (local.get $y)) + (local.set $y (local.get $z)) + (local.set $z (local.get $x)) + (local.set $x (local.get $y)) + (local.set $y (local.get $z)) + (local.set $z (local.get $x)) + (return (local.get $x)) + ) + (func $loop3 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local.set $x (local.get $y)) + (local.set $y (local.get $z)) + (local.set $z (local.get $y)) + (local.set $y (local.get $z)) + (local.set $z (local.get $y)) + (return (local.get $y)) + ) + (func $handle-removing (param $var$0 f64) (param $var$1 f64) (param $var$2 i32) (result f32) + (local.set $var$2 + (select + (local.tee $var$2 + (i32.const 32767) + ) + (local.tee $var$2 + (i32.const 1024) + ) + (i32.const -2147483648) + ) + ) + (f32.const 1) + ) +) +;; a testcase that fails if we don't handle equivalent local canonicalization properly +(module + (type $0 (func)) + (type $1 (func (param i32 f64) (result i32))) + (type $2 (func (param i64 f32 i32))) + (global $global$0 (mut i32) (i32.const 10)) + (table 23 23 funcref) + (export "func_1_invoker" (func $1)) + (export "func_6" (func $2)) + (func $0 (; 0 ;) (type $2) (param $var$0 i64) (param $var$1 f32) (param $var$2 i32) + (if + (block $label$1 (result i32) + (drop + (br_if $label$1 + (i32.const 0) + (br_if $label$1 + (i32.const 128) + (i32.const 0) + ) + ) + ) + (i32.const -14051) + ) + (global.set $global$0 + (i32.const 0) + ) + ) + ) + (func $1 (; 1 ;) (type $0) + (call $0 + (i64.const 1125899906842624) + (f32.const -nan:0x7fc91a) + (i32.const -46) + ) + ) + (func $2 (; 2 ;) (type $1) (param $var$0 i32) (param $var$1 f64) (result i32) + (if + (global.get $global$0) + (unreachable) + ) + (i32.const 0) + ) +) +(module + (import "env" "out" (func $out (param i32))) + (func $each-pass-must-clear (param $var$0 i32) + (call $out + (i32.eqz + (local.get $var$0) + ) + ) + (call $out + (i32.eqz + (local.get $var$0) + ) + ) + ) +) +(module + (global $glob (mut i32) (i32.const 1)) + (func $i64-shifts (result i64) + (local $temp i64) + (local.set $temp + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (local.set $temp + (i64.const 9999) + ) + (local.set $temp + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (local.get $temp) + ) + (func $global + (local $x i32) + (local $y i32) + (local.set $x (global.get $glob)) + (local.set $y (global.get $glob)) + (local.set $y (global.get $glob)) + ) +) + +(module + ;; After --flatten, there will be a series of chain copies between multiple + ;; locals, but some of the locals will be funcref type and others anyref + ;; type. We cannot make locals of different types a common subexpression. + (func $subtype-test (result anyref) + (nop) + (loop $label$1 (result funcref) + (ref.null func) + ) + ) + + (func $test + (local $0 anyref) + (drop + (block $label$1 (result funcref) + (local.set $0 + (ref.null func) + ) + ;; After --flatten, this will be assigned to a local of funcref type. After + ;; --local-cse, even if we set (ref.null func) to local $0 above, this + ;; should not be replaced with $0, because it is of type anyref. + (ref.null func) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_local-cse_Os.txt binaryen-99/test/passes/flatten_local-cse_Os.txt --- binaryen-108/test/passes/flatten_local-cse_Os.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_local-cse_Os.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,27 @@ +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (export "div16_internal" (func $0)) + (func $0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (local.tee $0 + (i32.xor + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_local-cse_Os.wast binaryen-99/test/passes/flatten_local-cse_Os.wast --- binaryen-108/test/passes/flatten_local-cse_Os.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_local-cse_Os.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,39 @@ +(module + ;; testcase from AssemblyScript + (func "div16_internal" (param $0 i32) (param $1 i32) (result i32) + (i32.add + (i32.xor + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + (i32.xor + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_rereloop.txt binaryen-99/test/passes/flatten_rereloop.txt --- binaryen-108/test/passes/flatten_rereloop.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_rereloop.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1182 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_f32 (func (result f32))) + (type $i32_=>_f32 (func (param i32) (result f32))) + (type $none_=>_f64 (func (result f64))) + (memory $0 1) + (global $global (mut i32) (i32.const 0)) + (func $0 (result f64) + (local $0 f64) + (local $1 f64) + (local $2 i32) + (block + ) + (if + (i32.const 0) + (block + (unreachable) + ) + (block + (block + (local.set $0 + (f64.const -nan:0xfffffd63e4e5a) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + ) + ) + ) + (func $1 (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block + (block $block$6$break + (block + ) + (block $switch$1$leave + (block $switch$1$default + (block $switch$1$case$4 + (br_table $switch$1$case$4 $switch$1$case$4 $switch$1$default + (i32.const 0) + ) + ) + (block + (block + (unreachable) + ) + ) + ) + (block + (br $block$6$break) + ) + ) + ) + (block + (block + ) + (block $switch$6$leave + (block $switch$6$default + (block $switch$6$case$3 + (br_table $switch$6$case$3 $switch$6$default + (i32.const 1) + ) + ) + (block + (block + (unreachable) + ) + ) + ) + (block + (block + (block + (local.set $0 + (i32.const 2) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + ) + ) + ) + ) + ) + (unreachable) + ) + (func $skip-empty + (local $0 i32) + (block $block$2$break + (block + ) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + (func $skip-empty-2 + (local $0 i32) + (block $block$5$break + (block + ) + (block + (br $block$5$break) + ) + ) + (block + (block $block$4$break + (call $skip-empty) + (block + (br $block$4$break) + ) + ) + (block + (block $block$2$break + (call $skip-empty) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + ) + ) + (func $skip-empty-3 + (local $0 i32) + (block $block$5$break + (block + ) + (block + (br $block$5$break) + ) + ) + (block + (block $block$4$break + (call $skip-empty) + (block + (br $block$4$break) + ) + ) + (block + (block $block$2$break + (call $skip-empty) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + ) + ) + (func $skip-empty-4 (param $x i32) + (local $1 i32) + (local $2 i32) + (block $block$2$break + (local.set $1 + (local.get $x) + ) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + (func $skipping (param $0 i32) (result f32) + (local $1 f32) + (local $2 f32) + (local $3 f32) + (local $4 f32) + (local $5 i32) + (block + ) + (if + (i32.const 0) + (block + (unreachable) + ) + (block + (block + (local.set $1 + (f32.const 1) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $2) + ) + (local.set $4 + (local.get $3) + ) + (return + (local.get $4) + ) + ) + ) + ) + ) + (func $merging + (local $0 i32) + (block + (block + ) + (return) + ) + ) + (func $unswitch + (local $0 i32) + (block $block$2$break + (block + ) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + (func $skip-only-empty + (local $0 i32) + (block $block$3$break + (block + ) + (if + (i32.const 1) + (block + (global.set $global + (i32.const 0) + ) + (block + (br $block$3$break) + ) + ) + (br $block$3$break) + ) + ) + (block + (return) + ) + ) + (func $skip-only-one-branch-out (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (block + (block + ) + (block + ) + ) + (if + (i32.const 1) + (block + (unreachable) + ) + (block + (block + (local.set $0 + (i32.const 0) + ) + (local.set $1 + (local.get $0) + ) + (return + (local.get $1) + ) + ) + ) + ) + ) + (func $multipass-for-skips (result f32) + (local $0 f32) + (local $1 f32) + (local $2 f32) + (local $3 f32) + (local $4 i32) + (block $block$7$break + (block + ) + (if + (i32.const 0) + (block + (block + (local.set $0 + (f32.const 9223372036854775808) + ) + (block + (local.set $1 + (local.get $0) + ) + (local.set $2 + (local.get $1) + ) + ) + ) + (block + (br $block$7$break) + ) + ) + (block + (local.set $2 + (f32.const 65505) + ) + (block + (br $block$7$break) + ) + ) + ) + ) + (block + (block + (local.set $3 + (local.get $2) + ) + (return + (local.get $3) + ) + ) + ) + ) + (func $branch-merge-vs-replace + (local $0 i32) + (block + ) + (if + (i32.const 0) + (block + (unreachable) + ) + (block + (return) + ) + ) + ) + (func $unswitch-amount + (local $0 i32) + (block $block$2$break + (block + ) + (if + (i32.const -23) + (br $block$2$break) + (block + (block $block$6$break + (block + ) + (block $switch$4$leave + (block $switch$4$default + (block $switch$4$case$2 + (br_table $switch$4$case$2 $switch$4$default + (i32.const 44064) + ) + ) + (block + (br $block$2$break) + ) + ) + (block + (br $block$6$break) + ) + ) + ) + (block + (unreachable) + ) + ) + ) + ) + (block + (return) + ) + ) +) +(module + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (func $trivial + (local $0 i32) + (return) + ) + (func $trivial2 + (local $0 i32) + (block + (block + (call $trivial) + (call $trivial) + ) + (return) + ) + ) + (func $return-void + (local $0 i32) + (return) + ) + (func $return-val (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (return + (i32.const 1) + ) + ) + (func $ifs (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (block + (local.set $6 + (local.get $x) + ) + (local.set $1 + (local.get $6) + ) + (local.set $7 + (local.get $1) + ) + ) + (if + (local.get $7) + (block + (block + (local.set $8 + (local.get $x) + ) + (local.set $2 + (local.get $8) + ) + (local.set $9 + (local.get $2) + ) + ) + (if + (local.get $9) + (block + (return + (i32.const 2) + ) + ) + (block + (return + (i32.const 3) + ) + ) + ) + ) + (block + (block + (local.set $10 + (local.get $x) + ) + (local.set $3 + (local.get $10) + ) + (local.set $11 + (local.get $3) + ) + ) + (if + (local.get $11) + (block + (return + (i32.const 4) + ) + ) + (block + (return + (i32.const 5) + ) + ) + ) + ) + ) + ) + (func $loops (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block $block$21$break + (block + (local.set $4 + (local.get $x) + ) + (local.set $1 + (local.get $4) + ) + (local.set $5 + (local.get $1) + ) + ) + (if + (local.get $5) + (loop $shape$2$continue + (call $trivial) + (block + (br $shape$2$continue) + ) + ) + (br $block$21$break) + ) + ) + (block + (block $block$24$break + (loop $shape$4$continue + (block + (call $trivial) + (local.set $6 + (local.get $x) + ) + (local.set $2 + (local.get $6) + ) + (local.set $7 + (local.get $2) + ) + ) + (if + (local.get $7) + (br $shape$4$continue) + (br $block$24$break) + ) + ) + ) + (block + (block $block$2$break + (loop $shape$6$continue + (block + (call $trivial) + (local.set $8 + (local.get $x) + ) + (local.set $3 + (local.get $8) + ) + (local.set $9 + (local.get $3) + ) + ) + (if + (local.get $9) + (br $shape$6$continue) + (br $block$2$break) + ) + ) + ) + (block + (return) + ) + ) + ) + ) + (func $br-out (param $x i32) + (local $1 i32) + (block $block$2$break + (call $br-out + (i32.const 5) + ) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + (func $unreachable (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $block$4$break + (block + (local.set $3 + (local.get $x) + ) + (local.set $1 + (local.get $3) + ) + (local.set $4 + (local.get $1) + ) + ) + (if + (local.get $4) + (br $block$4$break) + (block + (block $block$2$break + (call $unreachable + (i32.const 5) + ) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + ) + ) + (block + (block + (local.set $5 + (local.get $x) + ) + (local.set $2 + (local.get $5) + ) + (local.set $6 + (local.get $2) + ) + ) + (if + (local.get $6) + (block + (block + (call $unreachable + (i32.const 1) + ) + (unreachable) + ) + ) + (block + (block + (call $unreachable + (i32.const 3) + ) + (return) + ) + ) + ) + ) + ) + (func $empty-blocks (param $x i32) + (local $1 i32) + (block $block$2$break + (block + ) + (block + (br $block$2$break) + ) + ) + (block + (return) + ) + ) + (func $before-and-after (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (block $block$4$break + (block + (block + (call $before-and-after + (i32.const 1) + ) + (call $before-and-after + (i32.const 2) + ) + ) + (block + (call $before-and-after + (i32.const 3) + ) + (call $before-and-after + (i32.const 4) + ) + (local.set $6 + (local.get $x) + ) + (local.set $1 + (local.get $6) + ) + (local.set $7 + (local.get $1) + ) + ) + ) + (if + (local.get $7) + (br $block$4$break) + (block + (call $before-and-after + (i32.const 5) + ) + (block + (br $block$4$break) + ) + ) + ) + ) + (block + (block $block$8$break + (block + (block + (call $before-and-after + (i32.const 6) + ) + (call $before-and-after + (i32.const 7) + ) + ) + (call $before-and-after + (i32.const 8) + ) + ) + (block + (br $block$8$break) + ) + ) + (block + (block $block$10$break + (loop $shape$4$continue + (block + (call $before-and-after + (i32.const 9) + ) + (local.set $8 + (local.get $x) + ) + (local.set $2 + (local.get $8) + ) + (local.set $9 + (local.get $2) + ) + ) + (if + (local.get $9) + (br $shape$4$continue) + (br $block$10$break) + ) + ) + ) + (block + (block $block$11$break + (block + (call $before-and-after + (i32.const 10) + ) + (block + (call $before-and-after + (i32.const 11) + ) + (local.set $10 + (local.get $x) + ) + (local.set $3 + (local.get $10) + ) + (local.set $11 + (local.get $3) + ) + ) + ) + (if + (local.get $11) + (block + (call $before-and-after + (i32.const 12) + ) + (block + (br $block$11$break) + ) + ) + (br $block$11$break) + ) + ) + (block + (block $block$15$break + (block + (call $before-and-after + (i32.const 13) + ) + (local.set $12 + (local.get $x) + ) + (local.set $4 + (local.get $12) + ) + (local.set $13 + (local.get $4) + ) + ) + (if + (local.get $13) + (block + (call $before-and-after + (i32.const 14) + ) + (block + (br $block$15$break) + ) + ) + (block + (call $before-and-after + (i32.const 15) + ) + (block + (br $block$15$break) + ) + ) + ) + ) + (block + (block $block$21$break + (block + (local.set $14 + (local.get $x) + ) + (local.set $5 + (local.get $14) + ) + (local.set $15 + (local.get $5) + ) + ) + (if + (local.get $15) + (block + (call $before-and-after + (i32.const 16) + ) + (block + (br $block$21$break) + ) + ) + (br $block$21$break) + ) + ) + (block + (block $block$28$break + (block + (block + (block + (call $before-and-after + (i32.const 17) + ) + (call $before-and-after + (i32.const 18) + ) + (call $before-and-after + (i32.const 19) + ) + ) + (call $before-and-after + (i32.const 20) + ) + ) + (block + (call $before-and-after + (i32.const 21) + ) + (call $before-and-after + (i32.const 22) + ) + ) + ) + (block + (br $block$28$break) + ) + ) + (block + (block $block$30$break + (block + (call $before-and-after + (i32.const 23) + ) + (call $before-and-after + (i32.const 24) + ) + ) + (block + (br $block$30$break) + ) + ) + (block + (block + (call $before-and-after + (i32.const 25) + ) + (return) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (func $switch (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $block$3$break + (block + (local.set $3 + (local.get $x) + ) + (local.set $1 + (local.get $3) + ) + (local.set $4 + (local.get $1) + ) + ) + (block + (br $block$3$break) + ) + ) + (block + (block $block$9$break + (block + (call $switch + (i32.const 1) + ) + (local.set $5 + (local.get $x) + ) + (local.set $2 + (local.get $5) + ) + (local.set $6 + (local.get $2) + ) + ) + (block $switch$3$leave + (block $switch$3$default + (block $switch$3$case$9 + (br_table $switch$3$case$9 $switch$3$case$9 $switch$3$case$9 $switch$3$default + (local.get $6) + ) + ) + (block + (br $block$9$break) + ) + ) + (block + (block + (call $switch + (i32.const 2) + ) + (block + (br $block$9$break) + ) + ) + ) + ) + ) + (block + (block + (call $switch + (i32.const 3) + ) + (return) + ) + ) + ) + ) + (func $no-return + (local $0 i32) + (block $block$6$break + (block + ) + (if + (i32.const 1) + (block + (drop + (i32.const 2) + ) + (block + (br $block$6$break) + ) + ) + (block + (drop + (i32.const 3) + ) + (block + (br $block$6$break) + ) + ) + ) + ) + (block + (return) + ) + ) + (func $if-br-wat (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $block$3$break + (block $block$4$break + (block + (call $if-br-wat + (i32.const 0) + ) + (local.set $3 + (local.get $x) + ) + (local.set $1 + (local.get $3) + ) + (local.set $4 + (local.get $1) + ) + ) + (if + (local.get $4) + (block + (call $if-br-wat + (i32.const 1) + ) + (block + (br $block$4$break) + ) + ) + (block + (block + (local.set $5 + (local.get $x) + ) + (local.set $2 + (local.get $5) + ) + (local.set $6 + (local.get $2) + ) + ) + (if + (local.get $6) + (br $block$3$break) + (br $block$4$break) + ) + ) + ) + ) + (block + (call $if-br-wat + (i32.const 2) + ) + (block + (br $block$3$break) + ) + ) + ) + (block + (block + (call $if-br-wat + (i32.const 3) + ) + (return) + ) + ) + ) + (func $switcher-to-nowhere (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block + (local.set $4 + (local.get $0) + ) + (local.set $1 + (local.get $4) + ) + (local.set $5 + (local.get $1) + ) + ) + (block $switch$1$leave + (block $switch$1$default + (block $switch$1$case$4 + (block $switch$1$case$5 + (br_table $switch$1$case$5 $switch$1$case$4 $switch$1$default + (local.get $5) + ) + ) + (block + (block + (return + (i32.const 1) + ) + ) + ) + ) + (block + (block + (return + (i32.const 2) + ) + ) + ) + ) + (block + (block + (return + (i32.const 3) + ) + ) + ) + ) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/flatten_rereloop.wast binaryen-99/test/passes/flatten_rereloop.wast --- binaryen-108/test/passes/flatten_rereloop.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_rereloop.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,783 @@ +(module + (memory 1) + (global $global (mut i32) (i32.const 0)) + (func $0 (result f64) + (if + (i32.const 0) + (loop $label$2 + (unreachable) + ) + ) + (f64.const -nan:0xfffffd63e4e5a) + ) + (func $1 (result i32) + (block $label$8 + (block $label$9 + (block $label$16 + (block $label$18 + (block $label$19 + (br_table $label$18 $label$16 $label$19 + (i32.const 0) + ) + ) + (br_table $label$9 $label$8 + (i32.const 1) + ) + ) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (i32.const 2) + ) + (func $skip-empty + (block $a1 + (block $a2 + (block $a3 + (block $a4 + (br $a4) + ) + (br $a3) + ) + (br $a2) + ) + (br $a1) + ) + ) + (func $skip-empty-2 + (block $a1 + (block $a2 + (block $a3 + (block $a4 + (br $a4) + ) + (call $skip-empty) + (br $a3) + ) + (call $skip-empty) + (br $a2) + ) + (br $a1) + ) + ) + (func $skip-empty-3 + (block $a1 + (block $a2 + (block $a3 + (block $a4 + (nop) + (br $a4) + (nop) + ) + (nop) + (call $skip-empty) + (nop) + (br $a3) + ) + (nop) + (call $skip-empty) + (nop) + (br $a2) + ) + (br $a1) + ) + ) + (func $skip-empty-4 (param $x i32) + (block $a1 + (block $a2 + (block $a3 + (block $a4 + (br_table $a1 $a2 $a3 $a4 $a1 $a2 $a3 $a4 (local.get $x)) + ) + (br $a3) + ) + (br $a2) + ) + (br $a1) + ) + ) + (func $skipping (param $0 i32) (result f32) + (if + (i32.const 0) + (unreachable) + ) ;; branches joining here lead to skip opportunities + (loop $label$2 (result f32) + (f32.const 1) + ) + ) + (func $merging + (if + (i32.const 0) + (return) + ;; no else, but the else ends up with a return too, and we can merge them + ) + ) + (func $unswitch + (block $label$1 + (br_table $label$1 $label$1 + (i32.const 0) + ) + ) + ) + (func $skip-only-empty + (if + (i32.const 1) + (global.set $global + (i32.const 0) + ) + ) + ) + (func $skip-only-one-branch-out (result i32) + (block $label$1 + (nop) + ) + (if + (i32.const 1) + (unreachable) ;; blocks a path through + ) + (i32.const 0) + ) + (func $multipass-for-skips (result f32) + (if (result f32) + (i32.const 0) + (block (result f32) + (block $label$2 + (br_if $label$2 + (i32.const 536870912) + ) + ) + (f32.const 9223372036854775808) + ) + (f32.const 65505) + ) + ) + (func $branch-merge-vs-replace + (if + (i32.const 0) + (unreachable) + ) + ) + (func $unswitch-amount + (block $label$1 + (if + (i32.const -23) + (nop) + (block + (block $label$4 + (br_table $label$1 $label$4 + (i32.const 44064) + ) + ) + (unreachable) + ) + ) + ) + ) +) +;; manual TODO: merge branches, all the parts +(module + (type $0 (func)) + (type $1 (func (result i32))) + (type $2 (func (param i32) (result i32))) + (type $3 (func (param i32))) + (func $trivial (; 0 ;) (type $0) + (nop) + ) + (func $trivial2 (; 1 ;) (type $0) + (block + (call $trivial) + (nop) + (call $trivial) + (nop) + ) + (nop) + ) + (func $return-void (; 2 ;) (type $0) + (return) + (unreachable) + ) + (func $return-val (; 3 ;) (type $1) (result i32) + (return + (i32.const 1) + ) + (unreachable) + ) + (func $ifs (; 4 ;) (type $2) (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (block + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (block + (block + (local.set $2 + (local.get $x) + ) + (if + (local.get $2) + (block + (return + (i32.const 2) + ) + (unreachable) + ) + (block + (return + (i32.const 3) + ) + (unreachable) + ) + ) + ) + (unreachable) + ) + ) + ) + (nop) + (block + (local.set $3 + (local.get $x) + ) + (if + (local.get $3) + (block + (return + (i32.const 4) + ) + (unreachable) + ) + ) + ) + (nop) + (return + (i32.const 5) + ) + (unreachable) + ) + (local.set $5 + (local.get $4) + ) + (return + (local.get $5) + ) + ) + (func $loops (; 5 ;) (type $3) (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (block + (block + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (block + (loop $top + (block + (call $trivial) + (nop) + (br $top) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (nop) + (loop $top2 + (block + (call $trivial) + (nop) + (local.set $2 + (local.get $x) + ) + (br_if $top2 + (local.get $2) + ) + (nop) + ) + (nop) + ) + (nop) + (loop $top3 + (block + (call $trivial) + (nop) + (block + (local.set $3 + (local.get $x) + ) + (if + (local.get $3) + (block + (br $top3) + (unreachable) + ) + ) + ) + (nop) + ) + (nop) + ) + (nop) + ) + (nop) + ) + (func $br-out (; 6 ;) (type $3) (param $x i32) + (block $out + (call $br-out + (i32.const 5) + ) + (nop) + (br $out) + (unreachable) + ) + (nop) + ) + (func $unreachable (; 7 ;) (type $3) (param $x i32) + (local $1 i32) + (local $2 i32) + (block + (block + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (block + (block + (local.set $2 + (local.get $x) + ) + (if + (local.get $2) + (block + (block $block + (call $unreachable + (i32.const 1) + ) + (nop) + (unreachable) + (unreachable) + (call $unreachable + (i32.const 2) + ) + (nop) + ) + (unreachable) + ) + (block + (block $block4 + (call $unreachable + (i32.const 3) + ) + (nop) + (return) + (unreachable) + (call $unreachable + (i32.const 4) + ) + (nop) + ) + (unreachable) + ) + ) + ) + (unreachable) + ) + ) + ) + (nop) + (block $out + (call $unreachable + (i32.const 5) + ) + (nop) + (br $out) + (unreachable) + (call $unreachable + (i32.const 6) + ) + (nop) + ) + (nop) + ) + (nop) + ) + (func $empty-blocks (; 8 ;) (type $3) (param $x i32) + (block + (block $block + ) + (nop) + (block $block5 + ) + (nop) + ) + (nop) + ) + (func $before-and-after (; 9 ;) (type $3) (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (call $before-and-after + (i32.const 1) + ) + (nop) + (block $block + (call $before-and-after + (i32.const 2) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 3) + ) + (nop) + (block $out + (call $before-and-after + (i32.const 4) + ) + (nop) + (local.set $1 + (local.get $x) + ) + (br_if $out + (local.get $1) + ) + (nop) + (call $before-and-after + (i32.const 5) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 6) + ) + (nop) + (loop $loop-in + (nop) + ) + (nop) + (call $before-and-after + (i32.const 7) + ) + (nop) + (loop $top + (nop) + ) + (nop) + (call $before-and-after + (i32.const 8) + ) + (nop) + (loop $top2 + (block + (call $before-and-after + (i32.const 9) + ) + (nop) + (local.set $2 + (local.get $x) + ) + (br_if $top2 + (local.get $2) + ) + (nop) + (call $before-and-after + (i32.const 10) + ) + (nop) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 11) + ) + (nop) + (block + (local.set $3 + (local.get $x) + ) + (if + (local.get $3) + (block + (call $before-and-after + (i32.const 12) + ) + (nop) + ) + ) + ) + (nop) + (call $before-and-after + (i32.const 13) + ) + (nop) + (block + (local.set $4 + (local.get $x) + ) + (if + (local.get $4) + (block + (call $before-and-after + (i32.const 14) + ) + (nop) + ) + (block + (call $before-and-after + (i32.const 15) + ) + (nop) + ) + ) + ) + (nop) + (block + (local.set $5 + (local.get $x) + ) + (if + (local.get $5) + (block + (block $block8 + (call $before-and-after + (i32.const 16) + ) + (nop) + ) + (nop) + ) + ) + ) + (nop) + (call $before-and-after + (i32.const 17) + ) + (nop) + (block $block9 + (call $before-and-after + (i32.const 18) + ) + (nop) + (block $block10 + (call $before-and-after + (i32.const 19) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 20) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 21) + ) + (nop) + (block $block11 + (block $block12 + (call $before-and-after + (i32.const 22) + ) + (nop) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 23) + ) + (nop) + (block $no1 + (block $no2 + (call $before-and-after + (i32.const 24) + ) + (nop) + ) + (nop) + ) + (nop) + (call $before-and-after + (i32.const 25) + ) + (nop) + ) + (nop) + ) + (func $switch (; 10 ;) (type $3) (param $x i32) + (local $1 i32) + (local $2 i32) + (block $out + (block $a + (local.set $1 + (local.get $x) + ) + (br_table $a $a + (local.get $1) + ) + (unreachable) + ) + (nop) + (call $switch + (i32.const 1) + ) + (nop) + (block $b + (block $c + (local.set $2 + (local.get $x) + ) + (br_table $b $b $b $c + (local.get $2) + ) + (unreachable) + ) + (nop) + (call $switch + (i32.const 2) + ) + (nop) + ) + (nop) + (call $switch + (i32.const 3) + ) + (nop) + ) + (nop) + ) + (func $no-return (; 11 ;) (type $0) + (if + (i32.const 1) + (block + (drop + (i32.const 2) + ) + (nop) + ) + (block + (drop + (i32.const 3) + ) + (nop) + ) + ) + (nop) + ) + (func $if-br-wat (; 12 ;) (type $3) (param $x i32) + (local $1 i32) + (local $2 i32) + (block + (call $if-br-wat + (i32.const 0) + ) + (nop) + (block $label$2 + (block + (local.set $1 + (local.get $x) + ) + (if + (local.get $1) + (block + (call $if-br-wat + (i32.const 1) + ) + (nop) + ) + (block + (block + (local.set $2 + (local.get $x) + ) + (if + (local.get $2) + (block + (br $label$2) + (unreachable) + ) + ) + ) + (nop) + ) + ) + ) + (nop) + (call $if-br-wat + (i32.const 2) + ) + (nop) + ) + (nop) + (call $if-br-wat + (i32.const 3) + ) + (nop) + ) + (nop) + ) + (func $switcher-to-nowhere (; 13 ;) (type $2) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (block + (block $switch + (block $switch-case0 + (block $switch-case + (local.set $1 + (local.get $0) + ) + (br_table $switch-case $switch-case0 $switch + (local.get $1) + ) + (unreachable) + ) + (nop) + (return + (i32.const 1) + ) + (unreachable) + ) + (nop) + (return + (i32.const 2) + ) + (unreachable) + ) + (nop) + (return + (i32.const 3) + ) + (unreachable) + ) + (local.set $3 + (local.get $2) + ) + (return + (local.get $3) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_simplify-locals-nonesting_dfo_O3.txt binaryen-99/test/passes/flatten_simplify-locals-nonesting_dfo_O3.txt --- binaryen-108/test/passes/flatten_simplify-locals-nonesting_dfo_O3.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_simplify-locals-nonesting_dfo_O3.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,41 @@ +(module + (type $none_=>_none (func)) + (type $i64_=>_none (func (param i64))) + (type $f64_=>_i32 (func (param f64) (result i32))) + (type $i32_f64_f64_=>_i32 (func (param i32 f64 f64) (result i32))) + (type $none_=>_f64 (func (result f64))) + (export "if-select" (func $0)) + (export "unreachable-body-update-zext" (func $1)) + (export "ssa-const" (func $2)) + (export "if-nothing" (func $3)) + (export "only-dfo" (func $4)) + (func $0 (; has Stack IR ;) + (nop) + ) + (func $1 (; has Stack IR ;) (result f64) + (unreachable) + ) + (func $2 (; has Stack IR ;) (param $0 i32) (param $1 f64) (param $2 f64) (result i32) + (unreachable) + ) + (func $3 (; has Stack IR ;) (param $0 i64) + (unreachable) + ) + (func $4 (; has Stack IR ;) (param $0 f64) (result i32) + (local $1 i32) + (loop $label$1 + (if + (i32.eqz + (local.get $1) + ) + (block + (local.set $1 + (i32.const -2147483648) + ) + (br $label$1) + ) + ) + ) + (i32.const -2766) + ) +) diff -Nru binaryen-108/test/passes/flatten_simplify-locals-nonesting_dfo_O3.wast binaryen-99/test/passes/flatten_simplify-locals-nonesting_dfo_O3.wast --- binaryen-108/test/passes/flatten_simplify-locals-nonesting_dfo_O3.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_simplify-locals-nonesting_dfo_O3.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,113 @@ +(module + (memory 1) + (func "if-select" + (local $var$0 i32) + (nop) + (drop + (if (result i32) + (select + (i32.const 65473) + (i32.const 1) + (local.get $var$0) + ) + (i32.const -2405046) + (i32.const 1) + ) + ) + ) + (func "unreachable-body-update-zext" (result f64) + (if + (i32.eqz + (i32.const 0) + ) + (unreachable) + ) + (f64.const -9223372036854775808) + ) + (func "ssa-const" (param $var$0 i32) (param $var$1 f64) (param $var$2 f64) (result i32) + (block $label$1 (result i32) + (block $label$2 + (if + (i32.const 1) + (block + (drop + (loop $label$5 (result i64) + (if (result i64) + (i32.const 0) + (i64.load offset=22 + (i32.and + (br_if $label$1 + (i32.const 0) + (i32.const 0) + ) + (i32.const 15) + ) + (i64.const 1) + ) + (i64.const 1) + ) + ) + ) + ) + ) + (unreachable) + ) + ) + ) + (func "if-nothing" (param $var$0 i64) + (local $var$1 i32) + (local $var$2 i32) + (block $label$1 + (loop $label$2 + (block $label$3 + (block $label$4 + (br_if $label$3 + (i32.eqz + (if (result i32) + (i32.const 0) + (i32.const 0) + (local.get $var$2) + ) + ) + ) + (unreachable) + ) + (unreachable) + ) + ) + (unreachable) + ) + ) + (func "only-dfo" (param $var$0 f64) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (local $var$4 i32) + (loop $label$1 + (local.set $var$3 + (local.tee $var$1 + (local.tee $var$2 + (local.get $var$1) + ) + ) + ) + (if + (i32.eqz + (local.get $var$4) + ) + (block + (local.set $var$4 + (select + (local.get $var$3) + (i32.const -2147483648) + (local.get $var$2) + ) + ) + (br $label$1) + ) + ) + ) + (i32.const -2766) + ) +) + diff -Nru binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.txt binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.txt --- binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,4877 @@ + +; function: figure-1a + +; start LHS (in figure-1a) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +infer %2 + + +; start LHS (in figure-1a) +%0:i64 = var +%1:i64 = var +%2 = ne %0, %1 +infer %2 + + +; start LHS (in figure-1a) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +%3:i32 = zext %2 +%4:i64 = var +%5 = ne %0, %4 +%6:i32 = zext %5 +%7 = and %3, %6 +infer %7 + + +; function: figure-1b + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = slt %0, %1 +infer %2 + + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +%3:i64 = var +%4 = slt %1, %3 +pc %4 1:i1 +infer %2 + + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = ne %0, %1 +%3:i64 = var +%4 = slt %3, %1 +pc %4 1:i1 +infer %2 + + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +%3:i32 = zext %2 +%4:i64 = var +%5 = ne %0, %4 +%6:i32 = zext %5 +%7 = and %3, %6 +%8 = slt %1, %4 +pc %8 1:i1 +infer %7 + + +; function: figure-3-if + +; start LHS (in figure-3-if) +%0:i32 = var +%1 = and %0, 1:i32 +infer %1 + + +; start LHS (in figure-3-if) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = and %0, 1:i32 +%3 = ne %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in figure-3-if) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = and %0, 1:i32 +%3 = eq %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in figure-3-if) +%0 = block 2 +%1:i32 = var +%2 = add %1, 1:i32 +%3 = add %1, 2:i32 +%4 = phi %0, %2, %3 +%5 = and %4, 1:i32 +%6 = and %1, 1:i32 +%7 = ne %6, 0:i32 +blockpc %0 0 %7 1:i1 +%8 = eq %6, 0:i32 +blockpc %0 1 %8 1:i1 +infer %5 + + +; function: send-i32 + +; function: flips + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +infer %0 + + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +%1:i32 = zext %0 +%2 = ule 0:i32, %1 +infer %2 + + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +%1:i32 = zext %0 +%2 = ule 0:i32, %1 +%3:i32 = zext %2 +%4 = slt 0:i32, %3 +infer %4 + + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +%1:i32 = zext %0 +%2 = ule 0:i32, %1 +%3:i32 = zext %2 +%4 = slt 0:i32, %3 +%5:i32 = zext %4 +%6 = ult 0:i32, %5 +infer %6 + + +; start LHS (in flips) +%0 = sle 0:i64, 0:i64 +infer %0 + + +; start LHS (in flips) +%0 = ule 0:i64, 0:i64 +infer %0 + + +; start LHS (in flips) +%0 = slt 0:i64, 0:i64 +infer %0 + + +; start LHS (in flips) +%0 = ult 0:i64, 0:i64 +infer %0 + + +; function: various-conditions-1 + +; start LHS (in various-conditions-1) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = ne %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; function: various-conditions-2 + +; start LHS (in various-conditions-2) +%0:i32 = var +%1 = slt %0, 0:i32 +infer %1 + + +; start LHS (in various-conditions-2) +%0:i32 = var +%1 = sub %0, 2:i32 +%2 = slt %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; function: various-conditions-3 + +; start LHS (in various-conditions-3) +%0:i32 = var +%1 = sub %0, 4:i32 +%2:i32 = var +%3 = ne %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; function: various-conditions-4 + +; function: unaries + +; start LHS (in unaries) +%0:i32 = var +%1 = eq %0, 0:i32 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = cttz %0 +%2:i32 = var +%3 = eq %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = ctlz %0 +%2 = eq %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = ctpop %0 +%2:i32 = var +%3 = eq %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = ctlz %0 +%2:i32 = var +%3 = ctpop %2 +%4 = sub %1, %3 +%5 = eq %0, 0:i32 +pc %5 1:i1 +infer %4 + + +; start LHS (in unaries) +%0:i32 = var +%1 = cttz %0 +%2:i32 = var +%3 = ctlz %2 +%4 = ctpop %0 +%5 = sub %3, %4 +%6 = add %1, %5 +%7 = eq %2, 0:i32 +pc %7 1:i1 +infer %6 + + +; function: unary-condition + +; start LHS (in unary-condition) +%0:i32 = var +%1 = ult 1:i32, %0 +infer %1 + + +; start LHS (in unary-condition) +%0:i32 = var +%1 = ult 1:i32, %0 +%2:i32 = zext %1 +%3 = cttz %2 +infer %3 + + +; start LHS (in unary-condition) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = ult 1:i32, %0 +%3:i32 = zext %2 +%4 = cttz %3 +%5 = ne %4, 0:i32 +pc %5 1:i1 +infer %1 + + +; function: unary-condition-2 + +; start LHS (in unary-condition-2) +%0:i32 = var +%1 = ult 1:i32, %0 +infer %1 + + +; start LHS (in unary-condition-2) +%0:i32 = var +%1 = ult 1:i32, %0 +%2:i32 = zext %1 +%3 = eq %2, 0:i32 +infer %3 + + +; start LHS (in unary-condition-2) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = ult 1:i32, %0 +%3:i32 = zext %2 +%4 = eq %3, 0:i32 +pc %4 1:i1 +infer %1 + + +; function: if-else-cond + +; start LHS (in if-else-cond) +%0:i32 = var +%1 = slt %0, 1:i32 +infer %1 + + +; start LHS (in if-else-cond) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = slt %0, 1:i32 +pc %2 1:i1 +infer %1 + + +; start LHS (in if-else-cond) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = slt %0, 1:i32 +%3:i32 = zext %2 +%4 = eq %3, 0:i32 +pc %4 1:i1 +infer %1 + + +; start LHS (in if-else-cond) +%0 = block 2 +%1:i32 = var +%2 = add %1, 1:i32 +%3 = add %1, 2:i32 +%4 = phi %0, %2, %3 +%5 = and %4, 1:i32 +%6 = slt %1, 1:i32 +blockpc %0 0 %6 1:i1 +%7:i32 = zext %6 +%8 = eq %7, 0:i32 +blockpc %0 1 %8 1:i1 +infer %5 + + +; function: trivial-ret + +; start LHS (in trivial-ret) +%0 = add 0:i32, 1:i32 +infer %0 + + +; function: trivial-const + +; function: trivial-const-block + +; function: bad-phi-value + +; function: bad-phi-value-2 + +; function: select + +; start LHS (in select) +%0 = ne 3:i32, 0:i32 +infer %0 + + +; start LHS (in select) +%0 = ne 3:i32, 0:i32 +%1 = select %0, 1:i32, 2:i32 +infer %1 + + +; function: select-2 + +; start LHS (in select-2) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add 2:i32, %0 +infer %1 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add 2:i32, %0 +%2 = ne %1, 0:i32 +infer %2 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add 2:i32, %0 +%2 = ne %1, 0:i32 +%3:i32 = var +%4 = add %3, %0 +%5 = add %3, 1:i32 +%6 = select %2, %4, %5 +infer %6 + + +; function: block-phi-1 + +; start LHS (in block-phi-1) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in block-phi-1) +%0:i32 = var +%1 = add %0, 1:i32 (hasExternalUses) +%2 = add %1, 2:i32 +infer %2 + + +; start LHS (in block-phi-1) +%0 = block 2 +%1:i32 = var +%2 = add %1, 1:i32 +%3 = add %2, 2:i32 +%4 = phi %0, %2, %3 +%5 = add %4, 3:i32 +infer %5 + + +; function: block-phi-2 + +; start LHS (in block-phi-2) +%0 = block 2 +%1 = phi %0, 1:i32, 2:i32 +%2 = add %1, 3:i32 +infer %2 + + +; function: zero_init-phi-bad_type + +; function: phi-bad-type + +; function: phi-one-side-i1 + +; start LHS (in phi-one-side-i1) +%0:i32 = var +%1:i32 = var +%2 = sle %0, %1 +infer %2 + + +; start LHS (in phi-one-side-i1) +%0:i32 = var +%1:i32 = var +%2 = eq %0, %1 +%3 = sle %0, %1 +pc %3 1:i1 +infer %2 + + +; start LHS (in phi-one-side-i1) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +%3 = sle %0, %1 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +pc %5 1:i1 +infer %2 + + +; function: call + +; start LHS (in call) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; start LHS (in call) +%0:i32 = var +%1 = add 10:i32, %0 +infer %1 + + +; start LHS (in call) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +%3:i32 = var +%4 = add 10:i32, %3 +%5 = mul %2, %4 +infer %5 + + +; function: in-unreachable-1 + +; function: in-unreachable-2 + +; function: in-unreachable-3 + +; function: in-unreachable-4 + +; function: in-unreachable-br_if + +; function: in-unreachable-big + +; function: in-unreachable-operations + +; function: merge-with-one-less + +; function: deep + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +infer %1 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +infer %2 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +infer %3 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +infer %4 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +infer %5 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +infer %6 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +infer %7 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +infer %8 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; function: two-pcs + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = slt %0, %1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1 = eq %0, 0:i64 +%2:i64 = var +%3 = slt %0, %2 +pc %3 1:i1 +infer %1 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = add %0, %1 +%3 = eq %0, 0:i64 +%4 = slt %0, %1 +pc %3 1:i1 +pc %4 1:i1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = sub %0, %1 +%3 = eq %0, 0:i64 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +%6 = slt %0, %1 +pc %5 1:i1 +pc %6 1:i1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1 = eq %0, 0:i64 +%2:i64 = var +%3 = slt %2, %0 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +pc %5 1:i1 +infer %1 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = mul %0, %1 +%3 = eq %1, 0:i64 +%4 = slt %0, %1 +%5:i32 = zext %4 +%6 = eq %5, 0:i32 +pc %3 1:i1 +pc %6 1:i1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = sdiv %0, %1 +%3 = eq %1, 0:i64 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +%6 = slt %0, %1 +%7:i32 = zext %6 +%8 = eq %7, 0:i32 +pc %5 1:i1 +pc %8 1:i1 +infer %2 + + +; function: loop-1 + +; start LHS (in loop-1) +%0 = add 1:i32, 2:i32 +infer %0 + + +; function: loop-2 + +; start LHS (in loop-2) +%0 = add 1:i32, 3:i32 +infer %0 + + +; start LHS (in loop-2) +%0 = add 2:i32, 4:i32 +infer %0 + + +; start LHS (in loop-2) +%0 = add 1:i32, 3:i32 +%1 = add 2:i32, 4:i32 +%2 = add %0, %1 +infer %2 + + +; function: loop-3 + +; start LHS (in loop-3) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-3) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-3) +%0:i32 = var +%1 = add %0, 3:i32 +%2:i32 = var +%3 = add %2, 4:i32 (hasExternalUses) +%4 = add %1, %3 +infer %4 + + +; function: loop-4 + +; start LHS (in loop-4) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-4) +%0:i32 = var +%1 = add %0, 3:i32 +%2 = add %1, 2:i32 +infer %2 + + +; function: loop-5 + +; start LHS (in loop-5) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-5) +%0:i32 = var +%1 = add %0, 3:i32 +%2 = add %1, 2:i32 +infer %2 + + +; function: loop-6 + +; start LHS (in loop-6) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-6) +%0:i32 = var +%1 = add %0, 3:i32 +%2 = add %1, 2:i32 +infer %2 + + +; function: loop-7 + +; start LHS (in loop-7) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-7) +%0:i32 = var +%1 = add %0, 3:i32 +%2 = add %1, 5:i32 +infer %2 + + +; function: loop-8 + +; start LHS (in loop-8) +%0 = add 1:i32, 4:i32 +infer %0 + + +; start LHS (in loop-8) +%0:i32 = var +%1 = sub 1:i32, %0 +infer %1 + + +; start LHS (in loop-8) +%0 = add 1:i32, 4:i32 +%1:i32 = var +%2 = sub 1:i32, %1 +%3 = mul %0, %2 +infer %3 + + +; function: loop-9 + +; start LHS (in loop-9) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; function: loop-10 + +; start LHS (in loop-10) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; function: loop-multicond-1 + +; start LHS (in loop-multicond-1) +%0 = ne 6:i32, 0:i32 +infer %0 + + +; start LHS (in loop-multicond-1) +%0 = ne 6:i32, 0:i32 +%1 = select %0, 4:i32, 5:i32 +infer %1 + + +; function: loop-multicond-2 + +; start LHS (in loop-multicond-2) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-multicond-2) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; start LHS (in loop-multicond-2) +%0 = add 3:i32, 6:i32 +infer %0 + + +; start LHS (in loop-multicond-2) +%0 = add 3:i32, 6:i32 +%1 = ne %0, 0:i32 +infer %1 + + +; start LHS (in loop-multicond-2) +%0 = add 3:i32, 6:i32 +%1 = ne %0, 0:i32 +%2:i32 = var +%3 = add %2, 4:i32 +%4:i32 = var +%5 = add %4, 5:i32 +%6 = select %1, %3, %5 +infer %6 + + +; function: loop-block-1 + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = add %0, 6:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = ne %0, 0:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = ne %0, 0:i32 +%2:i32 = var +%3 = add %2, 4:i32 +%4 = block 2 +%5:i32 = var +%6 = add %5, 5:i32 +%7 = phi %4, %5, %6 +%8 = select %1, %3, %7 +infer %8 + + +; function: loop-block-2 + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = add %0, 6:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = ne %0, 0:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = ne %0, 0:i32 +%2:i32 = var +%3 = add %2, 4:i32 +%4 = block 2 +%5:i32 = var +%6 = add %5, 5:i32 +%7 = phi %4, %5, %6 +%8 = select %1, %3, %7 +infer %8 + + +; function: bad-phi-type + +; function: loop-unreachable + +; function: phi-value-turns-bad + +; start LHS (in phi-value-turns-bad) +%0:i32 = var +%1 = ctlz %0 +%2 = eq %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; function: multi-use + +; start LHS (in multi-use) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in multi-use) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = add %1, %1 +infer %2 + + +; function: multi-use-2 + +; start LHS (in multi-use-2) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in multi-use-2) +%0:i32 = var +%1 = add %0, 1:i32 (hasExternalUses) +%2 = mul %1, 2:i32 +infer %2 + + +; start LHS (in multi-use-2) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = mul %1, 2:i32 +%3 = sub %2, %1 +infer %3 + + +; function: many-single-uses-with-param + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = mul 10:i32, %0 +infer %1 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = cttz %0 +infer %1 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = cttz %0 +%2 = sub %1, 20:i32 +infer %2 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = mul 10:i32, %0 +%2 = cttz %0 +%3 = sub %2, 20:i32 +%4 = add %1, %3 +infer %4 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = mul 10:i32, %0 +%2 = cttz %0 +%3 = sub %2, 20:i32 +%4 = add %1, %3 +%5 = eq %4, 0:i32 +infer %5 + + +; function: 56 + +; start LHS (in 56) +%0:i32 = var +%1 = add %0, -7:i32 +infer %1 + + +; start LHS (in 56) +%0:i32 = var +%1 = add %0, -7:i32 (hasExternalUses) +%2 = eq %1, 0:i32 +%3 = ne %1, 0:i32 +pc %3 1:i1 +infer %2 + + +; start LHS (in 56) +%0:i32 = var +%1:i32 = var +%2 = add %1, -7:i32 (hasExternalUses) +%3 = ne %0, %2 +%4 = ne %2, 0:i32 +pc %4 1:i1 +infer %3 + + +; function: multiple-uses-to-non-expression + +; start LHS (in multiple-uses-to-non-expression) +%0:i32 = var +%1 = add %0, 10:i32 +infer %1 + + +; start LHS (in multiple-uses-to-non-expression) +%0:i32 = var +%1 = add %0, 10:i32 (hasExternalUses) +%2 = add %1, 20:i32 +infer %2 + + +; function: nested-phi-forwarding + +; start LHS (in nested-phi-forwarding) +%0 = block 2 +%1:i32 = var +%2 = block 2 +%3 = block 2 +%4 = phi %3, %1, 1:i32 +%5 = phi %2, %1, %4 +%6 = phi %0, %1, %5 +%7 = or 1:i32, %6 +infer %7 + + +; function: zext-numGets + +; start LHS (in zext-numGets) +%0:i32 = var +%1 = eq %0, 0:i32 +infer %1 + + +; start LHS (in zext-numGets) +%0 = block 2 +%1:i32 = var +%2 = eq %1, 0:i32 +%3:i32 = zext %2 +%4 = phi %0, 1:i32, %3 +%5 = cttz %4 +infer %5 + + +; function: zext-numGets-hasAnotherUse + +; start LHS (in zext-numGets-hasAnotherUse) +%0:i32 = var +%1 = eq %0, 0:i32 +infer %1 + + +; start LHS (in zext-numGets-hasAnotherUse) +%0 = block 2 +%1:i32 = var +%2 = eq %1, 0:i32 +%3:i32 = zext %2 +%4 = phi %0, 1:i32, %3 +%5 = cttz %4 +infer %5 + + +; function: flipped-needs-right-origin + +; start LHS (in flipped-needs-right-origin) +%0 = block 2 +%1 = phi %0, 0:i32, 2:i32 +%2 = add %1, 4:i32 +infer %2 + + +; start LHS (in flipped-needs-right-origin) +%0 = block 2 +%1 = phi %0, 0:i32, 2:i32 +%2 = add %1, 4:i32 +%3 = slt %2, 3:i32 +infer %3 + + +; function: non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN + +; start LHS (in non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN) +%0:i32 = var +%1 = ult 1:i32, %0 +infer %1 + + +; start LHS (in non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN) +%0:i32 = var +%1 = ult 1:i32, %0 (hasExternalUses) +%2:i32 = zext %1 +%3 = sub 4:i32, %2 +infer %3 + + +; function: loop-of-set-connections + +; start LHS (in loop-of-set-connections) +%0 = add 0:i32, 1:i32 +%1 = ne 0:i32, 0:i32 +pc %1 1:i1 +infer %0 + + +; function: conditions-in-conditions + +; start LHS (in conditions-in-conditions) +%0 = sub 0:i32, 1:i32 +%1 = ne 0:i32, 0:i32 +pc %1 1:i1 +infer %0 + + +; start LHS (in conditions-in-conditions) +%0 = block 2 +%1 = block 2 +%2 = phi %1, 0:i32, 1:i32 +%3 = phi %0, %2, 1:i32 +%4 = add %3, 16:i32 +%5 = ne 0:i32, 0:i32 +blockpc %1 0 %5 1:i1 +%6 = eq 0:i32, 0:i32 +blockpc %1 1 %6 1:i1 +%7 = sub 0:i32, 1:i32 +%8 = phi %1, 1:i32, %7 +%9 = ne %8, 0:i32 +blockpc %0 0 %9 1:i1 +%10 = eq %8, 0:i32 +blockpc %0 1 %10 1:i1 +infer %4 + +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_f64 (func (result f64))) + (type $none_=>_none (func)) + (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $i64_i64_i32_f32_=>_none (func (param i64 i64 i32 f32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) + (type $i64_i64_i64_=>_i64 (func (param i64 i64 i64) (result i64))) + (memory $0 (shared 1 1)) + (export "replaced-print-internal" (func $56)) + (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (local $6 i64) + (local $7 i64) + (local $8 i32) + (local $9 i64) + (local $10 i64) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (local.set $12 + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $13 + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $15 + (i32.and + (local.get $12) + (local.get $13) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (local $6 i64) + (local $7 i64) + (local $8 i32) + (local $9 i64) + (local $10 i64) + (local $11 i32) + (local $12 i64) + (local $13 i64) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (block + (nop) + (nop) + (local.set $8 + (i64.lt_s + (local.get $x) + (local.get $y) + ) + ) + (if + (local.get $8) + (block + (block $block + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (local.set $15 + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $16 + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $18 + (i32.and + (local.get $15) + (local.get $16) + ) + ) + (return + (local.get $18) + ) + (unreachable) + ) + (unreachable) + ) + (block + (unreachable) + (unreachable) + ) + ) + ) + (unreachable) + ) + (func $figure-3-if (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block + (nop) + (local.set $2 + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (if + (local.get $2) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (nop) + (local.set $8 + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $send-i32 (param $0 i32) + (nop) + ) + (func $flips + (local $x i32) + (local $y i32) + (local $z i64) + (local $w i64) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i64) + (local $17 i64) + (local $18 i32) + (local $19 i64) + (local $20 i64) + (local $21 i32) + (local $22 i64) + (local $23 i64) + (local $24 i32) + (local $25 i64) + (local $26 i64) + (local $27 i32) + (nop) + (nop) + (nop) + (local.set $x + (i32.ge_s + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (nop) + (local.set $x + (i32.ge_u + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (nop) + (local.set $x + (i32.gt_s + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (nop) + (local.set $x + (i32.gt_u + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $18 + (i64.ge_s + (local.get $z) + (local.get $w) + ) + ) + (call $send-i32 + (local.get $18) + ) + (nop) + (nop) + (local.set $21 + (i64.ge_u + (local.get $z) + (local.get $w) + ) + ) + (call $send-i32 + (local.get $21) + ) + (nop) + (nop) + (local.set $24 + (i64.gt_s + (local.get $z) + (local.get $w) + ) + ) + (call $send-i32 + (local.get $24) + ) + (nop) + (nop) + (local.set $27 + (i64.gt_u + (local.get $z) + (local.get $w) + ) + ) + (call $send-i32 + (local.get $27) + ) + ) + (func $various-conditions-1 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (nop) + (if + (local.get $x) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + ) + ) + (func $various-conditions-2 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (nop) + (local.set $2 + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + ) + (if + (local.get $2) + (block + (nop) + (nop) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (func $various-conditions-3 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local.set $1 + (i32.reinterpret_f32 + (f32.const 0) + ) + ) + (if + (local.get $1) + (block + (nop) + (nop) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 4) + ) + ) + ) + ) + ) + (func $various-conditions-4 (param $x i32) + (local $1 i32) + (local $2 i32) + (block + (unreachable) + (if + (unreachable) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + ) + ) + ) + (unreachable) + ) + (func $unaries (param $x i32) (param $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (nop) + (local.set $3 + (i32.eqz + (local.get $x) + ) + ) + (if + (local.get $3) + (block + (nop) + (local.set $5 + (i32.ctz + (local.get $y) + ) + ) + (nop) + (local.set $7 + (i32.clz + (local.get $x) + ) + ) + (nop) + (local.set $9 + (i32.popcnt + (local.get $y) + ) + ) + (local.set $10 + (i32.sub + (local.get $7) + (local.get $9) + ) + ) + (nop) + (local.set $x + (i32.add + (local.get $5) + (local.get $10) + ) + ) + ) + ) + ) + (func $unary-condition (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (nop) + (local.set $2 + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $3 + (i32.ctz + (local.get $2) + ) + ) + (if + (local.get $3) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (func $unary-condition-2 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (nop) + (local.set $2 + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $3 + (i32.eqz + (local.get $2) + ) + ) + (if + (local.get $3) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (func $if-else-cond (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block + (nop) + (local.set $2 + (i32.lt_s + (local.get $x) + (i32.const 1) + ) + ) + (if + (local.get $2) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (nop) + (local.set $8 + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $trivial-ret (result i32) + (local $0 i32) + (local.set $0 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (return + (local.get $0) + ) + ) + (func $trivial-const (result i32) + (return + (i32.const 0) + ) + ) + (func $trivial-const-block (result i32) + (local $0 i32) + (local $1 i32) + (block + (nop) + (nop) + ) + (local.set $1 + (i32.const 0) + ) + (return + (local.get $1) + ) + ) + (func $bad-phi-value (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block + (if + (i32.const 1) + (block + (nop) + (local.set $1 + (i32.load + (i32.const 0) + ) + ) + ) + (local.set $1 + (i32.const 0) + ) + ) + (nop) + (if + (local.get $1) + (local.set $3 + (i32.const 0) + ) + (local.set $3 + (i32.const 1) + ) + ) + ) + (nop) + (return + (local.get $3) + ) + ) + (func $bad-phi-value-2 (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block + (if + (i32.const 1) + (block + (nop) + (local.set $2 + (i32.load + (i32.const 0) + ) + ) + ) + (local.set $2 + (i32.const 0) + ) + ) + (nop) + (if + (local.get $2) + (local.set $x + (i32.const 1) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $x) + ) + ) + (func $select (param $x i32) (result i32) + (local $1 i32) + (local.set $1 + (select + (i32.const 1) + (i32.const 2) + (i32.const 3) + ) + ) + (return + (local.get $1) + ) + (unreachable) + ) + (func $select-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (nop) + (nop) + (local.set $4 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (nop) + (local.set $6 + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (local.set $8 + (i32.add + (i32.const 2) + (local.get $y) + ) + ) + (local.set $9 + (select + (local.get $4) + (local.get $6) + (local.get $8) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (func $block-phi-1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block $out + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (br_if $out + (local.get $y) + ) + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (nop) + (nop) + (nop) + ) + (local.set $10 + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (return + (local.get $10) + ) + ) + (func $block-phi-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $out + (local.set $x + (i32.const 1) + ) + (nop) + (br_if $out + (local.get $y) + ) + (local.set $x + (i32.const 2) + ) + ) + (nop) + (nop) + (nop) + ) + (local.set $6 + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (return + (local.get $6) + ) + ) + (func $zero_init-phi-bad_type (result f64) + (local $x f64) + (local $1 f64) + (local $2 f64) + (local $3 f64) + (block + (if + (i32.const 0) + (local.set $x + (f64.const 1) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $x) + ) + ) + (func $phi-bad-type (result f64) + (local $0 f64) + (local $1 f64) + (local $2 f64) + (local $3 f64) + (block $label$1 + (if + (i32.const 0) + (local.set $0 + (f64.const 0) + ) + (local.set $0 + (f64.const 1) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $0) + ) + ) + (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) + (local $i i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (block + (block + (nop) + (nop) + (local.set $5 + (i32.le_s + (local.get $x) + (local.get $y) + ) + ) + (if + (local.get $5) + (block + (nop) + (nop) + (nop) + (local.set $i + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + ) + (block + (nop) + (nop) + (nop) + (local.set $i + (i32.add + (local.get $x) + (local.get $y) + ) + ) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $i) + ) + ) + (func $call (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $0 + (call $call) + ) + (local.set $1 + (call $call) + ) + (local.set $2 + (i32.add + (local.get $0) + (local.get $1) + ) + ) + (local.set $3 + (call $call) + ) + (local.set $4 + (i32.add + (i32.const 10) + (local.get $3) + ) + ) + (local.set $5 + (i32.mul + (local.get $2) + (local.get $4) + ) + ) + (return + (local.get $5) + ) + (unreachable) + ) + (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (unreachable) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $4) + ) + ) + (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $out + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (br $out) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $out + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (br_table $out $out $out + (i32.const 1) + ) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block + (block $out + (block + (nop) + (if + (local.get $x) + (block $block + (local.set $x + (i32.const 1) + ) + (nop) + (br_if $out + (local.get $x) + ) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $6) + ) + ) + (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $label$1 + (block $label$2 + (block $label$3 + (block + (nop) + (if + (local.get $2) + (block + (block + (nop) + (if + (local.get $0) + (block + (block $block + (local.set $1 + (i32.const -8531) + ) + (br $label$3) + (unreachable) + ) + (unreachable) + ) + (block + (block $block3 + (local.set $1 + (i32.const -8531) + ) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + ) + ) + (unreachable) + ) + ) + ) + (br $label$2) + (unreachable) + ) + (local.set $6 + (i32.load + (i32.const 0) + ) + ) + (drop + (local.get $6) + ) + (br $label$1) + (unreachable) + ) + (nop) + (i32.store16 + (i32.const 1) + (local.get $1) + ) + (unreachable) + (unreachable) + ) + (i32.store16 + (i32.const 0) + (i32.const -8531) + ) + ) + (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (block $block + (unreachable) + (unreachable) + (block + (nop) + (if + (local.get $x) + (local.set $x + (i32.const 1) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (unreachable) + ) + (func $merge-with-one-less (param $var$0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $label$1 + (block $label$2 + (block $label$3 + (block $label$4 + (block $label$5 + (local.set $1 + (i32.load + (i32.const 1) + ) + ) + (br_table $label$5 $label$4 $label$3 $label$2 + (local.get $1) + ) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (br $label$1) + (unreachable) + ) + (local.set $var$0 + (i32.const 8) + ) + (nop) + (local.set $3 + (i32.load + (local.get $var$0) + ) + ) + (f64.store + (local.get $3) + (f64.const 0) + ) + (br $label$1) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (nop) + (i32.store + (local.get $var$0) + (i32.const 16) + ) + (nop) + ) + (local.set $6 + (i32.const 1) + ) + (return + (local.get $6) + ) + ) + (func $deep (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 i32) + (local $24 i32) + (local $25 i32) + (local $26 i32) + (local $27 i32) + (local $28 i32) + (local $29 i32) + (local $30 i32) + (local $31 i32) + (local $32 i32) + (local $33 i32) + (local $34 i32) + (local $35 i32) + (local $36 i32) + (local $37 i32) + (local $38 i32) + (local $39 i32) + (local $40 i32) + (local $41 i32) + (local $42 i32) + (local $43 i32) + (local $44 i32) + (local $45 i32) + (local $46 i32) + (local $47 i32) + (local $48 i32) + (local $49 i32) + (local $50 i32) + (local $51 i32) + (local $52 i32) + (local $53 i32) + (local $54 i32) + (local $55 i32) + (block + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $x) + ) + ) + (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) + (local $3 i64) + (local $4 i64) + (local $5 i32) + (local $6 i64) + (local $7 i32) + (local $8 i64) + (local $9 i64) + (local $10 i64) + (local $11 i64) + (local $12 i64) + (local $13 i64) + (local $14 i64) + (local $15 i32) + (local $16 i64) + (local $17 i64) + (local $18 i64) + (local $19 i64) + (local $20 i64) + (local $21 i64) + (local $22 i64) + (local $23 i64) + (local $24 i64) + (block + (block + (nop) + (nop) + (local.set $5 + (i64.lt_s + (local.get $x) + (local.get $y) + ) + ) + (if + (local.get $5) + (block + (nop) + (local.set $7 + (i64.eqz + (local.get $x) + ) + ) + (if + (local.get $7) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.add + (local.get $x) + (local.get $y) + ) + ) + ) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.sub + (local.get $x) + (local.get $y) + ) + ) + ) + ) + ) + (block + (nop) + (local.set $15 + (i64.eqz + (local.get $y) + ) + ) + (if + (local.get $15) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.mul + (local.get $x) + (local.get $y) + ) + ) + ) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.div_s + (local.get $x) + (local.get $y) + ) + ) + ) + ) + ) + ) + ) + (nop) + (return + (local.get $t) + ) + (unreachable) + ) + (nop) + (return + (local.get $23) + ) + ) + (func $loop-1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + ) + (nop) + (nop) + (local.set $4 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $4) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $loop-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 4) + ) + ) + ) + (nop) + (nop) + (local.set $8 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $loop-3 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 4) + ) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-4 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-5 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (local.set $y + (i32.const 2) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-6 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (nop) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $8 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $loop-7 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (local.set $y + (i32.const 5) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-8 (param $x i32) (param $y i32) (result i32) + (local $z i32) + (local $w i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (local.set $z + (local.get $x) + ) + (nop) + (local.set $w + (local.get $y) + ) + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 4) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $12 + (i32.sub + (local.get $z) + (local.get $w) + ) + ) + (local.set $13 + (i32.mul + (local.get $9) + (local.get $12) + ) + ) + (return + (local.get $13) + ) + (unreachable) + ) + (nop) + (return + (local.get $14) + ) + ) + (func $loop-9 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (local.set $t + (local.get $x) + ) + (nop) + (local.set $x + (local.get $y) + ) + (nop) + (local.set $y + (local.get $t) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-10 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 1) + ) + (loop $loopy + (nop) + (local.set $t + (local.get $x) + ) + (nop) + (local.set $x + (local.get $y) + ) + (nop) + (local.set $y + (local.get $t) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (loop $loopy + (local.set $x + (i32.const 4) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (local.set $y + (i32.const 5) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (local.set $z + (i32.const 6) + ) + ) + (nop) + (nop) + (nop) + (local.set $9 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 4) + ) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 5) + ) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (nop) + (nop) + (local.set $z + (i32.add + (local.get $z) + (i32.const 6) + ) + ) + ) + (nop) + (nop) + (nop) + (local.set $15 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (loop $loopy + (block $out + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 4) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 5) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $z + (i32.add + (local.get $z) + (i32.const 6) + ) + ) + (br $loopy) + (unreachable) + ) + ) + (nop) + (nop) + (nop) + (local.set $15 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (block $out + (loop $loopy + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 4) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 5) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $z + (i32.add + (local.get $z) + (i32.const 6) + ) + ) + (br $loopy) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (nop) + (nop) + (nop) + (local.set $15 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local $11 f64) + (nop) + (if + (local.get $var$2) + (block + (loop $label$2 + (block + (block + (block $label$3 + (if + (i32.const 0) + (block + (unreachable) + (unreachable) + ) + ) + (nop) + (nop) + ) + (local.set $6 + (i32.const 0) + ) + (if + (local.get $6) + (block + (unreachable) + (unreachable) + ) + ) + ) + (nop) + (br_if $label$2 + (local.get $var$2) + ) + (nop) + ) + (nop) + (local.set $10 + (f64.const 0) + ) + ) + (nop) + (drop + (local.get $10) + ) + ) + ) + ) + (func $loop-unreachable + (local $var$0 i32) + (local $var$1 f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 f64) + (local $12 f64) + (local $13 f64) + (loop $label$1 + (block + (block $label$2 + (block $label$3 + (block $label$4 + (if + (i32.const 1337) + (block + (unreachable) + (unreachable) + ) + ) + (nop) + (nop) + ) + (nop) + (nop) + (loop $label$6 + (block $label$7 + (nop) + (local.set $6 + (local.get $var$0) + ) + (br_if $label$7 + (i32.const 65535) + ) + (nop) + (drop + (local.get $6) + ) + (nop) + (local.set $6 + (local.get $var$0) + ) + (br_if $label$7 + (i32.const 0) + ) + (nop) + (drop + (local.get $6) + ) + (unreachable) + (unreachable) + ) + (nop) + (br_if $label$6 + (local.get $6) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (nop) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (func $phi-value-turns-bad (result f64) + (local $var$0 i32) + (local $var$1 i32) + (local $var$2 f32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 f32) + (local $13 f32) + (local $14 f32) + (local $15 f32) + (local $16 f64) + (local $17 f64) + (block + (block + (nop) + (local.set $var$0 + (i32.atomic.rmw16.sub_u offset=22 + (i32.const 0) + (i32.const 0) + ) + ) + (nop) + (if + (local.get $var$0) + (block + (unreachable) + (unreachable) + ) + (block + (block $block + (block + (loop $label$3 + (block $label$4 + (nop) + (local.set $6 + (local.get $var$0) + ) + (br_if $label$4 + (i32.const 1) + ) + (nop) + (nop) + (local.set $6 + (i32.clz + (local.get $6) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (if + (local.get $6) + (nop) + ) + ) + (nop) + ) + (nop) + (local.set $14 + (f32.const 1) + ) + ) + ) + ) + (nop) + (nop) + (unreachable) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $multi-use (param $x i32) (result i32) + (local $temp i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (block + (nop) + (nop) + (local.set $temp + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (nop) + (nop) + (nop) + ) + (local.set $8 + (i32.add + (local.get $temp) + (local.get $temp) + ) + ) + (return + (local.get $8) + ) + ) + (func $multi-use-2 (param $x i32) (result i32) + (local $temp i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (nop) + (nop) + (local.set $temp + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $temp) + (i32.const 2) + ) + ) + (nop) + (nop) + (nop) + (nop) + ) + (local.set $10 + (i32.sub + (local.get $x) + (local.get $temp) + ) + ) + (return + (local.get $10) + ) + ) + (func $many-single-uses-with-param (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (nop) + (local.set $2 + (i32.mul + (i32.const 10) + (local.get $x) + ) + ) + (nop) + (local.set $4 + (i32.ctz + (local.get $x) + ) + ) + (local.set $5 + (i32.sub + (local.get $4) + (i32.const 20) + ) + ) + (local.set $6 + (i32.add + (local.get $2) + (local.get $5) + ) + ) + (local.set $7 + (i32.eqz + (local.get $6) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (func $56 (param $var$0 i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (nop) + (nop) + (local.set $var$0 + (i32.add + (local.get $var$0) + (i32.const -7) + ) + ) + (nop) + (if + (local.get $var$0) + (block $label$2 + (block $label$3 + (nop) + (local.set $var$1 + (local.get $var$0) + ) + (nop) + (local.set $8 + (i32.const 12) + ) + (br_if $label$3 + (local.get $8) + ) + (unreachable) + (unreachable) + ) + (nop) + (local.set $10 + (i32.eqz + (local.get $var$1) + ) + ) + (br_if $label$2 + (local.get $10) + ) + (block + (local.set $11 + (i32.load + (i32.const 0) + ) + ) + (nop) + (local.set $13 + (i32.ne + (local.get $11) + (local.get $var$0) + ) + ) + (if + (local.get $13) + (block + (unreachable) + (unreachable) + ) + ) + ) + (unreachable) + (unreachable) + ) + ) + ) + (func $multiple-uses-to-non-expression (param $x i32) + (local $temp i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 10) + ) + ) + (nop) + (i32.store + (i32.const 1) + (local.get $x) + ) + (nop) + (local.set $6 + (i32.add + (local.get $x) + (i32.const 20) + ) + ) + (i32.store + (i32.const 2) + (local.get $6) + ) + ) + (func $nested-phi-forwarding (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (block $label$1 + (block $label$2 + (loop $label$3 + (block $label$4 + (block $label$5 + (block $label$6 + (block $label$7 + (block $label$8 + (nop) + (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 + (local.get $var$0) + ) + (unreachable) + ) + (local.set $var$1 + (i32.const 1) + ) + ) + (br $label$4) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (br $label$1) + (unreachable) + ) + (local.set $var$2 + (i32.const 1) + ) + (nop) + (br_if $label$3 + (local.get $var$2) + ) + ) + ) + (block $label$9 + (nop) + (local.set $6 + (i32.or + (i32.const 1) + (local.get $var$1) + ) + ) + (br_if $label$9 + (local.get $6) + ) + ) + (unreachable) + (unreachable) + ) + (nop) + (i32.store offset=176 + (i32.const 0) + (local.get $var$2) + ) + (nop) + ) + (local.set $9 + (i32.const 0) + ) + (return + (local.get $9) + ) + ) + (func $zext-numGets (param $var$0 i32) (param $var$1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (block $label$1 + (local.set $2 + (i32.load + (i32.const -8) + ) + ) + (local.set $3 + (i32.const 1) + ) + (br_if $label$1 + (local.get $2) + ) + (nop) + (drop + (local.get $3) + ) + (local.set $5 + (i32.load + (i32.const -16) + ) + ) + (nop) + (local.set $3 + (i32.eqz + (local.get $5) + ) + ) + ) + (nop) + (local.set $8 + (i32.ctz + (local.get $3) + ) + ) + (if + (local.get $8) + (block + (unreachable) + (unreachable) + ) + ) + ) + (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) + (local $temp i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block $label$1 + (local.set $3 + (i32.load + (i32.const -8) + ) + ) + (local.set $4 + (i32.const 1) + ) + (br_if $label$1 + (local.get $3) + ) + (nop) + (drop + (local.get $4) + ) + (local.set $6 + (i32.load + (i32.const -16) + ) + ) + (nop) + (local.set $temp + (i32.eqz + (local.get $6) + ) + ) + (nop) + (drop + (local.get $temp) + ) + (nop) + (local.set $4 + (local.get $temp) + ) + ) + (nop) + (local.set $11 + (i32.ctz + (local.get $4) + ) + ) + (if + (local.get $11) + (block + (unreachable) + (unreachable) + ) + ) + ) + (func $flipped-needs-right-origin (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block + (block $label$1 + (local.set $2 + (i32.load + (i32.const 1) + ) + ) + (br_if $label$1 + (local.get $2) + ) + (local.set $var$1 + (i32.const 2) + ) + ) + (block + (nop) + (local.set $4 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (local.set $5 + (i32.gt_s + (i32.const 3) + (local.get $4) + ) + ) + (if + (local.get $5) + (block + (unreachable) + (unreachable) + ) + ) + ) + (nop) + ) + (local.set $7 + (i32.const 5) + ) + (return + (local.get $7) + ) + ) + (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (nop) + (nop) + (local.set $var$1 + (i32.gt_u + (local.get $var$1) + (i32.const 1) + ) + ) + (nop) + (i32.store + (local.get $var$1) + (i32.const 2) + ) + (nop) + (local.set $7 + (i32.sub + (i32.const 4) + (local.get $var$1) + ) + ) + (i32.store offset=8 + (i32.const 3) + (local.get $7) + ) + (unreachable) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (loop $label$1 + (block + (if + (i32.const 0) + (block + (block $block + (nop) + (local.set $var$2 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + ) + (nop) + (nop) + (nop) + (nop) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (local $var$6 i32) + (local $var$7 i32) + (local $var$8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (block + (local.set $var$1 + (i32.const 1) + ) + (if + (i32.const 0) + (loop $label$2 + (block + (nop) + (if + (local.get $var$1) + (nop) + ) + ) + (local.set $var$3 + (i32.const 1) + ) + (nop) + (nop) + (local.set $var$1 + (i32.sub + (i32.const 0) + (local.get $var$3) + ) + ) + (br_if $label$2 + (i32.const 0) + ) + ) + ) + (block + (nop) + (if + (local.get $var$1) + (local.set $var$3 + (i32.const 1) + ) + ) + ) + (nop) + (local.set $14 + (i32.add + (local.get $var$3) + (i32.const 16) + ) + ) + (i32.store + (i32.const 8) + (local.get $14) + ) + (i32.store + (i32.const 8) + (i32.const 64) + ) + (unreachable) + (unreachable) + ) + (nop) + (return + (local.get $15) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast --- binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify_enable-threads.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1253 @@ +(module + (memory $0 (shared 1 1)) + ;; Figure 1a from the Souper paper https://arxiv.org/pdf/1711.04422.pdf + (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (local.set $i + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $j + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (local.set $r + (i32.and + (local.get $i) + (local.get $j) + ) + ) + (return (local.get $r)) + ) + ;; Figure 1b, with a potential path condition + (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (if + (i64.lt_s + (local.get $x) + (local.get $y) + ) + (block + (local.set $i + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $j + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (local.set $r + (i32.and + (local.get $i) + (local.get $j) + ) + ) + (return (local.get $r)) + ) + (unreachable) + ) + ) + ;; Figure 3, simplified to an if + (func $figure-3-if (param $x i32) (result i32) + (if + (i32.and + (local.get $x) + (i32.const 1) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (return + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + ) + (func $send-i32 (param i32)) + ;; flipping of greater than/or equals ops, which are not in Souper IR + (func $flips + (local $x i32) + (local $y i32) + (local $z i64) + (local $w i64) + (local.set $x (i32.ge_s (local.get $x) (local.get $y))) + (local.set $x (i32.ge_u (local.get $x) (local.get $y))) + (local.set $x (i32.gt_s (local.get $x) (local.get $y))) + (local.set $x (i32.gt_u (local.get $x) (local.get $y))) + (call $send-i32 (i64.ge_s (local.get $z) (local.get $w))) + (call $send-i32 (i64.ge_u (local.get $z) (local.get $w))) + (call $send-i32 (i64.gt_s (local.get $z) (local.get $w))) + (call $send-i32 (i64.gt_u (local.get $z) (local.get $w))) + ) + (func $various-conditions-1 (param $x i32) + (if + (local.get $x) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + ) + (func $various-conditions-2 (param $x i32) + (if + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + (func $various-conditions-3 (param $x i32) + (if + (i32.reinterpret_f32 (f32.const 0)) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 4) + ) + ) + ) + ) + (func $various-conditions-4 (param $x i32) + (if + (unreachable) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + ) + ) + (func $unaries (param $x i32) (param $y i32) + (if + (i32.eqz + (local.get $x) + ) + (local.set $x + (i32.add + (i32.ctz + (local.get $y) + ) + (i32.sub + (i32.clz + (local.get $x) + ) + (i32.popcnt + (local.get $y) + ) + ) + ) + ) + ) + ) + (func $unary-condition (param $x i32) + (if + (i32.ctz + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + (func $unary-condition-2 (param $x i32) + (if + (i32.eqz + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + (func $if-else-cond (param $x i32) (result i32) + (if + (i32.lt_s + (local.get $x) + (i32.const 1) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (return + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + ) + (func $trivial-ret (result i32) + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (func $trivial-const (result i32) + (i32.const 0) + ) + (func $trivial-const-block (result i32) + (nop) + (i32.const 0) + ) + (func $bad-phi-value (result i32) + (if (result i32) + (if (result i32) + (i32.const 1) + (i32.load + (i32.const 0) + ) + (i32.const 0) + ) + (i32.const 0) + (i32.const 1) + ) + ) + (func $bad-phi-value-2 (param $x i32) (result i32) + (if + (if (result i32) + (i32.const 1) + (i32.load + (i32.const 0) + ) + (i32.const 0) + ) + (local.set $x (i32.const 1)) + (local.set $x (i32.const 2)) + ) + (local.get $x) + ) + (func $select (param $x i32) (result i32) + (return + (select + (i32.const 1) + (i32.const 2) + (i32.const 3) + ) + ) + ) + (func $select-2 (param $x i32) (param $y i32) (result i32) + (return + (select + (i32.add + (local.get $x) + (local.get $y) + ) + (i32.add + (local.get $x) + (i32.const 1) + ) + (i32.add + (i32.const 2) + (local.get $y) + ) + ) + ) + ) + (func $block-phi-1 (param $x i32) (param $y i32) (result i32) + (block $out + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (br_if $out (local.get $y)) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (func $block-phi-2 (param $x i32) (param $y i32) (result i32) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out (local.get $y)) + (local.set $x + (i32.const 2) + ) + ) + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (func $zero_init-phi-bad_type (result f64) + (local $x f64) + (if + (i32.const 0) + (local.set $x + (f64.const 1) + ) + ) + (local.get $x) + ) + (func $phi-bad-type (result f64) + (block $label$1 (result f64) + (if (result f64) + (i32.const 0) + (f64.const 0) + (f64.const 1) + ) + ) + ) + (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) + (local $i i32) + (if + (i32.le_s + (local.get $x) + (local.get $y) + ) + (local.set $i + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + (local.set $i + (i32.add + (local.get $x) + (local.get $y) + ) + ) + ) + (local.get $i) + ) + (func $call (result i32) + (return + (i32.mul + (i32.add + (call $call) + (call $call) + ) + (i32.add + (i32.const 10) + (call $call) + ) + ) + ) + ) + (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (return (local.get $x)) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) + (block $out + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (br $out) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (return + (local.get $x) + ) + ) + (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) + (block $out + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (br_table $out $out $out (i32.const 1)) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (return + (local.get $x) + ) + ) + (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) + (block $out + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (br_if $out + (local.get $x) + ) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; there *IS* a phi here since it was a br_if + (return + (local.get $x) + ) + ) + (return + (local.get $x) + ) + ) + (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (block $label$1 + (block $label$2 + (block $label$3 + (if + (local.get $2) + (if + (local.get $0) + (block + (local.set $1 + (i32.const -8531) + ) + (br $label$3) + ) + (block + (local.set $1 + (i32.const -8531) + ) + (br $label$1) + ) + ) + ) + (br $label$2) + ) + (drop + (i32.load + (i32.const 0) + ) + ) + (br $label$1) + ) + (i32.store16 + (i32.const 1) + (local.get $1) + ) + (unreachable) + ) + (i32.store16 + (i32.const 0) + (i32.const -8531) + ) + ) + (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) + (block + (unreachable) + (if + (local.get $x) + (local.set $x + (i32.const 1) + ) + (local.set $x + (i32.const 2) + ) + ) + (return + (local.get $x) + ) + ) + ) + (func $merge-with-one-less (param $var$0 i32) (result i32) + (block $label$1 + (block $label$2 + (block $label$3 + (block $label$4 + (block $label$5 + (br_table $label$5 $label$4 $label$3 $label$2 + (i32.load + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (br $label$1) + ) + (f64.store + (i32.load + (local.tee $var$0 + (i32.const 8) + ) + ) + (f64.const 0) + ) + (br $label$1) + ) + (unreachable) + ) + (i32.store + (local.get $var$0) + (i32.const 16) + ) + (i32.const 1) + ) + (func $deep (param $x i32) (result i32) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.get $x) + ) + (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) + (if + (i64.lt_s + (local.get $x) + (local.get $y) + ) + (if + (i64.eqz + (local.get $x) + ) + (local.set $t + (i64.add + (local.get $x) + (local.get $y) + ) + ) + (local.set $t + (i64.sub + (local.get $x) + (local.get $y) + ) + ) + ) + (if + (i64.eqz + (local.get $y) + ) + (local.set $t + (i64.mul + (local.get $x) + (local.get $y) + ) + ) + (local.set $t + (i64.div_s + (local.get $x) + (local.get $y) + ) + ) + ) + ) + (return (local.get $t)) + ) + (func $loop-1 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + ) + ;; neither needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-2 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.add (local.get $y) (i32.const 4))) + ) + ;; neither needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-3 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.add (local.get $y) (i32.const 4))) + (br_if $loopy (local.get $y)) + ) + ;; both needed + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-4 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (br_if $loopy (local.get $y)) + ) + ;; only x needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-5 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.const 2)) ;; same value + (br_if $loopy (local.get $y)) + ) + ;; only x needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-6 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (local.get $y)) ;; same value + (br_if $loopy (local.get $y)) + ) + ;; only x needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-7 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.const 5)) ;; different! + (br_if $loopy (local.get $y)) + ) + ;; y changed but we don't need a phi for it + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-8 (param $x i32) (param $y i32) (result i32) + (local $z i32) + (local $w i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $z (local.get $x)) + (local.set $w (local.get $y)) + (local.set $x (i32.const 1)) ;; same! + (local.set $y (i32.const 4)) ;; different! + (br_if $loopy (local.get $y)) + ) + ;; x is always 3, and y needs a phi. + ;; each is also copied to another local, which we need + ;; to handle properly + (return + (i32.mul + (i32.add + (local.get $x) + (local.get $y) + ) + (i32.sub + (local.get $z) + (local.get $w) + ) + ) + ) + ) + (func $loop-9 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $t (local.get $x)) + (local.set $x (local.get $y)) + (local.set $y (local.get $t)) + (br_if $loopy (local.get $t)) + ) + ;; x and y swapped, so both need phis + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-10 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 1)) + (loop $loopy ;; we swap the values. but we need a deeper analysis to figure that out... + (local.set $t (local.get $x)) + (local.set $x (local.get $y)) + (local.set $y (local.get $t)) + (br_if $loopy (local.get $t)) + ) + ;; x and y swapped, but the same constant was swapped + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (loop $loopy + (local.set $x (i32.const 4)) + (br_if $loopy (local.get $t)) + (local.set $y (i32.const 5)) + (br_if $loopy (local.get $t)) + (local.set $z (i32.const 6)) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 4))) + (br_if $loopy (local.get $t)) + (local.set $y (i32.add (local.get $y) (i32.const 5))) + (br_if $loopy (local.get $t)) + (local.set $z (i32.add (local.get $z) (i32.const 6))) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (loop $loopy + (block $out + (local.set $x (i32.add (local.get $x) (i32.const 4))) + (br_if $out (local.get $t)) + (local.set $y (i32.add (local.get $y) (i32.const 5))) + (br_if $out (local.get $t)) + (local.set $z (i32.add (local.get $z) (i32.const 6))) + (br $loopy) + ) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (block $out + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 4))) + (br_if $out (local.get $t)) + (local.set $y (i32.add (local.get $y) (i32.const 5))) + (br_if $out (local.get $t)) + (local.set $z (i32.add (local.get $z) (i32.const 6))) + (br $loopy) + ) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) + (if + (local.get $var$2) + (drop + (loop $label$2 (result f64) + (if + (block $label$3 (result i32) + (if + (i32.const 0) + (unreachable) + ) + (nop) + (i32.const 0) + ) + (unreachable) + ) + (br_if $label$2 + (local.get $var$2) + ) + (f64.const 0) + ) + ) + ) + ) + (func $loop-unreachable + (local $var$0 i32) + (local $var$1 f64) + (loop $label$1 + (local.set $var$1 + (block $label$2 (result f64) + (block $label$3 + (local.set $var$0 + (block $label$4 (result i32) + (if + (i32.const 1337) + (unreachable) + ) + (local.get $var$0) + ) + ) + (loop $label$6 + (br_if $label$6 + (block $label$7 (result i32) + (drop + (br_if $label$7 + (local.get $var$0) + (i32.const 65535) + ) + ) + (drop + (br_if $label$7 + (local.get $var$0) + (i32.const 0) + ) + ) + (unreachable) + ) + ) + ) + ) + (local.get $var$1) + ) + ) + (br $label$1) + ) + ) + (func $phi-value-turns-bad (result f64) + (local $var$0 i32) + (local $var$1 i32) + (local $var$2 f32) + (local.set $var$2 + (if (result f32) + (local.tee $var$0 + (i32.atomic.rmw16.sub_u offset=22 + (i32.const 0) + (i32.const 0) + ) + ) + (unreachable) + (block (result f32) + (if + (loop $label$3 (result i32) + (block $label$4 (result i32) + (i32.clz + (br_if $label$4 + (local.get $var$0) + (i32.const 1) + ) + ) + ) + ) + (nop) + ) + (f32.const 1) + ) + ) + ) + (unreachable) + ) + (func $multi-use (param $x i32) (result i32) + (local $temp i32) + (local.set $temp (i32.add (local.get $x) (i32.const 1))) + (i32.add (local.get $temp) (local.get $temp)) + ) + (func $multi-use-2 (param $x i32) (result i32) + (local $temp i32) + (local.set $temp (i32.add (local.get $x) (i32.const 1))) + (local.set $x (i32.mul (local.get $temp) (i32.const 2))) + (i32.sub (local.get $x) (local.get $temp)) + ) + (func $many-single-uses-with-param (param $x i32) (result i32) + (return + (i32.eqz + (i32.add + (i32.mul + (i32.const 10) + (local.get $x) + ) + (i32.sub + (i32.ctz + (local.get $x) + ) + (i32.const 20) + ) + ) + ) + ) + ) + (func "replaced-print-internal" (param $var$0 i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (if + (local.tee $var$0 + (i32.add + (local.get $var$0) + (i32.const -7) + ) + ) + (block $label$2 + (block $label$3 + (local.set $var$1 + (local.get $var$0) + ) + (br_if $label$3 + (local.tee $var$3 + (i32.const 12) + ) + ) + (unreachable) + ) + (br_if $label$2 + (i32.eqz + (local.get $var$1) + ) + ) + (if + (i32.ne + (i32.load + (i32.const 0) + ) + (local.get $var$0) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (func $multiple-uses-to-non-expression (param $x i32) + (local $temp i32) + (local.set $x + (i32.add + (local.get $x) + (i32.const 10) + ) + ) + (i32.store + (i32.const 1) + (local.get $x) ;; x+10 has two uses! + ) + (i32.store + (i32.const 2) + (i32.add + (local.get $x) + (i32.const 20) + ) + ) + ) + (func $nested-phi-forwarding (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (block $label$1 + (block $label$2 + (loop $label$3 + (block $label$4 + (block $label$5 + (block $label$6 + (block $label$7 + (block $label$8 + (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 + (local.get $var$0) + ) + ) + (local.set $var$1 + (i32.const 1) + ) + ) + (br $label$4) + ) + (unreachable) + ) + (br $label$1) + ) + (br_if $label$3 + (local.tee $var$2 + (i32.const 1) + ) + ) + ) + ) + (block $label$9 + (br_if $label$9 + (i32.or + (i32.const 1) + (local.get $var$1) + ) + ) + ) + (unreachable) + ) + (i32.store offset=176 + (i32.const 0) + (local.get $var$2) + ) + (i32.const 0) + ) + (func $zext-numGets (param $var$0 i32) (param $var$1 i32) + (if + (i32.ctz + (block $label$1 (result i32) + (drop + (br_if $label$1 + (i32.const 1) + (i32.load + (i32.const -8) + ) + ) + ) + (i32.eqz + (i32.load + (i32.const -16) + ) + ) + ) + ) + (unreachable) + ) + ) + (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) + (local $temp i32) + (if + (i32.ctz + (block $label$1 (result i32) + (drop + (br_if $label$1 + (i32.const 1) + (i32.load + (i32.const -8) + ) + ) + ) + (local.set $temp + (i32.eqz + (i32.load + (i32.const -16) + ) + ) + ) + (drop + (local.get $temp) + ) + (local.get $temp) + ) + ) + (unreachable) + ) + ) + (func $flipped-needs-right-origin (param $var$0 i32) (result i32) + (local $var$1 i32) + (block $label$1 + (br_if $label$1 + (i32.load + (i32.const 1) + ) + ) + (local.set $var$1 + (i32.const 2) + ) + ) + (if + (i32.gt_s + (i32.const 3) + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (unreachable) + ) + (i32.const 5) + ) + (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (i32.store + (local.tee $var$1 + (i32.gt_u + (local.get $var$1) + (i32.const 1) + ) + ) + (i32.const 2) + ) + (i32.store offset=8 + (i32.const 3) + (i32.sub + (i32.const 4) + (local.get $var$1) + ) + ) + (unreachable) + ) + (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) + (loop $label$1 + (if + (i32.const 0) + (block + (local.set $var$2 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (br $label$1) + ) + ) + (local.set $var$3 + (local.get $var$2) + ) + (local.set $var$2 + (local.get $var$3) + ) + (br $label$1) + ) + ) + (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (local $var$6 i32) + (local $var$7 i32) + (local $var$8 i32) + (local.set $var$1 + (i32.const 1) + ) + (if + (i32.const 0) + (loop $label$2 + (if + (local.get $var$1) + (nop) + ) + (local.set $var$1 + (i32.sub + (i32.const 0) + (local.tee $var$3 + (i32.const 1) + ) + ) + ) + (br_if $label$2 + (i32.const 0) + ) + ) + ) + (if + (local.get $var$1) + (local.set $var$3 + (i32.const 1) + ) + ) + (i32.store + (i32.const 8) + (i32.add + (local.get $var$3) + (i32.const 16) + ) + ) + (i32.store + (i32.const 8) + (i32.const 64) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.txt binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.txt --- binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,4775 @@ + +; function: figure-1a + +; start LHS (in figure-1a) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +infer %2 + + +; start LHS (in figure-1a) +%0:i64 = var +%1:i64 = var +%2 = ne %0, %1 +infer %2 + + +; start LHS (in figure-1a) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +%3:i32 = zext %2 +%4:i64 = var +%5 = ne %0, %4 +%6:i32 = zext %5 +%7 = and %3, %6 +infer %7 + + +; function: figure-1b + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = slt %0, %1 +infer %2 + + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +%3:i64 = var +%4 = slt %1, %3 +pc %4 1:i1 +infer %2 + + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = ne %0, %1 +%3:i64 = var +%4 = slt %3, %1 +pc %4 1:i1 +infer %2 + + +; start LHS (in figure-1b) +%0:i64 = var +%1:i64 = var +%2 = eq %0, %1 +%3:i32 = zext %2 +%4:i64 = var +%5 = ne %0, %4 +%6:i32 = zext %5 +%7 = and %3, %6 +%8 = slt %1, %4 +pc %8 1:i1 +infer %7 + + +; function: figure-3-if + +; start LHS (in figure-3-if) +%0:i32 = var +%1 = and %0, 1:i32 +infer %1 + + +; start LHS (in figure-3-if) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = and %0, 1:i32 +%3 = ne %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in figure-3-if) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = and %0, 1:i32 +%3 = eq %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in figure-3-if) +%0 = block 2 +%1:i32 = var +%2 = add %1, 1:i32 +%3 = add %1, 2:i32 +%4 = phi %0, %2, %3 +%5 = and %4, 1:i32 +%6 = and %1, 1:i32 +%7 = ne %6, 0:i32 +blockpc %0 0 %7 1:i1 +%8 = eq %6, 0:i32 +blockpc %0 1 %8 1:i1 +infer %5 + + +; function: flips + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +infer %0 + + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +%1:i32 = zext %0 +%2 = ule 0:i32, %1 +infer %2 + + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +%1:i32 = zext %0 +%2 = ule 0:i32, %1 +%3:i32 = zext %2 +%4 = slt 0:i32, %3 +infer %4 + + +; start LHS (in flips) +%0 = sle 0:i32, 0:i32 +%1:i32 = zext %0 +%2 = ule 0:i32, %1 +%3:i32 = zext %2 +%4 = slt 0:i32, %3 +%5:i32 = zext %4 +%6 = ult 0:i32, %5 +infer %6 + + +; function: various-conditions-1 + +; start LHS (in various-conditions-1) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = ne %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; function: various-conditions-2 + +; start LHS (in various-conditions-2) +%0:i32 = var +%1 = slt %0, 0:i32 +infer %1 + + +; start LHS (in various-conditions-2) +%0:i32 = var +%1 = sub %0, 2:i32 +%2 = slt %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; function: various-conditions-3 + +; start LHS (in various-conditions-3) +%0:i32 = var +%1 = sub %0, 4:i32 +%2:i32 = var +%3 = ne %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; function: various-conditions-4 + +; function: unaries + +; start LHS (in unaries) +%0:i32 = var +%1 = eq %0, 0:i32 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = cttz %0 +%2:i32 = var +%3 = eq %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = ctlz %0 +%2 = eq %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = ctpop %0 +%2:i32 = var +%3 = eq %2, 0:i32 +pc %3 1:i1 +infer %1 + + +; start LHS (in unaries) +%0:i32 = var +%1 = ctlz %0 +%2:i32 = var +%3 = ctpop %2 +%4 = sub %1, %3 +%5 = eq %0, 0:i32 +pc %5 1:i1 +infer %4 + + +; start LHS (in unaries) +%0:i32 = var +%1 = cttz %0 +%2:i32 = var +%3 = ctlz %2 +%4 = ctpop %0 +%5 = sub %3, %4 +%6 = add %1, %5 +%7 = eq %2, 0:i32 +pc %7 1:i1 +infer %6 + + +; function: unary-condition + +; start LHS (in unary-condition) +%0:i32 = var +%1 = ult 1:i32, %0 +infer %1 + + +; start LHS (in unary-condition) +%0:i32 = var +%1 = ult 1:i32, %0 +%2:i32 = zext %1 +%3 = cttz %2 +infer %3 + + +; start LHS (in unary-condition) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = ult 1:i32, %0 +%3:i32 = zext %2 +%4 = cttz %3 +%5 = ne %4, 0:i32 +pc %5 1:i1 +infer %1 + + +; function: unary-condition-2 + +; start LHS (in unary-condition-2) +%0:i32 = var +%1 = ult 1:i32, %0 +infer %1 + + +; start LHS (in unary-condition-2) +%0:i32 = var +%1 = ult 1:i32, %0 +%2:i32 = zext %1 +%3 = eq %2, 0:i32 +infer %3 + + +; start LHS (in unary-condition-2) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = ult 1:i32, %0 +%3:i32 = zext %2 +%4 = eq %3, 0:i32 +pc %4 1:i1 +infer %1 + + +; function: if-else-cond + +; start LHS (in if-else-cond) +%0:i32 = var +%1 = slt %0, 1:i32 +infer %1 + + +; start LHS (in if-else-cond) +%0:i32 = var +%1 = add %0, 1:i32 +%2 = slt %0, 1:i32 +pc %2 1:i1 +infer %1 + + +; start LHS (in if-else-cond) +%0:i32 = var +%1 = add %0, 2:i32 +%2 = slt %0, 1:i32 +%3:i32 = zext %2 +%4 = eq %3, 0:i32 +pc %4 1:i1 +infer %1 + + +; start LHS (in if-else-cond) +%0 = block 2 +%1:i32 = var +%2 = add %1, 1:i32 +%3 = add %1, 2:i32 +%4 = phi %0, %2, %3 +%5 = and %4, 1:i32 +%6 = slt %1, 1:i32 +blockpc %0 0 %6 1:i1 +%7:i32 = zext %6 +%8 = eq %7, 0:i32 +blockpc %0 1 %8 1:i1 +infer %5 + + +; function: trivial-ret + +; start LHS (in trivial-ret) +%0 = add 0:i32, 1:i32 +infer %0 + + +; function: trivial-const + +; function: trivial-const-block + +; function: bad-phi-value + +; function: bad-phi-value-2 + +; function: select + +; start LHS (in select) +%0 = ne 3:i32, 0:i32 +infer %0 + + +; start LHS (in select) +%0 = ne 3:i32, 0:i32 +%1 = select %0, 1:i32, 2:i32 +infer %1 + + +; function: select-2 + +; start LHS (in select-2) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add 2:i32, %0 +infer %1 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add 2:i32, %0 +%2 = ne %1, 0:i32 +infer %2 + + +; start LHS (in select-2) +%0:i32 = var +%1 = add 2:i32, %0 +%2 = ne %1, 0:i32 +%3:i32 = var +%4 = add %3, %0 +%5 = add %3, 1:i32 +%6 = select %2, %4, %5 +infer %6 + + +; function: block-phi-1 + +; start LHS (in block-phi-1) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in block-phi-1) +%0:i32 = var +%1 = add %0, 2:i32 +infer %1 + + +; start LHS (in block-phi-1) +%0 = block 2 +%1:i32 = var +%2 = add %1, 2:i32 +%3 = phi %0, %1, %2 +%4 = add %3, 3:i32 +infer %4 + + +; function: block-phi-2 + +; start LHS (in block-phi-2) +%0 = block 2 +%1 = phi %0, 1:i32, 2:i32 +%2 = add %1, 3:i32 +infer %2 + + +; function: zero_init-phi-bad_type + +; function: phi-bad-type + +; function: phi-one-side-i1 + +; start LHS (in phi-one-side-i1) +%0:i32 = var +%1:i32 = var +%2 = sle %0, %1 +infer %2 + + +; start LHS (in phi-one-side-i1) +%0:i32 = var +%1:i32 = var +%2 = eq %0, %1 +%3 = sle %0, %1 +pc %3 1:i1 +infer %2 + + +; start LHS (in phi-one-side-i1) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +%3 = sle %0, %1 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +pc %5 1:i1 +infer %2 + + +; function: call + +; start LHS (in call) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; start LHS (in call) +%0:i32 = var +%1 = add 10:i32, %0 +infer %1 + + +; start LHS (in call) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +%3:i32 = var +%4 = add 10:i32, %3 +%5 = mul %2, %4 +infer %5 + + +; function: in-unreachable-1 + +; function: in-unreachable-2 + +; function: in-unreachable-3 + +; function: in-unreachable-4 + +; function: in-unreachable-br_if + +; function: in-unreachable-big + +; function: in-unreachable-operations + +; function: merge-with-one-less + +; function: deep + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +infer %1 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +infer %2 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +infer %3 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +infer %4 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +infer %5 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +infer %6 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +infer %7 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +infer %8 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = xor %0, 1234:i32 +%2 = mul %1, 1234:i32 +%3 = xor %2, 1234:i32 +%4 = mul %3, 1234:i32 +%5 = xor %4, 1234:i32 +%6 = mul %5, 1234:i32 +%7 = xor %6, 1234:i32 +%8 = mul %7, 1234:i32 +%9 = xor %8, 1234:i32 +infer %9 + + +; start LHS (in deep) +%0:i32 = var +%1 = mul %0, 1234:i32 +%2 = xor %1, 1234:i32 +%3 = mul %2, 1234:i32 +%4 = xor %3, 1234:i32 +%5 = mul %4, 1234:i32 +%6 = xor %5, 1234:i32 +%7 = mul %6, 1234:i32 +%8 = xor %7, 1234:i32 +%9 = mul %8, 1234:i32 +infer %9 + + +; function: two-pcs + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = slt %0, %1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1 = eq %0, 0:i64 +%2:i64 = var +%3 = slt %0, %2 +pc %3 1:i1 +infer %1 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = add %0, %1 +%3 = eq %0, 0:i64 +%4 = slt %0, %1 +pc %3 1:i1 +pc %4 1:i1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = sub %0, %1 +%3 = eq %0, 0:i64 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +%6 = slt %0, %1 +pc %5 1:i1 +pc %6 1:i1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1 = eq %0, 0:i64 +%2:i64 = var +%3 = slt %2, %0 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +pc %5 1:i1 +infer %1 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = mul %0, %1 +%3 = eq %1, 0:i64 +%4 = slt %0, %1 +%5:i32 = zext %4 +%6 = eq %5, 0:i32 +pc %3 1:i1 +pc %6 1:i1 +infer %2 + + +; start LHS (in two-pcs) +%0:i64 = var +%1:i64 = var +%2 = sdiv %0, %1 +%3 = eq %1, 0:i64 +%4:i32 = zext %3 +%5 = eq %4, 0:i32 +%6 = slt %0, %1 +%7:i32 = zext %6 +%8 = eq %7, 0:i32 +pc %5 1:i1 +pc %8 1:i1 +infer %2 + + +; function: loop-1 + +; start LHS (in loop-1) +%0 = add 1:i32, 2:i32 +infer %0 + + +; function: loop-2 + +; start LHS (in loop-2) +%0 = add 1:i32, 3:i32 +infer %0 + + +; start LHS (in loop-2) +%0 = add 2:i32, 4:i32 +infer %0 + + +; start LHS (in loop-2) +%0 = add 1:i32, 3:i32 +%1 = add 2:i32, 4:i32 +%2 = add %0, %1 +infer %2 + + +; function: loop-3 + +; start LHS (in loop-3) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-3) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-3) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; function: loop-4 + +; start LHS (in loop-4) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-4) +%0:i32 = var +%1 = add %0, 2:i32 +infer %1 + + +; function: loop-5 + +; start LHS (in loop-5) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-5) +%0:i32 = var +%1 = add %0, 2:i32 +infer %1 + + +; function: loop-6 + +; start LHS (in loop-6) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-6) +%0:i32 = var +%1 = add %0, 2:i32 +infer %1 + + +; function: loop-7 + +; start LHS (in loop-7) +%0:i32 = var +%1 = add %0, 3:i32 +infer %1 + + +; start LHS (in loop-7) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; function: loop-8 + +; start LHS (in loop-8) +%0 = add 1:i32, 4:i32 +infer %0 + + +; start LHS (in loop-8) +%0:i32 = var +%1 = sub 1:i32, %0 +infer %1 + + +; start LHS (in loop-8) +%0 = add 1:i32, 4:i32 +%1:i32 = var +%2 = sub 1:i32, %1 +%3 = mul %0, %2 +infer %3 + + +; function: loop-9 + +; start LHS (in loop-9) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; function: loop-10 + +; start LHS (in loop-10) +%0:i32 = var +%1:i32 = var +%2 = add %0, %1 +infer %2 + + +; function: loop-multicond-1 + +; start LHS (in loop-multicond-1) +%0 = ne 6:i32, 0:i32 +infer %0 + + +; start LHS (in loop-multicond-1) +%0 = ne 6:i32, 0:i32 +%1 = select %0, 4:i32, 5:i32 +infer %1 + + +; function: loop-multicond-2 + +; start LHS (in loop-multicond-2) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-multicond-2) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; start LHS (in loop-multicond-2) +%0 = add 3:i32, 6:i32 +infer %0 + + +; start LHS (in loop-multicond-2) +%0 = add 3:i32, 6:i32 +%1 = ne %0, 0:i32 +infer %1 + + +; start LHS (in loop-multicond-2) +%0 = add 3:i32, 6:i32 +%1 = ne %0, 0:i32 +%2:i32 = var +%3:i32 = var +%4 = select %1, %2, %3 +infer %4 + + +; function: loop-block-1 + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = add %0, 6:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = ne %0, 0:i32 +infer %1 + + +; start LHS (in loop-block-1) +%0:i32 = var +%1 = ne %0, 0:i32 +%2:i32 = var +%3 = block 2 +%4:i32 = var +%5:i32 = var +%6 = phi %3, %4, %5 +%7 = select %1, %2, %6 +infer %7 + + +; function: loop-block-2 + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = add %0, 4:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = add %0, 5:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = add %0, 6:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = ne %0, 0:i32 +infer %1 + + +; start LHS (in loop-block-2) +%0:i32 = var +%1 = ne %0, 0:i32 +%2:i32 = var +%3 = block 2 +%4:i32 = var +%5:i32 = var +%6 = phi %3, %4, %5 +%7 = select %1, %2, %6 +infer %7 + + +; function: bad-phi-type + +; function: loop-unreachable + +; function: phi-value-turns-bad + +; start LHS (in phi-value-turns-bad) +%0:i32 = var +%1 = ctlz %0 +%2 = eq %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; function: multi-use + +; start LHS (in multi-use) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in multi-use) +%0:i32 = var +%1 = add %0, %0 +infer %1 + + +; function: multi-use-2 + +; start LHS (in multi-use-2) +%0:i32 = var +%1 = add %0, 1:i32 +infer %1 + + +; start LHS (in multi-use-2) +%0:i32 = var +%1 = mul %0, 2:i32 +infer %1 + + +; start LHS (in multi-use-2) +%0:i32 = var +%1 = mul %0, 2:i32 +%2 = sub %1, %0 +infer %2 + + +; function: many-single-uses-with-param + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = mul 10:i32, %0 +infer %1 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = cttz %0 +infer %1 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = cttz %0 +%2 = sub %1, 20:i32 +infer %2 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = mul 10:i32, %0 +%2 = cttz %0 +%3 = sub %2, 20:i32 +%4 = add %1, %3 +infer %4 + + +; start LHS (in many-single-uses-with-param) +%0:i32 = var +%1 = mul 10:i32, %0 +%2 = cttz %0 +%3 = sub %2, 20:i32 +%4 = add %1, %3 +%5 = eq %4, 0:i32 +infer %5 + + +; function: 55 + +; start LHS (in 55) +%0:i32 = var +%1 = add %0, -7:i32 +infer %1 + + +; start LHS (in 55) +%0:i32 = var +%1 = eq %0, 0:i32 +%2 = ne %0, 0:i32 +pc %2 1:i1 +infer %1 + + +; start LHS (in 55) +%0:i32 = var +%1:i32 = var +%2 = ne %0, %1 +%3 = ne %1, 0:i32 +pc %3 1:i1 +infer %2 + + +; function: multiple-uses-to-non-expression + +; start LHS (in multiple-uses-to-non-expression) +%0:i32 = var +%1 = add %0, 10:i32 +infer %1 + + +; start LHS (in multiple-uses-to-non-expression) +%0:i32 = var +%1 = add %0, 20:i32 +infer %1 + + +; function: nested-phi-forwarding + +; start LHS (in nested-phi-forwarding) +%0 = block 2 +%1:i32 = var +%2 = block 2 +%3 = block 2 +%4 = phi %3, %1, 1:i32 +%5 = phi %2, %1, %4 +%6 = phi %0, %1, %5 +%7 = or 1:i32, %6 +infer %7 + + +; function: zext-numGets + +; start LHS (in zext-numGets) +%0:i32 = var +%1 = eq %0, 0:i32 +infer %1 + + +; start LHS (in zext-numGets) +%0 = block 2 +%1:i32 = var +%2 = eq %1, 0:i32 +%3:i32 = zext %2 +%4 = phi %0, 1:i32, %3 +%5 = cttz %4 +infer %5 + + +; function: zext-numGets-hasAnotherUse + +; start LHS (in zext-numGets-hasAnotherUse) +%0:i32 = var +%1 = eq %0, 0:i32 +infer %1 + + +; start LHS (in zext-numGets-hasAnotherUse) +%0 = block 2 +%1:i32 = var +%2 = eq %1, 0:i32 +%3:i32 = zext %2 +%4 = phi %0, 1:i32, %3 +%5 = cttz %4 +infer %5 + + +; function: flipped-needs-right-origin + +; start LHS (in flipped-needs-right-origin) +%0 = block 2 +%1 = phi %0, 0:i32, 2:i32 +%2 = add %1, 4:i32 +infer %2 + + +; start LHS (in flipped-needs-right-origin) +%0 = block 2 +%1 = phi %0, 0:i32, 2:i32 +%2 = add %1, 4:i32 +%3 = slt %2, 3:i32 +infer %3 + + +; function: non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN + +; start LHS (in non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN) +%0:i32 = var +%1 = ult 1:i32, %0 +infer %1 + + +; start LHS (in non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN) +%0:i32 = var +%1:i32 = zext %0 +%2 = sub 4:i32, %1 +infer %2 + + +; function: loop-of-set-connections + +; start LHS (in loop-of-set-connections) +%0 = add 0:i32, 1:i32 +%1 = ne 0:i32, 0:i32 +pc %1 1:i1 +infer %0 + + +; function: conditions-in-conditions + +; start LHS (in conditions-in-conditions) +%0 = sub 0:i32, 1:i32 +%1 = ne 0:i32, 0:i32 +pc %1 1:i1 +infer %0 + + +; start LHS (in conditions-in-conditions) +%0 = block 2 +%1 = block 2 +%2 = phi %1, 0:i32, 1:i32 +%3 = phi %0, %2, 1:i32 +%4 = add %3, 16:i32 +%5 = ne 0:i32, 0:i32 +blockpc %1 0 %5 1:i1 +%6 = eq 0:i32, 0:i32 +blockpc %1 1 %6 1:i1 +%7:i32 = var +%8 = phi %1, 1:i32, %7 +%9 = ne %8, 0:i32 +blockpc %0 0 %9 1:i1 +%10 = eq %8, 0:i32 +blockpc %0 1 %10 1:i1 +infer %4 + +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_f64 (func (result f64))) + (type $none_=>_none (func)) + (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) + (type $i64_i64_i32_f32_=>_none (func (param i64 i64 i32 f32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) + (type $i64_i64_i64_=>_i64 (func (param i64 i64 i64) (result i64))) + (memory $0 (shared 1 1)) + (export "replaced-print-internal" (func $55)) + (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (local $6 i64) + (local $7 i64) + (local $8 i32) + (local $9 i64) + (local $10 i64) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (local.set $12 + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $13 + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $15 + (i32.and + (local.get $12) + (local.get $13) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (local $6 i64) + (local $7 i64) + (local $8 i32) + (local $9 i64) + (local $10 i64) + (local $11 i32) + (local $12 i64) + (local $13 i64) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (block + (nop) + (nop) + (local.set $8 + (i64.lt_s + (local.get $x) + (local.get $y) + ) + ) + (if + (local.get $8) + (block + (block $block + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (local.set $15 + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $16 + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $18 + (i32.and + (local.get $15) + (local.get $16) + ) + ) + (return + (local.get $18) + ) + (unreachable) + ) + (unreachable) + ) + (block + (unreachable) + (unreachable) + ) + ) + ) + (unreachable) + ) + (func $figure-3-if (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block + (nop) + (local.set $2 + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (if + (local.get $2) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (nop) + (local.set $8 + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $flips + (local $x i32) + (local $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (nop) + (nop) + (nop) + (local.set $x + (i32.ge_s + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (nop) + (local.set $x + (i32.ge_u + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (nop) + (local.set $x + (i32.gt_s + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (nop) + (local.set $x + (i32.gt_u + (local.get $x) + (local.get $y) + ) + ) + ) + (func $various-conditions-1 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (nop) + (if + (local.get $x) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + ) + ) + (func $various-conditions-2 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (nop) + (local.set $2 + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + ) + (if + (local.get $2) + (block + (nop) + (nop) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (func $various-conditions-3 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local.set $1 + (i32.reinterpret_f32 + (f32.const 0) + ) + ) + (if + (local.get $1) + (block + (nop) + (nop) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 4) + ) + ) + ) + ) + ) + (func $various-conditions-4 (param $x i32) + (local $1 i32) + (local $2 i32) + (block + (unreachable) + (if + (unreachable) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + ) + ) + ) + (unreachable) + ) + (func $unaries (param $x i32) (param $y i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (nop) + (local.set $3 + (i32.eqz + (local.get $x) + ) + ) + (if + (local.get $3) + (block + (nop) + (local.set $5 + (i32.ctz + (local.get $y) + ) + ) + (nop) + (local.set $7 + (i32.clz + (local.get $x) + ) + ) + (nop) + (local.set $9 + (i32.popcnt + (local.get $y) + ) + ) + (local.set $10 + (i32.sub + (local.get $7) + (local.get $9) + ) + ) + (nop) + (local.set $x + (i32.add + (local.get $5) + (local.get $10) + ) + ) + ) + ) + ) + (func $unary-condition (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (nop) + (local.set $2 + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $3 + (i32.ctz + (local.get $2) + ) + ) + (if + (local.get $3) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (func $unary-condition-2 (param $x i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (nop) + (local.set $2 + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $3 + (i32.eqz + (local.get $2) + ) + ) + (if + (local.get $3) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (func $if-else-cond (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block + (nop) + (local.set $2 + (i32.lt_s + (local.get $x) + (i32.const 1) + ) + ) + (if + (local.get $2) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + ) + (nop) + (local.set $8 + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $trivial-ret (result i32) + (local $0 i32) + (local.set $0 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (return + (local.get $0) + ) + ) + (func $trivial-const (result i32) + (return + (i32.const 0) + ) + ) + (func $trivial-const-block (result i32) + (local $0 i32) + (local $1 i32) + (block + (nop) + (nop) + ) + (local.set $1 + (i32.const 0) + ) + (return + (local.get $1) + ) + ) + (func $bad-phi-value (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (block + (if + (i32.const 1) + (block + (nop) + (local.set $1 + (i32.load + (i32.const 0) + ) + ) + ) + (local.set $1 + (i32.const 0) + ) + ) + (nop) + (if + (local.get $1) + (local.set $3 + (i32.const 0) + ) + (local.set $3 + (i32.const 1) + ) + ) + ) + (nop) + (return + (local.get $3) + ) + ) + (func $bad-phi-value-2 (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block + (if + (i32.const 1) + (block + (nop) + (local.set $2 + (i32.load + (i32.const 0) + ) + ) + ) + (local.set $2 + (i32.const 0) + ) + ) + (nop) + (if + (local.get $2) + (local.set $x + (i32.const 1) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $x) + ) + ) + (func $select (param $x i32) (result i32) + (local $1 i32) + (local.set $1 + (select + (i32.const 1) + (i32.const 2) + (i32.const 3) + ) + ) + (return + (local.get $1) + ) + (unreachable) + ) + (func $select-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (nop) + (nop) + (local.set $4 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (nop) + (local.set $6 + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (local.set $8 + (i32.add + (i32.const 2) + (local.get $y) + ) + ) + (local.set $9 + (select + (local.get $4) + (local.get $6) + (local.get $8) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (func $block-phi-1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (block $out + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (br_if $out + (local.get $y) + ) + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (nop) + (nop) + (nop) + ) + (local.set $10 + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (return + (local.get $10) + ) + ) + (func $block-phi-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $out + (local.set $x + (i32.const 1) + ) + (nop) + (br_if $out + (local.get $y) + ) + (local.set $x + (i32.const 2) + ) + ) + (nop) + (nop) + (nop) + ) + (local.set $6 + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (return + (local.get $6) + ) + ) + (func $zero_init-phi-bad_type (result f64) + (local $x f64) + (local $1 f64) + (local $2 f64) + (local $3 f64) + (block + (if + (i32.const 0) + (local.set $x + (f64.const 1) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $x) + ) + ) + (func $phi-bad-type (result f64) + (local $0 f64) + (local $1 f64) + (local $2 f64) + (local $3 f64) + (block $label$1 + (if + (i32.const 0) + (local.set $0 + (f64.const 0) + ) + (local.set $0 + (f64.const 1) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $0) + ) + ) + (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) + (local $i i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (block + (block + (nop) + (nop) + (local.set $5 + (i32.le_s + (local.get $x) + (local.get $y) + ) + ) + (if + (local.get $5) + (block + (nop) + (nop) + (nop) + (local.set $i + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + ) + (block + (nop) + (nop) + (nop) + (local.set $i + (i32.add + (local.get $x) + (local.get $y) + ) + ) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $i) + ) + ) + (func $call (result i32) + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $0 + (call $call) + ) + (local.set $1 + (call $call) + ) + (local.set $2 + (i32.add + (local.get $0) + (local.get $1) + ) + ) + (local.set $3 + (call $call) + ) + (local.set $4 + (i32.add + (i32.const 10) + (local.get $3) + ) + ) + (local.set $5 + (i32.mul + (local.get $2) + (local.get $4) + ) + ) + (return + (local.get $5) + ) + (unreachable) + ) + (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (unreachable) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $4) + ) + ) + (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $out + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (br $out) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $out + (block + (nop) + (if + (local.get $x) + (block + (block $block + (local.set $x + (i32.const 1) + ) + (br_table $out $out $out + (i32.const 1) + ) + (unreachable) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block + (block $out + (block + (nop) + (if + (local.get $x) + (block $block + (local.set $x + (i32.const 1) + ) + (nop) + (br_if $out + (local.get $x) + ) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (nop) + (return + (local.get $6) + ) + ) + (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block $label$1 + (block $label$2 + (block $label$3 + (block + (nop) + (if + (local.get $2) + (block + (block + (nop) + (if + (local.get $0) + (block + (block $block + (local.set $1 + (i32.const -8531) + ) + (br $label$3) + (unreachable) + ) + (unreachable) + ) + (block + (block $block3 + (local.set $1 + (i32.const -8531) + ) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + ) + ) + (unreachable) + ) + ) + ) + (br $label$2) + (unreachable) + ) + (local.set $6 + (i32.load + (i32.const 0) + ) + ) + (drop + (local.get $6) + ) + (br $label$1) + (unreachable) + ) + (nop) + (i32.store16 + (i32.const 1) + (local.get $1) + ) + (unreachable) + (unreachable) + ) + (i32.store16 + (i32.const 0) + (i32.const -8531) + ) + ) + (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (block $block + (unreachable) + (unreachable) + (block + (nop) + (if + (local.get $x) + (local.set $x + (i32.const 1) + ) + (local.set $x + (i32.const 2) + ) + ) + ) + (nop) + (return + (local.get $x) + ) + (unreachable) + ) + (unreachable) + ) + (func $merge-with-one-less (param $var$0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (block $label$1 + (block $label$2 + (block $label$3 + (block $label$4 + (block $label$5 + (local.set $1 + (i32.load + (i32.const 1) + ) + ) + (br_table $label$5 $label$4 $label$3 $label$2 + (local.get $1) + ) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (br $label$1) + (unreachable) + ) + (local.set $var$0 + (i32.const 8) + ) + (nop) + (local.set $3 + (i32.load + (local.get $var$0) + ) + ) + (f64.store + (local.get $3) + (f64.const 0) + ) + (br $label$1) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (nop) + (i32.store + (local.get $var$0) + (i32.const 16) + ) + (nop) + ) + (local.set $6 + (i32.const 1) + ) + (return + (local.get $6) + ) + ) + (func $deep (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 i32) + (local $24 i32) + (local $25 i32) + (local $26 i32) + (local $27 i32) + (local $28 i32) + (local $29 i32) + (local $30 i32) + (local $31 i32) + (local $32 i32) + (local $33 i32) + (local $34 i32) + (local $35 i32) + (local $36 i32) + (local $37 i32) + (local $38 i32) + (local $39 i32) + (local $40 i32) + (local $41 i32) + (local $42 i32) + (local $43 i32) + (local $44 i32) + (local $45 i32) + (local $46 i32) + (local $47 i32) + (local $48 i32) + (local $49 i32) + (local $50 i32) + (local $51 i32) + (local $52 i32) + (local $53 i32) + (local $54 i32) + (local $55 i32) + (block + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.xor + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $x) + (i32.const 1234) + ) + ) + (nop) + (nop) + ) + (nop) + (return + (local.get $x) + ) + ) + (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) + (local $3 i64) + (local $4 i64) + (local $5 i32) + (local $6 i64) + (local $7 i32) + (local $8 i64) + (local $9 i64) + (local $10 i64) + (local $11 i64) + (local $12 i64) + (local $13 i64) + (local $14 i64) + (local $15 i32) + (local $16 i64) + (local $17 i64) + (local $18 i64) + (local $19 i64) + (local $20 i64) + (local $21 i64) + (local $22 i64) + (local $23 i64) + (local $24 i64) + (block + (block + (nop) + (nop) + (local.set $5 + (i64.lt_s + (local.get $x) + (local.get $y) + ) + ) + (if + (local.get $5) + (block + (nop) + (local.set $7 + (i64.eqz + (local.get $x) + ) + ) + (if + (local.get $7) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.add + (local.get $x) + (local.get $y) + ) + ) + ) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.sub + (local.get $x) + (local.get $y) + ) + ) + ) + ) + ) + (block + (nop) + (local.set $15 + (i64.eqz + (local.get $y) + ) + ) + (if + (local.get $15) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.mul + (local.get $x) + (local.get $y) + ) + ) + ) + (block + (nop) + (nop) + (nop) + (local.set $t + (i64.div_s + (local.get $x) + (local.get $y) + ) + ) + ) + ) + ) + ) + ) + (nop) + (return + (local.get $t) + ) + (unreachable) + ) + (nop) + (return + (local.get $23) + ) + ) + (func $loop-1 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + ) + (nop) + (nop) + (local.set $4 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $4) + ) + (unreachable) + ) + (nop) + (return + (local.get $5) + ) + ) + (func $loop-2 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 4) + ) + ) + ) + (nop) + (nop) + (local.set $8 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $loop-3 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 4) + ) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-4 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-5 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (local.set $y + (i32.const 2) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-6 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (nop) + (nop) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $8 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $8) + ) + (unreachable) + ) + (nop) + (return + (local.get $9) + ) + ) + (func $loop-7 (param $x i32) (param $y i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (local.set $y + (i32.const 5) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $7 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-8 (param $x i32) (param $y i32) (result i32) + (local $z i32) + (local $w i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (local.set $z + (local.get $x) + ) + (nop) + (local.set $w + (local.get $y) + ) + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 4) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $12 + (i32.sub + (local.get $z) + (local.get $w) + ) + ) + (local.set $13 + (i32.mul + (local.get $9) + (local.get $12) + ) + ) + (return + (local.get $13) + ) + (unreachable) + ) + (nop) + (return + (local.get $14) + ) + ) + (func $loop-9 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (loop $loopy + (nop) + (local.set $t + (local.get $x) + ) + (nop) + (local.set $x + (local.get $y) + ) + (nop) + (local.set $y + (local.get $t) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-10 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 1) + ) + (loop $loopy + (nop) + (local.set $t + (local.get $x) + ) + (nop) + (local.set $x + (local.get $y) + ) + (nop) + (local.set $y + (local.get $t) + ) + (nop) + (br_if $loopy + (local.get $y) + ) + ) + (nop) + (nop) + (local.set $9 + (i32.add + (local.get $x) + (local.get $y) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (loop $loopy + (local.set $x + (i32.const 4) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (local.set $y + (i32.const 5) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (local.set $z + (i32.const 6) + ) + ) + (nop) + (nop) + (nop) + (local.set $9 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $9) + ) + (unreachable) + ) + (nop) + (return + (local.get $10) + ) + ) + (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (loop $loopy + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 4) + ) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 5) + ) + ) + (nop) + (br_if $loopy + (local.get $t) + ) + (nop) + (nop) + (local.set $z + (i32.add + (local.get $z) + (i32.const 6) + ) + ) + ) + (nop) + (nop) + (nop) + (local.set $15 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (loop $loopy + (block $out + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 4) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 5) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $z + (i32.add + (local.get $z) + (i32.const 6) + ) + ) + (br $loopy) + (unreachable) + ) + ) + (nop) + (nop) + (nop) + (local.set $15 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (block + (local.set $x + (i32.const 1) + ) + (local.set $y + (i32.const 2) + ) + (local.set $z + (i32.const 3) + ) + (block $out + (loop $loopy + (block + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 4) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $y + (i32.add + (local.get $y) + (i32.const 5) + ) + ) + (nop) + (br_if $out + (local.get $t) + ) + (nop) + (nop) + (local.set $z + (i32.add + (local.get $z) + (i32.const 6) + ) + ) + (br $loopy) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (nop) + (nop) + (nop) + (local.set $15 + (select + (local.get $x) + (local.get $y) + (local.get $z) + ) + ) + (return + (local.get $15) + ) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local $11 f64) + (nop) + (if + (local.get $var$2) + (block + (loop $label$2 + (block + (block + (block $label$3 + (if + (i32.const 0) + (block + (unreachable) + (unreachable) + ) + ) + (nop) + (nop) + ) + (local.set $6 + (i32.const 0) + ) + (if + (local.get $6) + (block + (unreachable) + (unreachable) + ) + ) + ) + (nop) + (br_if $label$2 + (local.get $var$2) + ) + (nop) + ) + (nop) + (local.set $10 + (f64.const 0) + ) + ) + (nop) + (drop + (local.get $10) + ) + ) + ) + ) + (func $loop-unreachable + (local $var$0 i32) + (local $var$1 f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 f64) + (local $12 f64) + (local $13 f64) + (loop $label$1 + (block + (block $label$2 + (block $label$3 + (block $label$4 + (if + (i32.const 1337) + (block + (unreachable) + (unreachable) + ) + ) + (nop) + (nop) + ) + (nop) + (nop) + (loop $label$6 + (block $label$7 + (nop) + (local.set $6 + (local.get $var$0) + ) + (br_if $label$7 + (i32.const 65535) + ) + (nop) + (drop + (local.get $6) + ) + (nop) + (local.set $6 + (local.get $var$0) + ) + (br_if $label$7 + (i32.const 0) + ) + (nop) + (drop + (local.get $6) + ) + (unreachable) + (unreachable) + ) + (nop) + (br_if $label$6 + (local.get $6) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (nop) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (func $phi-value-turns-bad (result f64) + (local $var$0 i32) + (local $var$1 i32) + (local $var$2 f32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 f32) + (local $13 f32) + (local $14 f32) + (local $15 f32) + (local $16 f64) + (local $17 f64) + (block + (block + (nop) + (local.set $var$0 + (i32.atomic.rmw16.sub_u offset=22 + (i32.const 0) + (i32.const 0) + ) + ) + (nop) + (if + (local.get $var$0) + (block + (unreachable) + (unreachable) + ) + (block + (block $block + (block + (loop $label$3 + (block $label$4 + (nop) + (local.set $6 + (local.get $var$0) + ) + (br_if $label$4 + (i32.const 1) + ) + (nop) + (nop) + (local.set $6 + (i32.clz + (local.get $6) + ) + ) + ) + (nop) + (nop) + ) + (nop) + (if + (local.get $6) + (nop) + ) + ) + (nop) + ) + (nop) + (local.set $14 + (f32.const 1) + ) + ) + ) + ) + (nop) + (nop) + (unreachable) + (unreachable) + ) + (nop) + (return + (local.get $16) + ) + ) + (func $multi-use (param $x i32) (result i32) + (local $temp i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (block + (nop) + (nop) + (local.set $temp + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (nop) + (nop) + (nop) + ) + (local.set $8 + (i32.add + (local.get $temp) + (local.get $temp) + ) + ) + (return + (local.get $8) + ) + ) + (func $multi-use-2 (param $x i32) (result i32) + (local $temp i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (block + (nop) + (nop) + (local.set $temp + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (nop) + (nop) + (local.set $x + (i32.mul + (local.get $temp) + (i32.const 2) + ) + ) + (nop) + (nop) + (nop) + (nop) + ) + (local.set $10 + (i32.sub + (local.get $x) + (local.get $temp) + ) + ) + (return + (local.get $10) + ) + ) + (func $many-single-uses-with-param (param $x i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (nop) + (local.set $2 + (i32.mul + (i32.const 10) + (local.get $x) + ) + ) + (nop) + (local.set $4 + (i32.ctz + (local.get $x) + ) + ) + (local.set $5 + (i32.sub + (local.get $4) + (i32.const 20) + ) + ) + (local.set $6 + (i32.add + (local.get $2) + (local.get $5) + ) + ) + (local.set $7 + (i32.eqz + (local.get $6) + ) + ) + (return + (local.get $7) + ) + (unreachable) + ) + (func $55 (param $var$0 i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (nop) + (nop) + (local.set $var$0 + (i32.add + (local.get $var$0) + (i32.const -7) + ) + ) + (nop) + (if + (local.get $var$0) + (block $label$2 + (block $label$3 + (nop) + (local.set $var$1 + (local.get $var$0) + ) + (nop) + (local.set $8 + (i32.const 12) + ) + (br_if $label$3 + (local.get $8) + ) + (unreachable) + (unreachable) + ) + (nop) + (local.set $10 + (i32.eqz + (local.get $var$1) + ) + ) + (br_if $label$2 + (local.get $10) + ) + (block + (local.set $11 + (i32.load + (i32.const 0) + ) + ) + (nop) + (local.set $13 + (i32.ne + (local.get $11) + (local.get $var$0) + ) + ) + (if + (local.get $13) + (block + (unreachable) + (unreachable) + ) + ) + ) + (unreachable) + (unreachable) + ) + ) + ) + (func $multiple-uses-to-non-expression (param $x i32) + (local $temp i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (nop) + (nop) + (local.set $x + (i32.add + (local.get $x) + (i32.const 10) + ) + ) + (nop) + (i32.store + (i32.const 1) + (local.get $x) + ) + (nop) + (local.set $6 + (i32.add + (local.get $x) + (i32.const 20) + ) + ) + (i32.store + (i32.const 2) + (local.get $6) + ) + ) + (func $nested-phi-forwarding (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (block $label$1 + (block $label$2 + (loop $label$3 + (block $label$4 + (block $label$5 + (block $label$6 + (block $label$7 + (block $label$8 + (nop) + (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 + (local.get $var$0) + ) + (unreachable) + ) + (local.set $var$1 + (i32.const 1) + ) + ) + (br $label$4) + (unreachable) + ) + (unreachable) + (unreachable) + ) + (br $label$1) + (unreachable) + ) + (local.set $var$2 + (i32.const 1) + ) + (nop) + (br_if $label$3 + (local.get $var$2) + ) + ) + ) + (block $label$9 + (nop) + (local.set $6 + (i32.or + (i32.const 1) + (local.get $var$1) + ) + ) + (br_if $label$9 + (local.get $6) + ) + ) + (unreachable) + (unreachable) + ) + (nop) + (i32.store offset=176 + (i32.const 0) + (local.get $var$2) + ) + (nop) + ) + (local.set $9 + (i32.const 0) + ) + (return + (local.get $9) + ) + ) + (func $zext-numGets (param $var$0 i32) (param $var$1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (block $label$1 + (local.set $2 + (i32.load + (i32.const -8) + ) + ) + (local.set $3 + (i32.const 1) + ) + (br_if $label$1 + (local.get $2) + ) + (nop) + (drop + (local.get $3) + ) + (local.set $5 + (i32.load + (i32.const -16) + ) + ) + (nop) + (local.set $3 + (i32.eqz + (local.get $5) + ) + ) + ) + (nop) + (local.set $8 + (i32.ctz + (local.get $3) + ) + ) + (if + (local.get $8) + (block + (unreachable) + (unreachable) + ) + ) + ) + (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) + (local $temp i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (block $label$1 + (local.set $3 + (i32.load + (i32.const -8) + ) + ) + (local.set $4 + (i32.const 1) + ) + (br_if $label$1 + (local.get $3) + ) + (nop) + (drop + (local.get $4) + ) + (local.set $6 + (i32.load + (i32.const -16) + ) + ) + (nop) + (local.set $temp + (i32.eqz + (local.get $6) + ) + ) + (nop) + (drop + (local.get $temp) + ) + (nop) + (local.set $4 + (local.get $temp) + ) + ) + (nop) + (local.set $11 + (i32.ctz + (local.get $4) + ) + ) + (if + (local.get $11) + (block + (unreachable) + (unreachable) + ) + ) + ) + (func $flipped-needs-right-origin (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (block + (block $label$1 + (local.set $2 + (i32.load + (i32.const 1) + ) + ) + (br_if $label$1 + (local.get $2) + ) + (local.set $var$1 + (i32.const 2) + ) + ) + (block + (nop) + (local.set $4 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (local.set $5 + (i32.gt_s + (i32.const 3) + (local.get $4) + ) + ) + (if + (local.get $5) + (block + (unreachable) + (unreachable) + ) + ) + ) + (nop) + ) + (local.set $7 + (i32.const 5) + ) + (return + (local.get $7) + ) + ) + (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (block + (nop) + (nop) + (local.set $var$1 + (i32.gt_u + (local.get $var$1) + (i32.const 1) + ) + ) + (nop) + (i32.store + (local.get $var$1) + (i32.const 2) + ) + (nop) + (local.set $7 + (i32.sub + (i32.const 4) + (local.get $var$1) + ) + ) + (i32.store offset=8 + (i32.const 3) + (local.get $7) + ) + (unreachable) + (unreachable) + ) + (nop) + (return + (local.get $8) + ) + ) + (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (loop $label$1 + (block + (if + (i32.const 0) + (block + (block $block + (nop) + (local.set $var$2 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + ) + (nop) + (nop) + (nop) + (nop) + (br $label$1) + (unreachable) + ) + (unreachable) + ) + (unreachable) + ) + (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (local $var$6 i32) + (local $var$7 i32) + (local $var$8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (block + (local.set $var$1 + (i32.const 1) + ) + (if + (i32.const 0) + (loop $label$2 + (block + (nop) + (if + (local.get $var$1) + (nop) + ) + ) + (local.set $var$3 + (i32.const 1) + ) + (nop) + (nop) + (local.set $var$1 + (i32.sub + (i32.const 0) + (local.get $var$3) + ) + ) + (br_if $label$2 + (i32.const 0) + ) + ) + ) + (block + (nop) + (if + (local.get $var$1) + (local.set $var$3 + (i32.const 1) + ) + ) + ) + (nop) + (local.set $14 + (i32.add + (local.get $var$3) + (i32.const 16) + ) + ) + (i32.store + (i32.const 8) + (local.get $14) + ) + (i32.store + (i32.const 8) + (i32.const 64) + ) + (unreachable) + (unreachable) + ) + (nop) + (return + (local.get $15) + ) + ) +) diff -Nru binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast --- binaryen-108/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/flatten_simplify-locals-nonesting_souperify-single-use_enable-threads.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1246 @@ +(module + (memory $0 (shared 1 1)) + ;; Figure 1a from the Souper paper https://arxiv.org/pdf/1711.04422.pdf + (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (local.set $i + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $j + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (local.set $r + (i32.and + (local.get $i) + (local.get $j) + ) + ) + (return (local.get $r)) + ) + ;; Figure 1b, with a potential path condition + (func $figure-1b (param $a i64) (param $x i64) (param $y i64) (result i32) + (local $i i32) + (local $j i32) + (local $r i32) + (if + (i64.lt_s + (local.get $x) + (local.get $y) + ) + (block + (local.set $i + (i64.eq + (local.get $a) + (local.get $x) + ) + ) + (local.set $j + (i64.ne + (local.get $a) + (local.get $y) + ) + ) + (local.set $r + (i32.and + (local.get $i) + (local.get $j) + ) + ) + (return (local.get $r)) + ) + (unreachable) + ) + ) + ;; Figure 3, simplified to an if + (func $figure-3-if (param $x i32) (result i32) + (if + (i32.and + (local.get $x) + (i32.const 1) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (return + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + ) + ;; flipping of greater than/or equals ops, which are not in Souper IR + (func $flips + (local $x i32) + (local $y i32) + (local.set $x (i32.ge_s (local.get $x) (local.get $y))) + (local.set $x (i32.ge_u (local.get $x) (local.get $y))) + (local.set $x (i32.gt_s (local.get $x) (local.get $y))) + (local.set $x (i32.gt_u (local.get $x) (local.get $y))) + ) + (func $various-conditions-1 (param $x i32) + (if + (local.get $x) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + ) + ) + (func $various-conditions-2 (param $x i32) + (if + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + (func $various-conditions-3 (param $x i32) + (if + (i32.reinterpret_f32 (f32.const 0)) + (local.set $x + (i32.sub + (local.get $x) + (i32.const 4) + ) + ) + ) + ) + (func $various-conditions-4 (param $x i32) + (if + (unreachable) + (local.set $x + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + ) + ) + (func $unaries (param $x i32) (param $y i32) + (if + (i32.eqz + (local.get $x) + ) + (local.set $x + (i32.add + (i32.ctz + (local.get $y) + ) + (i32.sub + (i32.clz + (local.get $x) + ) + (i32.popcnt + (local.get $y) + ) + ) + ) + ) + ) + ) + (func $unary-condition (param $x i32) + (if + (i32.ctz + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + (func $unary-condition-2 (param $x i32) + (if + (i32.eqz + (i32.gt_u + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + ) + (func $if-else-cond (param $x i32) (result i32) + (if + (i32.lt_s + (local.get $x) + (i32.const 1) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (return + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + ) + (func $trivial-ret (result i32) + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (func $trivial-const (result i32) + (i32.const 0) + ) + (func $trivial-const-block (result i32) + (nop) + (i32.const 0) + ) + (func $bad-phi-value (result i32) + (if (result i32) + (if (result i32) + (i32.const 1) + (i32.load + (i32.const 0) + ) + (i32.const 0) + ) + (i32.const 0) + (i32.const 1) + ) + ) + (func $bad-phi-value-2 (param $x i32) (result i32) + (if + (if (result i32) + (i32.const 1) + (i32.load + (i32.const 0) + ) + (i32.const 0) + ) + (local.set $x (i32.const 1)) + (local.set $x (i32.const 2)) + ) + (local.get $x) + ) + (func $select (param $x i32) (result i32) + (return + (select + (i32.const 1) + (i32.const 2) + (i32.const 3) + ) + ) + ) + (func $select-2 (param $x i32) (param $y i32) (result i32) + (return + (select + (i32.add + (local.get $x) + (local.get $y) + ) + (i32.add + (local.get $x) + (i32.const 1) + ) + (i32.add + (i32.const 2) + (local.get $y) + ) + ) + ) + ) + (func $block-phi-1 (param $x i32) (param $y i32) (result i32) + (block $out + (local.set $x + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (br_if $out (local.get $y)) + (local.set $x + (i32.add + (local.get $x) + (i32.const 2) + ) + ) + ) + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (func $block-phi-2 (param $x i32) (param $y i32) (result i32) + (block $out + (local.set $x + (i32.const 1) + ) + (br_if $out (local.get $y)) + (local.set $x + (i32.const 2) + ) + ) + (i32.add + (local.get $x) + (i32.const 3) + ) + ) + (func $zero_init-phi-bad_type (result f64) + (local $x f64) + (if + (i32.const 0) + (local.set $x + (f64.const 1) + ) + ) + (local.get $x) + ) + (func $phi-bad-type (result f64) + (block $label$1 (result f64) + (if (result f64) + (i32.const 0) + (f64.const 0) + (f64.const 1) + ) + ) + ) + (func $phi-one-side-i1 (param $x i32) (param $y i32) (result i32) + (local $i i32) + (if + (i32.le_s + (local.get $x) + (local.get $y) + ) + (local.set $i + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + (local.set $i + (i32.add + (local.get $x) + (local.get $y) + ) + ) + ) + (local.get $i) + ) + (func $call (result i32) + (return + (i32.mul + (i32.add + (call $call) + (call $call) + ) + (i32.add + (i32.const 10) + (call $call) + ) + ) + ) + ) + (func $in-unreachable-1 (param $x i32) (param $y i32) (result i32) + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (return (local.get $x)) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (func $in-unreachable-2 (param $x i32) (param $y i32) (result i32) + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (unreachable) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (func $in-unreachable-3 (param $x i32) (param $y i32) (result i32) + (block $out + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (br $out) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (return + (local.get $x) + ) + ) + (func $in-unreachable-4 (param $x i32) (param $y i32) (result i32) + (block $out + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (br_table $out $out $out (i32.const 1)) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; no phi here! + (return + (local.get $x) + ) + ) + (return + (local.get $x) + ) + ) + (func $in-unreachable-br_if (param $x i32) (param $y i32) (result i32) + (block $out + (if + (local.get $x) + (block + (local.set $x + (i32.const 1) + ) + (br_if $out + (local.get $x) + ) + ) + (local.set $x + (i32.const 2) + ) + ) + ;; there *IS* a phi here since it was a br_if + (return + (local.get $x) + ) + ) + (return + (local.get $x) + ) + ) + (func $in-unreachable-big (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) + (block $label$1 + (block $label$2 + (block $label$3 + (if + (local.get $2) + (if + (local.get $0) + (block + (local.set $1 + (i32.const -8531) + ) + (br $label$3) + ) + (block + (local.set $1 + (i32.const -8531) + ) + (br $label$1) + ) + ) + ) + (br $label$2) + ) + (drop + (i32.load + (i32.const 0) + ) + ) + (br $label$1) + ) + (i32.store16 + (i32.const 1) + (local.get $1) + ) + (unreachable) + ) + (i32.store16 + (i32.const 0) + (i32.const -8531) + ) + ) + (func $in-unreachable-operations (param $x i32) (param $y i32) (result i32) + (block + (unreachable) + (if + (local.get $x) + (local.set $x + (i32.const 1) + ) + (local.set $x + (i32.const 2) + ) + ) + (return + (local.get $x) + ) + ) + ) + (func $merge-with-one-less (param $var$0 i32) (result i32) + (block $label$1 + (block $label$2 + (block $label$3 + (block $label$4 + (block $label$5 + (br_table $label$5 $label$4 $label$3 $label$2 + (i32.load + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (br $label$1) + ) + (f64.store + (i32.load + (local.tee $var$0 + (i32.const 8) + ) + ) + (f64.const 0) + ) + (br $label$1) + ) + (unreachable) + ) + (i32.store + (local.get $var$0) + (i32.const 16) + ) + (i32.const 1) + ) + (func $deep (param $x i32) (result i32) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.set $x (i32.xor (local.get $x) (i32.const 1234))) + (local.set $x (i32.mul (local.get $x) (i32.const 1234))) + (local.get $x) + ) + (func $two-pcs (param $x i64) (param $y i64) (param $t i64) (result i64) + (if + (i64.lt_s + (local.get $x) + (local.get $y) + ) + (if + (i64.eqz + (local.get $x) + ) + (local.set $t + (i64.add + (local.get $x) + (local.get $y) + ) + ) + (local.set $t + (i64.sub + (local.get $x) + (local.get $y) + ) + ) + ) + (if + (i64.eqz + (local.get $y) + ) + (local.set $t + (i64.mul + (local.get $x) + (local.get $y) + ) + ) + (local.set $t + (i64.div_s + (local.get $x) + (local.get $y) + ) + ) + ) + ) + (return (local.get $t)) + ) + (func $loop-1 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + ) + ;; neither needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-2 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.add (local.get $y) (i32.const 4))) + ) + ;; neither needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-3 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.add (local.get $y) (i32.const 4))) + (br_if $loopy (local.get $y)) + ) + ;; both needed + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-4 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (br_if $loopy (local.get $y)) + ) + ;; only x needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-5 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.const 2)) ;; same value + (br_if $loopy (local.get $y)) + ) + ;; only x needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-6 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (local.get $y)) ;; same value + (br_if $loopy (local.get $y)) + ) + ;; only x needed a phi + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-7 (param $x i32) (param $y i32) (result i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 3))) + (local.set $y (i32.const 5)) ;; different! + (br_if $loopy (local.get $y)) + ) + ;; y changed but we don't need a phi for it + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-8 (param $x i32) (param $y i32) (result i32) + (local $z i32) + (local $w i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $z (local.get $x)) + (local.set $w (local.get $y)) + (local.set $x (i32.const 1)) ;; same! + (local.set $y (i32.const 4)) ;; different! + (br_if $loopy (local.get $y)) + ) + ;; x is always 3, and y needs a phi. + ;; each is also copied to another local, which we need + ;; to handle properly + (return + (i32.mul + (i32.add + (local.get $x) + (local.get $y) + ) + (i32.sub + (local.get $z) + (local.get $w) + ) + ) + ) + ) + (func $loop-9 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (loop $loopy + (local.set $t (local.get $x)) + (local.set $x (local.get $y)) + (local.set $y (local.get $t)) + (br_if $loopy (local.get $t)) + ) + ;; x and y swapped, so both need phis + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-10 (param $x i32) (param $y i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 1)) + (loop $loopy ;; we swap the values. but we need a deeper analysis to figure that out... + (local.set $t (local.get $x)) + (local.set $x (local.get $y)) + (local.set $y (local.get $t)) + (br_if $loopy (local.get $t)) + ) + ;; x and y swapped, but the same constant was swapped + (return (i32.add (local.get $x) (local.get $y))) + ) + (func $loop-multicond-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (loop $loopy + (local.set $x (i32.const 4)) + (br_if $loopy (local.get $t)) + (local.set $y (i32.const 5)) + (br_if $loopy (local.get $t)) + (local.set $z (i32.const 6)) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $loop-multicond-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 4))) + (br_if $loopy (local.get $t)) + (local.set $y (i32.add (local.get $y) (i32.const 5))) + (br_if $loopy (local.get $t)) + (local.set $z (i32.add (local.get $z) (i32.const 6))) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $loop-block-1 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (loop $loopy + (block $out + (local.set $x (i32.add (local.get $x) (i32.const 4))) + (br_if $out (local.get $t)) + (local.set $y (i32.add (local.get $y) (i32.const 5))) + (br_if $out (local.get $t)) + (local.set $z (i32.add (local.get $z) (i32.const 6))) + (br $loopy) + ) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $loop-block-2 (param $x i32) (param $y i32) (param $z i32) (result i32) + (local $t i32) + (local.set $x (i32.const 1)) + (local.set $y (i32.const 2)) + (local.set $z (i32.const 3)) + (block $out + (loop $loopy + (local.set $x (i32.add (local.get $x) (i32.const 4))) + (br_if $out (local.get $t)) + (local.set $y (i32.add (local.get $y) (i32.const 5))) + (br_if $out (local.get $t)) + (local.set $z (i32.add (local.get $z) (i32.const 6))) + (br $loopy) + ) + ) + (return (select (local.get $x) (local.get $y) (local.get $z))) + ) + (func $bad-phi-type (param $var$0 i64) (param $var$1 i64) (param $var$2 i32) (param $var$3 f32) + (if + (local.get $var$2) + (drop + (loop $label$2 (result f64) + (if + (block $label$3 (result i32) + (if + (i32.const 0) + (unreachable) + ) + (nop) + (i32.const 0) + ) + (unreachable) + ) + (br_if $label$2 + (local.get $var$2) + ) + (f64.const 0) + ) + ) + ) + ) + (func $loop-unreachable + (local $var$0 i32) + (local $var$1 f64) + (loop $label$1 + (local.set $var$1 + (block $label$2 (result f64) + (block $label$3 + (local.set $var$0 + (block $label$4 (result i32) + (if + (i32.const 1337) + (unreachable) + ) + (local.get $var$0) + ) + ) + (loop $label$6 + (br_if $label$6 + (block $label$7 (result i32) + (drop + (br_if $label$7 + (local.get $var$0) + (i32.const 65535) + ) + ) + (drop + (br_if $label$7 + (local.get $var$0) + (i32.const 0) + ) + ) + (unreachable) + ) + ) + ) + ) + (local.get $var$1) + ) + ) + (br $label$1) + ) + ) + (func $phi-value-turns-bad (result f64) + (local $var$0 i32) + (local $var$1 i32) + (local $var$2 f32) + (local.set $var$2 + (if (result f32) + (local.tee $var$0 + (i32.atomic.rmw16.sub_u offset=22 + (i32.const 0) + (i32.const 0) + ) + ) + (unreachable) + (block (result f32) + (if + (loop $label$3 (result i32) + (block $label$4 (result i32) + (i32.clz + (br_if $label$4 + (local.get $var$0) + (i32.const 1) + ) + ) + ) + ) + (nop) + ) + (f32.const 1) + ) + ) + ) + (unreachable) + ) + (func $multi-use (param $x i32) (result i32) + (local $temp i32) + (local.set $temp (i32.add (local.get $x) (i32.const 1))) + (i32.add (local.get $temp) (local.get $temp)) + ) + (func $multi-use-2 (param $x i32) (result i32) + (local $temp i32) + (local.set $temp (i32.add (local.get $x) (i32.const 1))) + (local.set $x (i32.mul (local.get $temp) (i32.const 2))) + (i32.sub (local.get $x) (local.get $temp)) + ) + (func $many-single-uses-with-param (param $x i32) (result i32) + (return + (i32.eqz + (i32.add + (i32.mul + (i32.const 10) + (local.get $x) + ) + (i32.sub + (i32.ctz + (local.get $x) + ) + (i32.const 20) + ) + ) + ) + ) + ) + (func "replaced-print-internal" (param $var$0 i32) + (local $var$1 i32) + (local $var$2 i32) + (local $var$3 i32) + (if + (local.tee $var$0 + (i32.add + (local.get $var$0) + (i32.const -7) + ) + ) + (block $label$2 + (block $label$3 + (local.set $var$1 + (local.get $var$0) + ) + (br_if $label$3 + (local.tee $var$3 + (i32.const 12) + ) + ) + (unreachable) + ) + (br_if $label$2 + (i32.eqz + (local.get $var$1) + ) + ) + (if + (i32.ne + (i32.load + (i32.const 0) + ) + (local.get $var$0) + ) + (unreachable) + ) + (unreachable) + ) + ) + ) + (func $multiple-uses-to-non-expression (param $x i32) + (local $temp i32) + (local.set $x + (i32.add + (local.get $x) + (i32.const 10) + ) + ) + (i32.store + (i32.const 1) + (local.get $x) ;; x+10 has two uses! + ) + (i32.store + (i32.const 2) + (i32.add + (local.get $x) + (i32.const 20) + ) + ) + ) + (func $nested-phi-forwarding (param $var$0 i32) (result i32) + (local $var$1 i32) + (local $var$2 i32) + (block $label$1 + (block $label$2 + (loop $label$3 + (block $label$4 + (block $label$5 + (block $label$6 + (block $label$7 + (block $label$8 + (br_table $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$8 $label$2 $label$2 $label$2 $label$6 $label$2 $label$2 $label$7 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$2 $label$5 $label$4 + (local.get $var$0) + ) + ) + (local.set $var$1 + (i32.const 1) + ) + ) + (br $label$4) + ) + (unreachable) + ) + (br $label$1) + ) + (br_if $label$3 + (local.tee $var$2 + (i32.const 1) + ) + ) + ) + ) + (block $label$9 + (br_if $label$9 + (i32.or + (i32.const 1) + (local.get $var$1) + ) + ) + ) + (unreachable) + ) + (i32.store offset=176 + (i32.const 0) + (local.get $var$2) + ) + (i32.const 0) + ) + (func $zext-numGets (param $var$0 i32) (param $var$1 i32) + (if + (i32.ctz + (block $label$1 (result i32) + (drop + (br_if $label$1 + (i32.const 1) + (i32.load + (i32.const -8) + ) + ) + ) + (i32.eqz + (i32.load + (i32.const -16) + ) + ) + ) + ) + (unreachable) + ) + ) + (func $zext-numGets-hasAnotherUse (param $var$0 i32) (param $var$1 i32) + (local $temp i32) + (if + (i32.ctz + (block $label$1 (result i32) + (drop + (br_if $label$1 + (i32.const 1) + (i32.load + (i32.const -8) + ) + ) + ) + (local.set $temp + (i32.eqz + (i32.load + (i32.const -16) + ) + ) + ) + (drop + (local.get $temp) + ) + (local.get $temp) + ) + ) + (unreachable) + ) + ) + (func $flipped-needs-right-origin (param $var$0 i32) (result i32) + (local $var$1 i32) + (block $label$1 + (br_if $label$1 + (i32.load + (i32.const 1) + ) + ) + (local.set $var$1 + (i32.const 2) + ) + ) + (if + (i32.gt_s + (i32.const 3) + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (unreachable) + ) + (i32.const 5) + ) + (func $non-expr-nodes-may-have-multiple-uses-too-its-the-ORIGIN (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (i32.store + (local.tee $var$1 + (i32.gt_u + (local.get $var$1) + (i32.const 1) + ) + ) + (i32.const 2) + ) + (i32.store offset=8 + (i32.const 3) + (i32.sub + (i32.const 4) + (local.get $var$1) + ) + ) + (unreachable) + ) + (func $loop-of-set-connections (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i32) (param $var$4 i32) (result i32) + (loop $label$1 + (if + (i32.const 0) + (block + (local.set $var$2 + (i32.add + (i32.const 0) + (i32.const 1) + ) + ) + (br $label$1) + ) + ) + (local.set $var$3 + (local.get $var$2) + ) + (local.set $var$2 + (local.get $var$3) + ) + (br $label$1) + ) + ) + (func $conditions-in-conditions (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) (result i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (local $var$6 i32) + (local $var$7 i32) + (local $var$8 i32) + (local.set $var$1 + (i32.const 1) + ) + (if + (i32.const 0) + (loop $label$2 + (if + (local.get $var$1) + (nop) + ) + (local.set $var$1 + (i32.sub + (i32.const 0) + (local.tee $var$3 + (i32.const 1) + ) + ) + ) + (br_if $label$2 + (i32.const 0) + ) + ) + ) + (if + (local.get $var$1) + (local.set $var$3 + (i32.const 1) + ) + ) + (i32.store + (i32.const 8) + (i32.add + (local.get $var$3) + (i32.const 16) + ) + ) + (i32.store + (i32.const 8) + (i32.const 64) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt binaryen-99/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt --- binaryen-108/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module (type $i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64) (result i64))) - (type $vijfd (func (param i32 i64 f32 f64))) + (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) (table $0 10 10 funcref) (elem (i32.const 0) $byn$fpcast-emu$a) (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) diff -Nru binaryen-108/test/passes/fpcast-emu.txt binaryen-99/test/passes/fpcast-emu.txt --- binaryen-108/test/passes/fpcast-emu.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/fpcast-emu.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,312 @@ +(module + (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) (result i64))) + (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) + (type $f64_f64_=>_i32 (func (param f64 f64) (result i32))) + (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) + (type $i32_i64_f32_f64_=>_f32 (func (param i32 i64 f32 f64) (result f32))) + (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) + (type $f32_f32_=>_f64 (func (param f32 f32) (result f64))) + (import "env" "imported_func" (func $imported-func (param i32 i64 f32 f64) (result f32))) + (table $0 10 10 funcref) + (elem (i32.const 0) $byn$fpcast-emu$a $byn$fpcast-emu$b $byn$fpcast-emu$c $byn$fpcast-emu$d $byn$fpcast-emu$e $byn$fpcast-emu$e $byn$fpcast-emu$imported-func) + (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) + (drop + (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) + (i64.extend_i32_u + (i32.const 1) + ) + (i64.const 2) + (i64.extend_i32_u + (i32.reinterpret_f32 + (f32.const 3) + ) + ) + (i64.reinterpret_f64 + (f64.const 4) + ) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i32.const 1337) + ) + ) + ) + (func $b (param $x i32) (param $y i32) (result i64) + (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) + (i64.extend_i32_u + (i32.const 1) + ) + (i64.extend_i32_u + (i32.const 2) + ) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i32.const 1337) + ) + ) + (func $c (param $x i64) (param $y i64) (result f32) + (f32.reinterpret_i32 + (i32.wrap_i64 + (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) + (i64.const 1) + (i64.const 2) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i32.const 1337) + ) + ) + ) + ) + (func $d (param $x f32) (param $y f32) (result f64) + (f64.reinterpret_i64 + (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) + (i64.extend_i32_u + (i32.reinterpret_f32 + (f32.const 1) + ) + ) + (i64.extend_i32_u + (i32.reinterpret_f32 + (f32.const 2) + ) + ) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i32.const 1337) + ) + ) + ) + (func $e (param $x f64) (param $y f64) (result i32) + (i32.wrap_i64 + (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) + (i64.reinterpret_f64 + (f64.const 1) + ) + (i64.reinterpret_f64 + (f64.const 2) + ) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i32.const 1337) + ) + ) + ) + (func $byn$fpcast-emu$a (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (call $a + (i32.wrap_i64 + (local.get $0) + ) + (local.get $1) + (f32.reinterpret_i32 + (i32.wrap_i64 + (local.get $2) + ) + ) + (f64.reinterpret_i64 + (local.get $3) + ) + ) + (i64.const 0) + ) + (func $byn$fpcast-emu$b (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (call $b + (i32.wrap_i64 + (local.get $0) + ) + (i32.wrap_i64 + (local.get $1) + ) + ) + ) + (func $byn$fpcast-emu$c (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (i64.extend_i32_u + (i32.reinterpret_f32 + (call $c + (local.get $0) + (local.get $1) + ) + ) + ) + ) + (func $byn$fpcast-emu$d (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (i64.reinterpret_f64 + (call $d + (f32.reinterpret_i32 + (i32.wrap_i64 + (local.get $0) + ) + ) + (f32.reinterpret_i32 + (i32.wrap_i64 + (local.get $1) + ) + ) + ) + ) + ) + (func $byn$fpcast-emu$e (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (i64.extend_i32_u + (call $e + (f64.reinterpret_i64 + (local.get $0) + ) + (f64.reinterpret_i64 + (local.get $1) + ) + ) + ) + ) + (func $byn$fpcast-emu$imported-func (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (i64.extend_i32_u + (i32.reinterpret_f32 + (call $imported-func + (i32.wrap_i64 + (local.get $0) + ) + (local.get $1) + (f32.reinterpret_i32 + (i32.wrap_i64 + (local.get $2) + ) + ) + (f64.reinterpret_i64 + (local.get $3) + ) + ) + ) + ) + ) +) +(module + (type $f32_=>_i64 (func (param f32) (result i64))) + (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) (result i64))) + (table $0 42 42 funcref) + (global $global$0 (mut i32) (i32.const 10)) + (export "func_106" (func $0)) + (func $0 (param $0 f32) (result i64) + (block $label$1 (result i64) + (loop $label$2 + (global.set $global$0 + (i32.const 0) + ) + (call_indirect (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64) + (br $label$1 + (i64.const 4294967295) + ) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i64.const 0) + (i32.const 18) + ) + ) + ) + ) +) +(module + (type $f32_=>_none (func (param f32))) + (type $i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64) (result i64))) + (type $f64_=>_none (func (param f64))) + (table $0 42 42 funcref) + (elem (i32.const 0) $byn$fpcast-emu$a $byn$fpcast-emu$b) + (export "dynCall_vf" (func $dynCall_vf)) + (export "dynCall_vd" (func $min_vd)) + (func $a (param $0 f32) + (nop) + ) + (func $b (param $0 f64) + (nop) + ) + (func $dynCall_vf (param $0 f32) + (nop) + ) + (func $min_vd (param $0 f32) + (nop) + ) + (func $byn$fpcast-emu$a (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (call $a + (f32.reinterpret_i32 + (i32.wrap_i64 + (local.get $0) + ) + ) + ) + (i64.const 0) + ) + (func $byn$fpcast-emu$b (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (param $5 i64) (param $6 i64) (param $7 i64) (param $8 i64) (param $9 i64) (param $10 i64) (param $11 i64) (param $12 i64) (param $13 i64) (param $14 i64) (param $15 i64) (result i64) + (call $b + (f64.reinterpret_i64 + (local.get $0) + ) + ) + (i64.const 0) + ) +) diff -Nru binaryen-108/test/passes/fpcast-emu.wast binaryen-99/test/passes/fpcast-emu.wast --- binaryen-108/test/passes/fpcast-emu.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/fpcast-emu.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,80 @@ +(module + (type $vijfd (func (param i32) (param i64) (param f32) (param f64))) + (type $jii (func (param i32) (param i32) (result i64))) + (type $fjj (func (param i64) (param i64) (result f32))) + (type $dff (func (param f32) (param f32) (result f64))) + (type $idd (func (param f64) (param f64) (result i32))) + (import "env" "imported_func" (func $imported-func (param i32 i64 f32 f64) (result f32))) + (table 10 10 funcref) + (elem (i32.const 0) $a $b $c $d $e $e $imported-func) + (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) + (call_indirect (type $vijfd) + (i32.const 1) + (i64.const 2) + (f32.const 3) + (f64.const 4) + (i32.const 1337) + ) + ) + (func $b (param $x i32) (param $y i32) (result i64) + (call_indirect (type $jii) + (i32.const 1) + (i32.const 2) + (i32.const 1337) + ) + ) + (func $c (param $x i64) (param $y i64) (result f32) + (call_indirect (type $fjj) + (i64.const 1) + (i64.const 2) + (i32.const 1337) + ) + ) + (func $d (param $x f32) (param $y f32) (result f64) + (call_indirect (type $dff) + (f32.const 1) + (f32.const 2) + (i32.const 1337) + ) + ) + (func $e (param $x f64) (param $y f64) (result i32) + (call_indirect (type $idd) + (f64.const 1) + (f64.const 2) + (i32.const 1337) + ) + ) +) +(module + (type $0 (func (param i64))) + (type $1 (func (param f32) (result i64))) + (global $global$0 (mut i32) (i32.const 10)) + (table 42 42 funcref) + (export "func_106" (func $0)) + (func $0 (; 0 ;) (type $1) (param $0 f32) (result i64) + (block $label$1 (result i64) + (loop $label$2 + (global.set $global$0 + (i32.const 0) + ) + (call_indirect (type $0) + (br $label$1 + (i64.const 4294967295) + ) + (i32.const 18) + ) + ) + ) + ) +) +(module + (table 42 42 funcref) + (elem (i32.const 0) $a $b) + (export "dynCall_vf" (func $dynCall_vf)) + (export "dynCall_vd" (func $min_vd)) + (func $a (param $0 f32)) + (func $b (param $0 f64)) + (func $dynCall_vf (param $0 f32)) + (func $min_vd (param $0 f32)) +) + diff -Nru binaryen-108/test/passes/func-metrics.txt binaryen-99/test/passes/func-metrics.txt --- binaryen-108/test/passes/func-metrics.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/func-metrics.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,46 +1,44 @@ global + [events] : 0 [exports] : 0 [funcs] : 3 [globals] : 1 [imports] : 0 [memory-data] : 9 [table-data] : 3 - [tables] : 1 - [tags] : 0 - [total] : 6 - Const : 3 - RefFunc : 3 + [total] : 3 + const : 3 func: empty [binary-bytes] : 3 [total] : 1 [vars] : 0 - Nop : 1 + nop : 1 func: small [binary-bytes] : 9 [total] : 5 [vars] : 0 - Block : 1 - Const : 1 - Drop : 1 - Nop : 1 - Return : 1 + block : 1 + const : 1 + drop : 1 + nop : 1 + return : 1 func: ifs [binary-bytes] : 51 [total] : 24 [vars] : 1 - Binary : 1 - Block : 1 - Const : 12 - Drop : 6 - If : 4 + binary : 1 + block : 1 + const : 12 + drop : 6 + if : 4 (module (type $none_=>_none (func)) - (type $0 (func (param i32))) - (global $glob i32 (i32.const 1337)) + (type $i32_=>_none (func (param i32))) (memory $0 256 256) (data (i32.const 0) "\ff\ef\0f\1f 0@P\99") (table $0 256 256 funcref) (elem (i32.const 0) $ifs $ifs $ifs) + (global $glob i32 (i32.const 1337)) (func $empty (nop) ) @@ -92,43 +90,41 @@ ) ) global + [events] : 0 [exports] : 0 [funcs] : 0 [globals] : 0 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 0 (module ) global + [events] : 0 [exports] : 2 [funcs] : 3 [globals] : 0 [imports] : 1 - [tables] : 0 - [tags] : 0 [total] : 0 func: func_a [binary-bytes] : 16 [total] : 8 [vars] : 0 - Block : 1 - Call : 7 + block : 1 + call : 7 func: func_b [binary-bytes] : 22 [total] : 11 [vars] : 0 - Block : 1 - Call : 10 + block : 1 + call : 10 func: func_c [binary-bytes] : 32 [total] : 16 [vars] : 0 - Block : 1 - Call : 15 + block : 1 + call : 15 export: a (func_a) - [removable-bytes-without-it]: 58 + [removable-bytes-without-it]: 72 [total] : 0 export: b (func_b) [removable-bytes-without-it]: 18 @@ -178,19 +174,18 @@ ) ) global + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 0 [imports] : 1 - [tables] : 0 - [tags] : 0 [total] : 0 func: func_a [binary-bytes] : 12 [total] : 6 [vars] : 0 - Block : 1 - Call : 5 + block : 1 + call : 5 export: a (func_a) [removable-bytes-without-it]: 7 [total] : 0 @@ -211,19 +206,18 @@ ) ) global + [events] : 0 [exports] : 0 [funcs] : 1 [globals] : 0 [imports] : 1 - [tables] : 0 - [tags] : 0 [total] : 0 func: func_a [binary-bytes] : 12 [total] : 6 [vars] : 0 - Block : 1 - Call : 5 + block : 1 + call : 5 start: func_a [removable-bytes-without-it]: 57 [total] : 0 @@ -240,24 +234,23 @@ ) ) global + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 1 [imports] : 1 - [tables] : 0 - [tags] : 0 [total] : 1 - GlobalGet : 1 + global.get : 1 func: 0 [binary-bytes] : 4 [total] : 1 [vars] : 0 - GlobalGet : 1 + global.get : 1 export: stackSave (0) - [removable-bytes-without-it]: 62 + [removable-bytes-without-it]: 56 [total] : 0 (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "STACKTOP" (global $gimport$0 i32)) (global $global$0 (mut i32) (global.get $gimport$0)) (export "stackSave" (func $0)) diff -Nru binaryen-108/test/passes/fuzz-exec_all-features.txt binaryen-99/test/passes/fuzz-exec_all-features.txt --- binaryen-108/test/passes/fuzz-exec_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fuzz-exec_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -71,9 +71,9 @@ [trap final > memory: 18446744073709551512 > 65514] (module (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) - (type $none_=>_none (func)) (import "fuzzing-support" "log-i32" (func $fimport$0 (param i32))) (memory $0 (shared 1 1)) (export "unaligned_load" (func $0)) @@ -139,11 +139,9 @@ [fuzz-exec] calling oob_notify [trap final > memory: 18446744073709551512 > 65514] [fuzz-exec] comparing aligned_for_size -[fuzz-exec] comparing oob_notify [fuzz-exec] comparing unaligned_load [fuzz-exec] comparing unaligned_load_offset [fuzz-exec] comparing unaligned_notify -[fuzz-exec] comparing wrap_cmpxchg [fuzz-exec] calling unsigned_2_bytes [fuzz-exec] note result: unsigned_2_bytes => 65535 (module @@ -164,8 +162,8 @@ [fuzz-exec] calling rmw-reads-modifies-and-writes [LoggingExternalInterface logging 0] (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (import "fuzzing-support" "log-i32" (func $fimport$0 (param i32))) (memory $0 (shared 1 1)) (export "rmw-reads-modifies-and-writes" (func $0)) @@ -185,12 +183,11 @@ ) [fuzz-exec] calling rmw-reads-modifies-and-writes [LoggingExternalInterface logging 0] -[fuzz-exec] comparing rmw-reads-modifies-and-writes [fuzz-exec] calling rmw-reads-modifies-and-writes-asymmetrical [LoggingExternalInterface logging 214] (module - (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (import "fuzzing-support" "log-i32" (func $fimport$0 (param i32))) (memory $0 (shared 1 1)) (export "rmw-reads-modifies-and-writes-asymmetrical" (func $0)) @@ -210,17 +207,15 @@ ) [fuzz-exec] calling rmw-reads-modifies-and-writes-asymmetrical [LoggingExternalInterface logging 214] -[fuzz-exec] comparing rmw-reads-modifies-and-writes-asymmetrical [fuzz-exec] calling func -[fuzz-exec] note result: func => funcref +[fuzz-exec] note result: func => funcref(func) (module (type $none_=>_funcref (func (result funcref))) - (elem declare func $func) (export "func" (func $func)) (func $func (result funcref) (ref.func $func) ) ) [fuzz-exec] calling func -[fuzz-exec] note result: func => funcref +[fuzz-exec] note result: func => funcref(func) [fuzz-exec] comparing func diff -Nru binaryen-108/test/passes/fuzz-exec_O.txt binaryen-99/test/passes/fuzz-exec_O.txt --- binaryen-108/test/passes/fuzz-exec_O.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fuzz-exec_O.txt 2021-01-07 20:01:06.000000000 +0000 @@ -3,8 +3,8 @@ [fuzz-exec] calling func_1 [trap final > memory: 18446744073709551615 > 65514] (module - (type $none_=>_i64 (func (result i64))) (type $none_=>_i32 (func (result i32))) + (type $none_=>_i64 (func (result i64))) (memory $0 1 1) (export "func_0" (func $func_0)) (export "func_1" (func $func_1)) diff -Nru binaryen-108/test/passes/fuzz_metrics_noprint.bin.txt binaryen-99/test/passes/fuzz_metrics_noprint.bin.txt --- binaryen-108/test/passes/fuzz_metrics_noprint.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/fuzz_metrics_noprint.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,32 +1,30 @@ total - [exports] : 39 - [funcs] : 50 + [events] : 0 + [exports] : 51 + [funcs] : 67 [globals] : 7 [imports] : 4 [memory-data] : 4 - [table-data] : 17 - [tables] : 1 - [tags] : 0 - [total] : 3442 - [vars] : 108 - Binary : 299 - Block : 495 - Break : 110 - Call : 193 - CallIndirect : 29 - Const : 650 - Drop : 48 - GlobalGet : 295 - GlobalSet : 131 - If : 183 - Load : 79 - LocalGet : 199 - LocalSet : 153 - Loop : 71 - Nop : 45 - RefFunc : 17 - Return : 155 - Select : 25 - Store : 29 - Unary : 235 - Unreachable : 1 + [table-data] : 18 + [total] : 4870 + [vars] : 236 + binary : 368 + block : 699 + break : 191 + call : 300 + call_indirect : 39 + const : 847 + drop : 91 + global.get : 403 + global.set : 171 + if : 260 + load : 85 + local.get : 374 + local.set : 251 + loop : 111 + nop : 86 + return : 187 + select : 30 + store : 36 + unary : 340 + unreachable : 1 diff -Nru binaryen-108/test/passes/generate-dyncalls.txt binaryen-99/test/passes/generate-dyncalls.txt --- binaryen-108/test/passes/generate-dyncalls.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/generate-dyncalls.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,38 @@ +(module + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i64 (func (param i32) (result i64))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) + (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) + (table $0 2 2 funcref) + (elem (i32.const 0) $f1 $f2) + (export "dynCall_i" (func $dynCall_i)) + (export "dynCall_ji" (func $dynCall_ji)) + (export "dynCall_vii" (func $dynCall_vii)) + (func $f1 (result i32) + (i32.const 1024) + ) + (func $f2 (param $0 i32) (result i64) + (i64.const 42) + ) + (func $dynCall_i (param $fptr i32) (result i32) + (call_indirect (type $none_=>_i32) + (local.get $fptr) + ) + ) + (func $dynCall_ji (param $fptr i32) (param $0 i32) (result i64) + (call_indirect (type $i32_=>_i64) + (local.get $0) + (local.get $fptr) + ) + ) + (func $dynCall_vii (param $fptr i32) (param $0 i32) (param $1 i32) + (call_indirect (type $i32_i32_=>_none) + (local.get $0) + (local.get $1) + (local.get $fptr) + ) + ) +) diff -Nru binaryen-108/test/passes/generate-dyncalls.wast binaryen-99/test/passes/generate-dyncalls.wast --- binaryen-108/test/passes/generate-dyncalls.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/generate-dyncalls.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,11 @@ +(module + (import "env" "invoke_vii" (func $invoke_vii (param i32 i32 i32))) + (func $f1 (result i32) + (i32.const 1024) + ) + (func $f2 (param i32) (result i64) + (i64.const 42) + ) + (table 2 2 funcref) + (elem (i32.const 0) $f1 $f2) +) diff -Nru binaryen-108/test/passes/generate-i64-dyncalls.txt binaryen-99/test/passes/generate-i64-dyncalls.txt --- binaryen-108/test/passes/generate-i64-dyncalls.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/generate-i64-dyncalls.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,20 @@ +(module + (type $i32_=>_i64 (func (param i32) (result i64))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) + (table $0 2 2 funcref) + (elem (i32.const 0) $f1 $f2) + (export "dynCall_ji" (func $dynCall_ji)) + (func $f1 (result i32) + (i32.const 1024) + ) + (func $f2 (param $0 i32) (result i64) + (i64.const 42) + ) + (func $dynCall_ji (param $fptr i32) (param $0 i32) (result i64) + (call_indirect (type $i32_=>_i64) + (local.get $0) + (local.get $fptr) + ) + ) +) diff -Nru binaryen-108/test/passes/generate-i64-dyncalls.wast binaryen-99/test/passes/generate-i64-dyncalls.wast --- binaryen-108/test/passes/generate-i64-dyncalls.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/generate-i64-dyncalls.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,10 @@ +(module + (func $f1 (result i32) + (i32.const 1024) + ) + (func $f2 (param i32) (result i64) + (i64.const 42) + ) + (table 2 2 funcref) + (elem (i32.const 0) $f1 $f2) +) diff -Nru binaryen-108/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt binaryen-99/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt --- binaryen-108/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,50 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (event $e0 (attr 0) (param i32)) + (func $eh + (local $exn exnref) + try + i32.const 0 + throw $e0 + catch + + local.set $exn + block $l0 (result i32) + local.get $exn + br_on_exn $l0 $e0 + rethrow + end + drop + end + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (event $e0 (attr 0) (param i32)) + (func $eh (; has Stack IR ;) + (local $exn exnref) + (try + (do + (throw $e0 + (i32.const 0) + ) + ) + (catch + (local.set $exn + (pop exnref) + ) + (drop + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e0 + (local.get $exn) + ) + ) + ) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast binaryen-99/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast --- binaryen-108/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,21 @@ +(module + (event $e0 (attr 0) (param i32)) + + (func $eh (local $exn exnref) + (try + (do + (throw $e0 (i32.const 0)) + ) + (catch + (local.set $exn (pop exnref)) + (drop + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e0 (local.get $exn)) + ) + ) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt binaryen-99/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt --- binaryen-108/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/generate-stack-ir_optimize-stack-ir_print-stack-ir_optimize-level=3.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,14 +1,14 @@ (module - (type $FUNCSIG$v (func)) - (type $5 (func (result i32))) - (type $6 (func (param i32) (result i32))) - (type $FUNCSIG$vf (func (param f32))) - (type $4 (func (result f64))) - (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) - (type $FUNCSIG$id (func (param f64) (result i32))) - (type $7 (func (param f64) (result f64))) - (type $8 (func (result i64))) - (type $9 (func (param i32 i64))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $f32_=>_none (func (param f32))) + (type $none_=>_f64 (func (result f64))) + (type $f64_f64_=>_f64 (func (param f64 f64) (result f64))) + (type $i32_i64_=>_none (func (param i32 i64))) + (type $f64_=>_i32 (func (param f64) (result i32))) + (type $none_=>_i64 (func (result i64))) + (type $f64_=>_f64 (func (param f64) (result f64))) (import "env" "_emscripten_asm_const_vi" (func $_emscripten_asm_const_vi)) (import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32))) (import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64))) @@ -276,7 +276,7 @@ i32.and i32.const 8 i32.add - call_indirect $0 (type $f32_=>_none) + call_indirect (type $f32_=>_none) ) (func $cneg (param $x f32) local.get $x @@ -285,7 +285,7 @@ i32.and i32.const 8 i32.add - call_indirect $0 (type $f32_=>_none) + call_indirect (type $f32_=>_none) ) (func $___syscall_ret (local $$0 i32) @@ -629,16 +629,16 @@ ) ) (module - (type $FUNCSIG$v (func)) - (type $5 (func (result i32))) - (type $6 (func (param i32) (result i32))) - (type $FUNCSIG$vf (func (param f32))) - (type $4 (func (result f64))) - (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) - (type $FUNCSIG$id (func (param f64) (result i32))) - (type $7 (func (param f64) (result f64))) - (type $8 (func (result i64))) - (type $9 (func (param i32 i64))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $f32_=>_none (func (param f32))) + (type $none_=>_f64 (func (result f64))) + (type $f64_f64_=>_f64 (func (param f64 f64) (result f64))) + (type $i32_i64_=>_none (func (param i32 i64))) + (type $f64_=>_i32 (func (param f64) (result i32))) + (type $none_=>_i64 (func (result i64))) + (type $f64_=>_f64 (func (param f64) (result f64))) (import "env" "_emscripten_asm_const_vi" (func $_emscripten_asm_const_vi)) (import "asm2wasm" "f64-to-int" (func $f64-to-int (param f64) (result i32))) (import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64))) @@ -1009,7 +1009,7 @@ (local.get $x) ) ) - (call_indirect (type $FUNCSIG$vf) + (call_indirect (type $f32_=>_none) (local.get $x) (i32.add (i32.and @@ -1022,7 +1022,7 @@ ) ) (func $cneg (; has Stack IR ;) (param $x f32) - (call_indirect (type $FUNCSIG$vf) + (call_indirect (type $f32_=>_none) (local.get $x) (i32.add (i32.and diff -Nru binaryen-108/test/passes/ignore_missing_func_dwarf.bin.txt binaryen-99/test/passes/ignore_missing_func_dwarf.bin.txt --- binaryen-108/test/passes/ignore_missing_func_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/ignore_missing_func_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "\nvoid used(int x) {\n x++;\n x--;\n return x;\n}\n\nvoid unused(int x) {\n x >>= 1;\n x <<= 1;\n return x;\n}\n\nint main() {\n return used(42);\n}\n\00") @@ -823,8 +823,8 @@ 00000010 (module (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "\nvoid used(int x) {\n x++;\n x--;\n return x;\n}\n\nvoid unused(int x) {\n x >>= 1;\n x <<= 1;\n return x;\n}\n\nint main() {\n return used(42);\n}\n\00") diff -Nru binaryen-108/test/passes/inlined_to_start_dwarf.bin.txt binaryen-99/test/passes/inlined_to_start_dwarf.bin.txt --- binaryen-108/test/passes/inlined_to_start_dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/inlined_to_start_dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -409,16 +409,16 @@ 00000000 00000013 0000001b 00000000 (module - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "\00\00\00\00") + (table $0 1 1 funcref) (global $global$0 (mut i32) (i32.const 5243920)) (global $global$1 i32 (i32.const 1028)) - (table $0 1 1 funcref) (export "__indirect_function_table" (table $0)) (export "__wasm_call_ctors" (func $__wasm_call_ctors)) (export "main" (func $main)) diff -Nru binaryen-108/test/passes/inline-main.txt binaryen-99/test/passes/inline-main.txt --- binaryen-108/test/passes/inline-main.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inline-main.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,69 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) + (func $main (param $0 i32) (param $1 i32) (result i32) + (block $__inlined_func$__original_main (result i32) + (i32.const 0) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) + (func $main (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) +) +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (export "main" (func $main)) + (func $main (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) + (func $main (param $0 i32) (param $1 i32) (result i32) + (drop + (call $__original_main) + ) + (call $__original_main) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (func $__original_main (result i32) + (i32.const 0) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (import "env" "main" (func $main (param i32 i32) (result i32))) + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (import "env" "original_main" (func $__original_main (result i32))) + (export "main" (func $main)) + (func $main (param $0 i32) (param $1 i32) (result i32) + (call $__original_main) + ) +) diff -Nru binaryen-108/test/passes/inline-main.wast binaryen-99/test/passes/inline-main.wast --- binaryen-108/test/passes/inline-main.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inline-main.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,53 @@ +(module + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) + (func $main (param $0 i32) (param $1 i32) (result i32) + (call $__original_main) + ) +) +(module + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) + (func $main (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) +) +(module + (export "main" (func $main)) + (func $main (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) +) +(module + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) + (func $main (param $0 i32) (param $1 i32) (result i32) + (drop (call $__original_main)) + (call $__original_main) + ) +) +(module + (func $__original_main (result i32) + (i32.const 0) + ) +) +(module + (import "env" "main" (func $main (param i32 i32) (result i32))) + (export "main" (func $main)) + (func $__original_main (result i32) + (i32.const 0) + ) +) +(module + (import "env" "original_main" (func $__original_main (result i32))) + (export "main" (func $main)) + (func $main (param $0 i32) (param $1 i32) (result i32) + (call $__original_main) + ) +) diff -Nru binaryen-108/test/passes/inlining_all-features.txt binaryen-99/test/passes/inlining_all-features.txt --- binaryen-108/test/passes/inlining_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,88 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $none_=>_funcref (func (result funcref))) + (event $e (attr 0) (param i32)) + (export "ref_func_test" (func $ref_func_test)) + (func $foo + (nop) + ) + (func $ref_func_test (result funcref) + (block + (block $__inlined_func$foo + (nop) + ) + ) + (ref.func $foo) + ) + (func $br_on_exn_name_uniquify_test + (local $exn exnref) + (local $1 exnref) + (drop + (block $l (result i32) + (block + (block $__inlined_func$func_inner + (local.set $1 + (ref.null exn) + ) + (drop + (block $l0 (result i32) + (drop + (br_on_exn $l0 $e + (local.get $1) + ) + ) + (i32.const 0) + ) + ) + ) + ) + (drop + (br_on_exn $l $e + (local.get $exn) + ) + ) + (i32.const 0) + ) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (global $global$0 (mut funcref) (ref.func $0)) + (func $0 (result i32) + (i32.const 1337) + ) + (func $1 (result i32) + (block $__inlined_func$0 (result i32) + (i32.const 1337) + ) + ) +) +(module + (type $none_=>_none (func)) + (start $0) + (func $0 + (nop) + ) + (func $1 + (block $__inlined_func$0 + (nop) + ) + ) +) +(module + (type $none_=>_none (func)) + (export "func_36_invoker" (func $1)) + (func $1 + (block $__inlined_func$0 + (block + (call_ref + (ref.null $none_=>_none) + ) + (br $__inlined_func$0) + ) + (br $__inlined_func$0) + ) + ) +) diff -Nru binaryen-108/test/passes/inlining_all-features.wast binaryen-99/test/passes/inlining_all-features.wast --- binaryen-108/test/passes/inlining_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,73 @@ +(module + (export "ref_func_test" (func $ref_func_test)) + ;; $foo should not be removed after being inlined, because there is 'ref.func' + ;; instruction that refers to it + (func $foo) + (func $ref_func_test (result funcref) + (call $foo) + (ref.func $foo) + ) + + ;; Tests if UniqueNameMapper works correctly for br_on_exn labels. + ;; We have $l in br_on_exns in both $func_inner and $br_on_name_uniquify_test, + ;; which should become unique names respectively after inlining. + (event $e (attr 0) (param i32)) + (func $func_inner + (local $exn exnref) + (drop + (block $l (result i32) + (drop + (br_on_exn $l $e (local.get $exn)) + ) + (i32.const 0) + ) + ) + ) + (func $br_on_exn_name_uniquify_test + (local $exn exnref) + (drop + (block $l (result i32) + (call $func_inner) + (drop + (br_on_exn $l $e (local.get $exn)) + ) + (i32.const 0) + ) + ) + ) +) +(module + ;; a function reference in a global's init should be noticed, and prevent us + ;; from removing an inlined function + (global $global$0 (mut funcref) (ref.func $0)) + (func $0 (result i32) + (i32.const 1337) + ) + (func $1 (result i32) + (call $0) + ) +) +(module + ;; a function reference in the start should be noticed, and prevent us + ;; from removing an inlined function + (start $0) + (func $0 + (nop) + ) + (func $1 + (call $0) + ) +) +;; inline a return_call_ref +(module + (type $none_=>_none (func)) + (export "func_36_invoker" (func $1)) + (func $0 + (return_call_ref + (ref.null $none_=>_none) + ) + ) + (func $1 + (call $0) + ) +) diff -Nru binaryen-108/test/passes/inlining_enable-tail-call.txt binaryen-99/test/passes/inlining_enable-tail-call.txt --- binaryen-108/test/passes/inlining_enable-tail-call.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining_enable-tail-call.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,418 @@ +(module + (type $none_=>_none (func)) + (table $0 1 1 funcref) + (elem (i32.const 0) $tabled) + (export "user" (func $user)) + (export "exported" (func $exported)) + (func $user + (local $x i32) + (local $y f64) + (local $2 f32) + (local $3 i64) + (local $4 f32) + (local $5 i64) + (local $6 f32) + (block + (block $__inlined_func$exported + (nop) + ) + ) + (block + (block $__inlined_func$tabled + (nop) + ) + ) + (block + (block $__inlined_func$multi + (nop) + ) + ) + (block + (block $__inlined_func$multi0 + (nop) + ) + ) + (block + (block $__inlined_func$ok + (drop + (i32.const 1) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$int (result i32) + (i32.const 2) + ) + ) + ) + (drop + (block (result f64) + (block $__inlined_func$double (result f64) + (f64.const 3.14159) + ) + ) + ) + (local.set $x + (block (result i32) + (block $__inlined_func$int2 (result i32) + (i32.const 112) + ) + ) + ) + (local.set $y + (block (result f64) + (block $__inlined_func$double2 (result f64) + (f64.const 113.14159) + ) + ) + ) + (block + (block $__inlined_func$with-local + (local.set $2 + (f32.const 0) + ) + (local.set $2 + (f32.const 2.1418280601501465) + ) + ) + ) + (block + (block $__inlined_func$with-local2 + (local.set $3 + (i64.const 0) + ) + (local.set $3 + (i64.const 4) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$return (result i32) + (br $__inlined_func$return + (i32.const 5) + ) + ) + ) + ) + (block + (block $__inlined_func$multipass + (block + (block + (block $__inlined_func$multipass2 + (drop + (i32.const 6) + ) + ) + ) + ) + ) + ) + (block + (block $__inlined_func$param + (local.set $4 + (f32.const 12.34000015258789) + ) + (local.set $5 + (i64.const 890005350012) + ) + (local.set $6 + (f32.const 0) + ) + (block + (drop + (local.get $4) + ) + (drop + (local.get $5) + ) + (drop + (local.get $6) + ) + ) + ) + ) + ) + (func $exported + (nop) + ) + (func $recursive + (call $recursive) + ) + (func $tabled + (nop) + ) + (func $cycle1 + (block $__inlined_func$cycle2 + (block + (call $cycle1) + ) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (func $child (param $0 i32) (result i32) + (i32.const 1234) + ) + (func $parent (result i32) + (call $child + (unreachable) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $f32_i32_=>_i32 (func (param f32 i32) (result i32))) + (memory $0 1 1) + (global $hangLimit (mut i32) (i32.const 25)) + (export "hangLimitInitializer" (func $hangLimitInitializer)) + (func $func_4 (param $0 f32) (param $1 i32) (result i32) + (local $2 i64) + (local $3 f64) + (local $4 f32) + (local $5 i32) + (local $6 i32) + (local $7 f64) + (local $8 i32) + (loop $label$0 (result i32) + (block $block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 54) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.eqz + (if (result i32) + (i32.const 1) + (if (result i32) + (i32.eqz + (block (result i32) + (block $__inlined_func$func_3 (result i32) + (local.set $8 + (i32.const 0) + ) + (select + (local.get $8) + (local.tee $8 + (i32.const -1) + ) + (i32.const 1) + ) + ) + ) + ) + (br $label$0) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + ) + (func $hangLimitInitializer + (global.set $hangLimit + (i32.const 25) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (table $0 10 funcref) + (func $0 + (block $__inlined_func$1 + (call_indirect (type $i32_=>_none) + (if (result i32) + (i32.const 0) + (unreachable) + (unreachable) + ) + (i32.const 1) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (func $1 + (block $__inlined_func$0 + (block $label$1 + (br_table $label$1 $label$1 + (i32.const 0) + ) + ) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (func $0 (result i32) + (return + (block $__inlined_func$1 (result i32) + (i32.const 42) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (func $0 + (local $0 i32) + (block + (block $__inlined_func$1 + (local.set $0 + (i32.const 42) + ) + (drop + (local.get $0) + ) + ) + (return) + ) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (func $0 (result i32) + (local $0 i32) + (return + (block $__inlined_func$1 (result i32) + (local.set $0 + (i32.const 42) + ) + (local.get $0) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (func $0 + (drop + (block (result i32) + (block $__inlined_func$1 (result i32) + (block + (br $__inlined_func$1 + (block (result i32) + (block $__inlined_func$2 (result i32) + (i32.const 42) + ) + ) + ) + ) + ) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (func $0 + (local $0 i32) + (block $__inlined_func$1 + (block + (block + (block + (block $__inlined_func$2 + (local.set $0 + (i32.const 42) + ) + (drop + (local.get $0) + ) + ) + ) + (br $__inlined_func$1) + ) + ) + (br $__inlined_func$1) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) + (table $0 10 funcref) + (func $0 + (drop + (block (result i32) + (block $__inlined_func$1 (result i32) + (br $__inlined_func$1 + (call_indirect (type $i32_=>_i32) + (i32.const 42) + (i32.const 0) + ) + ) + ) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (table $0 10 funcref) + (func $0 + (block $__inlined_func$1 + (block + (call_indirect (type $i32_=>_none) + (i32.const 42) + (i32.const 0) + ) + (br $__inlined_func$1) + ) + (br $__inlined_func$1) + ) + ) +) +(module + (type $none_=>_none (func)) + (memory $0 1 1) + (global $global$0 (mut i32) (i32.const 10)) + (export "func_102_invoker" (func $19)) + (func $19 + (block + (block + (block $__inlined_func$13 + (block + (if + (global.get $global$0) + (unreachable) + ) + (block + (block + (block $__inlined_func$2 + (block + (if + (global.get $global$0) + (br $__inlined_func$2) + ) + (global.set $global$0 + (i32.const 1) + ) + ) + ) + (br $__inlined_func$13) + ) + ) + ) + (br $__inlined_func$13) + ) + ) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/inlining_enable-tail-call.wast binaryen-99/test/passes/inlining_enable-tail-call.wast --- binaryen-108/test/passes/inlining_enable-tail-call.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining_enable-tail-call.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,288 @@ +(module + (table 1 1 funcref) + (elem (i32.const 0) $tabled) + (func $user (export "user") + (local $x i32) + (local $y f64) + (call $exported) + (call $tabled) + (call $multi) + (call $multi) + (call $ok) + (drop (call $int)) + (drop (call $double)) + (local.set $x (call $int2)) + (local.set $y (call $double2)) + (call $with-local) + (call $with-local2) + (drop (call $return)) + (call $multipass) + (call $param (f32.const 12.34) (i64.const 890005350012)) + ) + (func $exported (export "exported") + (nop) + ) + (func $recursive + (call $recursive) + ) + (func $tabled + (nop) + ) + (func $cycle1 + (call $cycle2) + ) + (func $cycle2 + (call $cycle1) + ) + (func $multi + (nop) + ) + (func $ok + (drop (i32.const 1)) + ) + (func $int (result i32) + (i32.const 2) + ) + (func $double (result f64) + (f64.const 3.14159) + ) + (func $int2 (result i32) + (i32.const 112) + ) + (func $double2 (result f64) + (f64.const 113.14159) + ) + (func $with-local + (local $x f32) + (local.set $x (f32.const 2.141828)) + ) + (func $with-local2 + (local $y i64) + (local.set $y (i64.const 4)) + ) + (func $return (result i32) + (return (i32.const 5)) + ) + (func $multipass + (call $multipass2) + ) + (func $multipass2 + (drop (i32.const 6)) + ) + (func $param (param $x f32) (param $y i64) + (local $z f32) + (drop (local.get $x)) + (drop (local.get $y)) + (drop (local.get $z)) + ) +) +(module + (func $child (param i32) (result i32) + (i32.const 1234) + ) + (func $parent (result i32) + (call $child + (unreachable) ;; call is not performed, no sense to inline + ) + ) +) +(module + (global $hangLimit (mut i32) (i32.const 25)) + (memory $0 1 1) + (export "hangLimitInitializer" (func $hangLimitInitializer)) + (func $func_3 (result i32) + (local $0 i32) + (select + (local.get $0) ;; we depend on the zero-init value here, so it must be set when inlining! + (local.tee $0 + (i32.const -1) + ) + (i32.const 1) + ) + ) + (func $func_4 (param $0 f32) (param $1 i32) (result i32) + (local $2 i64) + (local $3 f64) + (local $4 f32) + (local $5 i32) + (local $6 i32) + (local $7 f64) + (loop $label$0 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 54) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.eqz + (if (result i32) + (i32.const 1) + (if (result i32) + (i32.eqz + (call $func_3) + ) + (br $label$0) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + ) + (func $hangLimitInitializer + (global.set $hangLimit + (i32.const 25) + ) + ) +) +(module + (type $T (func (param i32))) + (table 10 funcref) + (func $0 + (call $1) + ) + (func $1 + (call_indirect (type $T) + (if (result i32) ;; if copy must preserve the forced type + (i32.const 0) + (unreachable) + (unreachable) + ) + (i32.const 1) + ) + ) +) +(module + (func $0 + (block $label$1 ;; copy this name + (br_table $label$1 $label$1 + (i32.const 0) + ) + ) + ) + (func $1 + (call $0) + ) +) +(module + (func $0 (result i32) + (return_call $1) + ) + (func $1 (result i32) + (i32.const 42) + ) +) +(module + (func $0 + (return_call $1 + (i32.const 42) + ) + ) + (func $1 (param i32) + (drop + (local.get 0) + ) + ) +) +(module + (func $0 (result i32) + (return_call $1 + (i32.const 42) + ) + ) + (func $1 (param i32) (result i32) + (local.get 0) + ) +) +(module + (func $0 + (drop + (call $1) + ) + ) + (func $1 (result i32) + (return_call $2) + ) + (func $2 (result i32) + (i32.const 42) + ) +) +(module + (func $0 + (call $1) + ) + (func $1 + (return_call $2 + (i32.const 42) + ) + ) + (func $2 (param i32) + (drop + (local.get 0) + ) + ) +) +(module + (type $T (func (param i32) (result i32))) + (table 10 funcref) + (func $0 + (drop + (call $1) + ) + ) + (func $1 (result i32) + (return_call_indirect (type $T) + (i32.const 42) + (i32.const 0) + ) + ) +) +(module + (type $T (func (param i32))) + (table 10 funcref) + (func $0 + (call $1) + ) + (func $1 + (return_call_indirect (type $T) + (i32.const 42) + (i32.const 0) + ) + ) +) +(module + (type $6 (func)) + (memory $0 1 1) + (global $global$0 (mut i32) (i32.const 10)) + (export "func_102_invoker" (func $19)) + (func $2 (; 2 ;) (type $6) + (if + (global.get $global$0) + (return) + ) + (global.set $global$0 + (i32.const 1) + ) + ) + (func $13 (; 13 ;) (type $6) + (if + (global.get $global$0) + (unreachable) + ) + (return_call $2) + ) + (func $19 (; 19 ;) (type $6) + (call $13) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/inlining_optimize-level=3.txt binaryen-99/test/passes/inlining_optimize-level=3.txt --- binaryen-108/test/passes/inlining_optimize-level=3.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining_optimize-level=3.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,156 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (table $0 1 1 funcref) + (elem (i32.const 0) $no-loops-but-one-use-but-tabled) + (export "yes" (func $yes)) + (export "no-loops-but-one-use-but-exported" (func $no-loops-but-one-use-but-exported)) + (func $yes (result i32) + (i32.const 1) + ) + (func $no-tooBig (result i32) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (i32.const 1) + ) + (func $no-loops-but-one-use-but-exported (result i32) + (loop $loop-in (result i32) + (i32.const 1) + ) + ) + (func $no-loops-but-one-use-but-tabled (result i32) + (loop $loop-in (result i32) + (i32.const 1) + ) + ) + (func $intoHere + (drop + (block (result i32) + (block $__inlined_func$yes (result i32) + (i32.const 1) + ) + ) + ) + (drop + (call $no-tooBig) + ) + (drop + (block (result i32) + (block (result i32) + (block $__inlined_func$no-calls (result i32) + (block (result i32) + (block $__inlined_func$yes0 (result i32) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (block (result i32) + (block $__inlined_func$no-calls1 (result i32) + (block (result i32) + (block $__inlined_func$yes2 (result i32) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (block (result i32) + (block $__inlined_func$yes-calls-but-one-use (result i32) + (block (result i32) + (block $__inlined_func$yes3 (result i32) + (i32.const 1) + ) + ) + ) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$no-loops (result i32) + (loop $loop-in (result i32) + (i32.const 1) + ) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$no-loops0 (result i32) + (loop $loop-in1 (result i32) + (i32.const 1) + ) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$yes-loops-but-one-use (result i32) + (loop $loop-in2 (result i32) + (i32.const 1) + ) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$no-loops-but-one-use-but-exported (result i32) + (loop $loop-in3 (result i32) + (i32.const 1) + ) + ) + ) + ) + (drop + (block (result i32) + (block $__inlined_func$no-loops-but-one-use-but-tabled (result i32) + (loop $loop-in4 (result i32) + (i32.const 1) + ) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/inlining_optimize-level=3.wast binaryen-99/test/passes/inlining_optimize-level=3.wast --- binaryen-108/test/passes/inlining_optimize-level=3.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining_optimize-level=3.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,58 @@ +(module + (export "yes" (func $yes)) + (export "no-loops-but-one-use-but-exported" (func $no-loops-but-one-use-but-exported)) + (table 1 1 funcref) + (elem (i32.const 0) $no-loops-but-one-use-but-tabled) + + (func $yes (result i32) ;; inlinable: small, lightweight, even with multi uses and a global use, ok when opt-level=3 + (i32.const 1) + ) + (func $no-tooBig (result i32) + (nop) (nop) (nop) (nop) (nop) (nop) + (nop) (nop) (nop) (nop) (nop) (nop) + (nop) (nop) (nop) (nop) (nop) (nop) + (nop) (nop) (nop) (nop) (nop) (nop) + (nop) (nop) (nop) (nop) (nop) (nop) + (nop) (nop) (nop) (nop) (nop) (nop) + (i32.const 1) + ) + (func $no-calls (result i32) + (call $yes) + ) + (func $yes-calls-but-one-use (result i32) + (call $yes) + ) + (func $no-loops (result i32) + (loop (result i32) + (i32.const 1) + ) + ) + (func $yes-loops-but-one-use (result i32) + (loop (result i32) + (i32.const 1) + ) + ) + (func $no-loops-but-one-use-but-exported (result i32) + (loop (result i32) + (i32.const 1) + ) + ) + (func $no-loops-but-one-use-but-tabled (result i32) + (loop (result i32) + (i32.const 1) + ) + ) + (func $intoHere + (drop (call $yes)) + (drop (call $no-tooBig)) + (drop (call $no-calls)) + (drop (call $no-calls)) + (drop (call $yes-calls-but-one-use)) + (drop (call $no-loops)) + (drop (call $no-loops)) + (drop (call $yes-loops-but-one-use)) + (drop (call $no-loops-but-one-use-but-exported)) + (drop (call $no-loops-but-one-use-but-tabled)) + ) +) + diff -Nru binaryen-108/test/passes/inlining-optimizing_enable-threads.txt binaryen-99/test/passes/inlining-optimizing_enable-threads.txt --- binaryen-108/test/passes/inlining-optimizing_enable-threads.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining-optimizing_enable-threads.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,95 @@ +(module + (type $none_=>_none (func)) + (table $0 1 1 funcref) + (elem (i32.const 0) $tabled) + (export "user" (func $user)) + (export "exported" (func $exported)) + (export "exported_small" (func $exported_small)) + (func $user + (call $exported) + (call $tabled) + (call $multi) + (call $multi) + ) + (func $exported + (nop) + (nop) + ) + (func $exported_small + (nop) + ) + (func $recursive + (call $recursive) + ) + (func $tabled + (nop) + (nop) + ) + (func $cycle1 + (call $cycle1) + ) + (func $multi + (nop) + (nop) + ) +) +(module + (type $none_=>_i32 (func (result i32))) + (func $main (result i32) + (unreachable) + ) +) +(module + (type $none_=>_i64 (func (result i64))) + (memory $0 (shared 1 1)) + (func $1 (result i64) + (i32.atomic.store16 + (i32.const 0) + (i32.const 0) + ) + (i64.const 0) + ) +) +(module + (type $none_=>_none (func)) + (func $main + (call $one) + (call $one) + ) + (func $one + (call $one) + ) +) +(module + (type $none_=>_none (func)) + (func $main + (call $two) + (call $two) + ) + (func $two + (call $two) + ) +) +(module + (type $none_=>_none (func)) + (memory $0 17) + (table $0 89 89 funcref) + (start $1) + (func $1 + (i32.store + (i32.const 4) + (i32.const 0) + ) + (i32.store + (i32.const 56) + (i32.const 0) + ) + (i64.store + (i32.const 49) + (i64.load + (i32.const 24) + ) + ) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/inlining-optimizing_enable-threads.wast binaryen-99/test/passes/inlining-optimizing_enable-threads.wast --- binaryen-108/test/passes/inlining-optimizing_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining-optimizing_enable-threads.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,180 @@ +(module + (table 1 1 funcref) + (elem (i32.const 0) $tabled) + (func $user (export "user") + (local $x i32) + (local $y f64) + (call $exported) + (call $exported_small) + (call $tabled) + (call $tabled_small) + (call $multi) + (call $multi) + (call $multi_small) + (call $multi_small) + (call $ok) + (drop (call $int)) + (drop (call $double)) + (local.set $x (call $int2)) + (local.set $y (call $double2)) + (call $with-local) + (call $with-local2) + (drop (call $return)) + (call $multipass) + (call $param (f32.const 12.34) (i64.const 890005350012)) + ) + (func $exported (export "exported") + (nop) + (nop) + ) + (func $exported_small (export "exported_small") + (nop) + ) + (func $recursive + (call $recursive) + ) + (func $tabled + (nop) + (nop) + ) + (func $tabled_small + (nop) + ) + (func $cycle1 + (call $cycle2) + ) + (func $cycle2 + (call $cycle1) + ) + (func $multi + (nop) + (nop) + ) + (func $multi_small + (nop) + ) + (func $ok + (drop (i32.const 1)) + ) + (func $int (result i32) + (i32.const 2) + ) + (func $double (result f64) + (f64.const 3.14159) + ) + (func $int2 (result i32) + (i32.const 112) + ) + (func $double2 (result f64) + (f64.const 113.14159) + ) + (func $with-local + (local $x f32) + (local.set $x (f32.const 2.141828)) + ) + (func $with-local2 + (local $y i64) + (local.set $y (i64.const 4)) + ) + (func $return (result i32) + (return (i32.const 5)) + ) + (func $multipass + (call $multipass2) + ) + (func $multipass2 + (drop (i32.const 6)) + ) + (func $param (param $x f32) (param $y i64) + (local $z f32) + (drop (local.get $x)) + (drop (local.get $y)) + (drop (local.get $z)) + ) +) +(module + (func $main (result i32) + (call $func_51) + (i32.const 0) + ) + (func $func_51 + (unreachable) ;; void function but having unreachable body, when inlined, type must be fixed + ) +) +(module + (memory $0 (shared 1 1)) + (func $0 (result i32) + (i32.atomic.store16 + (i32.const 0) + (i32.const 0) + ) + (i32.const 1) + ) + (func $1 (result i64) + (drop + (call $0) + ) + (i64.const 0) + ) +) +;; potential infinite recursion +(module + (func $main + (call $one) + (call $one) + ) + (func $one + (call $one) + ) +) +;; potential infinite cycling recursion +(module + (func $main + (call $one) + (call $one) + ) + (func $one + (call $two) + ) + (func $two + (call $one) + ) +) +;; make sure to dce, as we may be combining unreachable code with others +(module + (type $0 (func)) + (type $1 (func (param i32 i32) (result i32))) + (table 89 89 funcref) + (memory $0 17) + (start $1) + (func $0 (; 0 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) + (i32.store + (i32.const 4) + (local.tee $0 + (i32.const 0) + ) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 56) + ) + (i32.const 0) + ) + (i64.store + (i32.const 49) + (i64.load + (i32.const 24) + ) + ) + (unreachable) + ) + (func $1 (; 1 ;) (type $0) + (drop + (call $0 + (i32.const 0) + (i32.const 0) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/inlining-optimizing_optimize-level=3.txt binaryen-99/test/passes/inlining-optimizing_optimize-level=3.txt --- binaryen-108/test/passes/inlining-optimizing_optimize-level=3.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining-optimizing_optimize-level=3.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,15438 @@ +(module + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_none (func)) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) + (type $f64_i32_=>_f64 (func (param f64 i32) (result f64))) + (import "env" "memory" (memory $0 256 256)) + (data (i32.const 1024) "emcc_hello_world.asm.js") + (import "env" "table" (table $timport$0 18 18 funcref)) + (elem (global.get $tableBase) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) + (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) + (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) + (import "env" "tempDoublePtr" (global $tempDoublePtr$asm2wasm$import i32)) + (import "env" "memoryBase" (global $memoryBase i32)) + (import "env" "tableBase" (global $tableBase i32)) + (import "env" "abort" (func $abort)) + (import "env" "nullFunc_ii" (func $nullFunc_ii (param i32))) + (import "env" "nullFunc_iiii" (func $nullFunc_iiii (param i32))) + (import "env" "nullFunc_vi" (func $nullFunc_vi (param i32))) + (import "env" "_pthread_cleanup_pop" (func $_pthread_cleanup_pop (param i32))) + (import "env" "___lock" (func $___lock (param i32))) + (import "env" "_pthread_self" (func $_pthread_self (result i32))) + (import "env" "_abort" (func $_abort)) + (import "env" "___syscall6" (func $___syscall6 (param i32 i32) (result i32))) + (import "env" "_sbrk" (func $_sbrk (param i32) (result i32))) + (import "env" "_time" (func $_time (param i32) (result i32))) + (import "env" "_emscripten_memcpy_big" (func $_emscripten_memcpy_big (param i32 i32 i32) (result i32))) + (import "env" "___syscall54" (func $___syscall54 (param i32 i32) (result i32))) + (import "env" "___unlock" (func $___unlock (param i32))) + (import "env" "___syscall140" (func $___syscall140 (param i32 i32) (result i32))) + (import "env" "_pthread_cleanup_push" (func $_pthread_cleanup_push (param i32 i32))) + (import "env" "_sysconf" (func $_sysconf (param i32) (result i32))) + (import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32))) + (global $STACKTOP (mut i32) (global.get $STACKTOP$asm2wasm$import)) + (global $STACK_MAX (mut i32) (global.get $STACK_MAX$asm2wasm$import)) + (global $tempDoublePtr (mut i32) (global.get $tempDoublePtr$asm2wasm$import)) + (global $__THREW__ (mut i32) (i32.const 0)) + (global $threwValue (mut i32) (i32.const 0)) + (global $tempRet0 (mut i32) (i32.const 0)) + (export "_i64Subtract" (func $_i64Subtract)) + (export "_free" (func $_free)) + (export "_main" (func $_main)) + (export "_i64Add" (func $_i64Add)) + (export "_memset" (func $_memset)) + (export "_malloc" (func $_malloc)) + (export "_memcpy" (func $_memcpy)) + (export "_bitshift64Lshr" (func $_bitshift64Lshr)) + (export "_fflush" (func $_fflush)) + (export "___errno_location" (func $___errno_location)) + (export "_bitshift64Shl" (func $_bitshift64Shl)) + (export "runPostSets" (func $runPostSets)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackSave" (func $stackSave)) + (export "stackRestore" (func $stackRestore)) + (export "establishStackSpace" (func $establishStackSpace)) + (export "setThrew" (func $setThrew)) + (export "setTempRet0" (func $setTempRet0)) + (export "getTempRet0" (func $getTempRet0)) + (export "dynCall_ii" (func $dynCall_ii)) + (export "dynCall_iiii" (func $dynCall_iiii)) + (export "dynCall_vi" (func $dynCall_vi)) + (export "___udivmoddi4" (func $___udivmoddi4)) + (func $stackAlloc (param $0 i32) (result i32) + (local $1 i32) + (local.set $1 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (local.get $0) + ) + ) + (global.set $STACKTOP + (i32.and + (i32.add + (global.get $STACKTOP) + (i32.const 15) + ) + (i32.const -16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.get $1) + ) + (func $stackSave (result i32) + (global.get $STACKTOP) + ) + (func $stackRestore (param $0 i32) + (global.set $STACKTOP + (local.get $0) + ) + ) + (func $establishStackSpace (param $0 i32) (param $1 i32) + (global.set $STACKTOP + (local.get $0) + ) + (global.set $STACK_MAX + (local.get $1) + ) + ) + (func $setThrew (param $0 i32) (param $1 i32) + (if + (i32.eqz + (global.get $__THREW__) + ) + (block $block + (global.set $__THREW__ + (local.get $0) + ) + (global.set $threwValue + (local.get $1) + ) + ) + ) + ) + (func $setTempRet0 (param $0 i32) + (global.set $tempRet0 + (local.get $0) + ) + ) + (func $getTempRet0 (result i32) + (global.get $tempRet0) + ) + (func $_main (result i32) + (local $0 i32) + (local.set $0 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (drop + (call $_printf + (i32.const 672) + (local.get $0) + ) + ) + (global.set $STACKTOP + (local.get $0) + ) + (i32.const 0) + ) + (func $_frexp (param $0 f64) (param $1 i32) (result f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (f64.store + (global.get $tempDoublePtr) + (local.get $0) + ) + (block $switch + (block $switch-default + (block $switch-case0 + (block $switch-case + (br_table $switch-case $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case0 $switch-default + (local.tee $3 + (i32.and + (local.tee $3 + (call $_bitshift64Lshr + (local.tee $2 + (i32.load + (global.get $tempDoublePtr) + ) + ) + (local.tee $4 + (i32.load offset=4 + (global.get $tempDoublePtr) + ) + ) + (i32.const 52) + ) + ) + (i32.const 2047) + ) + ) + ) + ) + (i32.store + (local.get $1) + (local.tee $2 + (if (result i32) + (f64.ne + (local.get $0) + (f64.const 0) + ) + (block $block (result i32) + (local.set $0 + (call $_frexp + (f64.mul + (local.get $0) + (f64.const 18446744073709551615) + ) + (local.get $1) + ) + ) + (i32.add + (i32.load + (local.get $1) + ) + (i32.const -64) + ) + ) + (i32.const 0) + ) + ) + ) + (br $switch) + ) + (br $switch) + ) + (i32.store + (local.get $1) + (i32.add + (local.get $3) + (i32.const -1022) + ) + ) + (i32.store + (global.get $tempDoublePtr) + (local.get $2) + ) + (i32.store offset=4 + (global.get $tempDoublePtr) + (i32.or + (i32.and + (local.get $4) + (i32.const -2146435073) + ) + (i32.const 1071644672) + ) + ) + (local.set $0 + (f64.load + (global.get $tempDoublePtr) + ) + ) + ) + (local.get $0) + ) + (func $_strerror (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (i32.const 0) + ) + (block $__rjto$1 + (block $__rjti$1 + (block $__rjti$0 + (loop $while-in + (br_if $__rjti$0 + (i32.eq + (i32.load8_u offset=687 + (local.get $1) + ) + (local.get $0) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 87) + ) + ) + (local.set $1 + (i32.const 87) + ) + (br $__rjti$1) + ) + ) + (br_if $__rjti$1 + (local.get $1) + ) + (local.set $0 + (i32.const 775) + ) + (br $__rjto$1) + ) + (local.set $0 + (i32.const 775) + ) + (loop $while-in1 + (loop $while-in3 + (local.set $2 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (if + (i32.load8_s + (local.get $0) + ) + (block $block + (local.set $0 + (local.get $2) + ) + (br $while-in3) + ) + (local.set $0 + (local.get $2) + ) + ) + ) + (br_if $while-in1 + (local.tee $1 + (i32.add + (local.get $1) + (i32.const -1) + ) + ) + ) + ) + ) + (local.get $0) + ) + (func $___errno_location (result i32) + (if (result i32) + (i32.load + (i32.const 16) + ) + (i32.load offset=60 + (call $_pthread_self) + ) + (i32.const 60) + ) + ) + (func $___stdio_close (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (i32.store + (local.tee $2 + (local.get $1) + ) + (i32.load offset=60 + (local.get $0) + ) + ) + (local.set $0 + (call $___syscall_ret + (call $___syscall6 + (i32.const 6) + (local.get $2) + ) + ) + ) + (global.set $STACKTOP + (local.get $1) + ) + (local.get $0) + ) + (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 80) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $3 + (local.get $4) + ) + (local.set $5 + (i32.add + (local.get $4) + (i32.const 12) + ) + ) + (i32.store offset=36 + (local.get $0) + (i32.const 4) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 64) + ) + ) + (block $block + (i32.store + (local.get $3) + (i32.load offset=60 + (local.get $0) + ) + ) + (i32.store offset=4 + (local.get $3) + (i32.const 21505) + ) + (i32.store offset=8 + (local.get $3) + (local.get $5) + ) + (if + (call $___syscall54 + (i32.const 54) + (local.get $3) + ) + (i32.store8 offset=75 + (local.get $0) + (i32.const -1) + ) + ) + ) + ) + (local.set $0 + (call $___stdio_write + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (local.get $0) + ) + (func $___stdio_seek (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 32) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (i32.store + (local.tee $3 + (local.get $4) + ) + (i32.load offset=60 + (local.get $0) + ) + ) + (i32.store offset=4 + (local.get $3) + (i32.const 0) + ) + (i32.store offset=8 + (local.get $3) + (local.get $1) + ) + (i32.store offset=12 + (local.get $3) + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 20) + ) + ) + ) + (i32.store offset=16 + (local.get $3) + (local.get $2) + ) + (local.set $0 + (if (result i32) + (i32.lt_s + (call $___syscall_ret + (call $___syscall140 + (i32.const 140) + (local.get $3) + ) + ) + (i32.const 0) + ) + (block $block (result i32) + (i32.store + (local.get $0) + (i32.const -1) + ) + (i32.const -1) + ) + (i32.load + (local.get $0) + ) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (local.get $0) + ) + (func $_fflush (param $0 i32) (result i32) + (local $1 i32) + (if + (local.get $0) + (local.set $0 + (block $do-once (result i32) + (if + (i32.le_s + (i32.load offset=76 + (local.get $0) + ) + (i32.const -1) + ) + (br $do-once + (call $___fflush_unlocked + (local.get $0) + ) + ) + ) + (local.tee $0 + (call $___fflush_unlocked + (local.get $0) + ) + ) + ) + ) + (block + (local.set $0 + (if (result i32) + (i32.load + (i32.const 12) + ) + (call $_fflush + (i32.load + (i32.const 12) + ) + ) + (i32.const 0) + ) + ) + (call $___lock + (i32.const 44) + ) + (if + (local.tee $1 + (i32.load + (i32.const 40) + ) + ) + (loop $while-in + (drop + (i32.load offset=76 + (local.get $1) + ) + ) + (if + (i32.gt_u + (i32.load offset=20 + (local.get $1) + ) + (i32.load offset=28 + (local.get $1) + ) + ) + (local.set $0 + (i32.or + (call $___fflush_unlocked + (local.get $1) + ) + (local.get $0) + ) + ) + ) + (br_if $while-in + (local.tee $1 + (i32.load offset=56 + (local.get $1) + ) + ) + ) + ) + ) + (call $___unlock + (i32.const 44) + ) + ) + ) + (local.get $0) + ) + (func $_printf (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local.set $2 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (i32.store + (local.tee $3 + (local.get $2) + ) + (local.get $1) + ) + (local.set $0 + (call $_vfprintf + (i32.load + (i32.const 8) + ) + (local.get $0) + (local.get $3) + ) + ) + (global.set $STACKTOP + (local.get $2) + ) + (local.get $0) + ) + (func $___stdio_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local.set $8 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 48) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $9 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + (local.set $10 + (local.get $8) + ) + (i32.store + (local.tee $4 + (i32.add + (local.get $8) + (i32.const 32) + ) + ) + (local.tee $3 + (i32.load + (local.tee $6 + (i32.add + (local.get $0) + (i32.const 28) + ) + ) + ) + ) + ) + (i32.store offset=4 + (local.get $4) + (local.tee $3 + (i32.sub + (i32.load + (local.tee $11 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + ) + (local.get $3) + ) + ) + ) + (i32.store offset=8 + (local.get $4) + (local.get $1) + ) + (i32.store offset=12 + (local.get $4) + (local.get $2) + ) + (local.set $13 + (i32.add + (local.get $0) + (i32.const 60) + ) + ) + (local.set $14 + (i32.add + (local.get $0) + (i32.const 44) + ) + ) + (local.set $1 + (local.get $4) + ) + (local.set $4 + (i32.const 2) + ) + (local.set $12 + (i32.add + (local.get $3) + (local.get $2) + ) + ) + (block $__rjto$1 + (block $__rjti$1 + (block $__rjti$0 + (loop $while-in + (if + (i32.load + (i32.const 16) + ) + (block $block + (call $_pthread_cleanup_push + (i32.const 5) + (local.get $0) + ) + (i32.store + (local.get $10) + (i32.load + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $10) + (local.get $1) + ) + (i32.store offset=8 + (local.get $10) + (local.get $4) + ) + (local.set $3 + (call $___syscall_ret + (call $___syscall146 + (i32.const 146) + (local.get $10) + ) + ) + ) + (call $_pthread_cleanup_pop + (i32.const 0) + ) + ) + (block $block14 + (i32.store + (local.get $9) + (i32.load + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $9) + (local.get $1) + ) + (i32.store offset=8 + (local.get $9) + (local.get $4) + ) + (local.set $3 + (call $___syscall_ret + (call $___syscall146 + (i32.const 146) + (local.get $9) + ) + ) + ) + ) + ) + (br_if $__rjti$0 + (i32.eq + (local.get $12) + (local.get $3) + ) + ) + (br_if $__rjti$1 + (i32.lt_s + (local.get $3) + (i32.const 0) + ) + ) + (local.set $5 + (if (result i32) + (i32.gt_u + (local.get $3) + (local.tee $5 + (i32.load offset=4 + (local.get $1) + ) + ) + ) + (block $block16 (result i32) + (i32.store + (local.get $6) + (local.tee $7 + (i32.load + (local.get $14) + ) + ) + ) + (i32.store + (local.get $11) + (local.get $7) + ) + (local.set $7 + (i32.load offset=12 + (local.get $1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (local.set $4 + (i32.add + (local.get $4) + (i32.const -1) + ) + ) + (i32.sub + (local.get $3) + (local.get $5) + ) + ) + (block $block17 (result i32) + (if + (i32.eq + (local.get $4) + (i32.const 2) + ) + (block $block19 + (i32.store + (local.get $6) + (i32.add + (i32.load + (local.get $6) + ) + (local.get $3) + ) + ) + (local.set $7 + (local.get $5) + ) + (local.set $4 + (i32.const 2) + ) + ) + (local.set $7 + (local.get $5) + ) + ) + (local.get $3) + ) + ) + ) + (i32.store + (local.get $1) + (i32.add + (i32.load + (local.get $1) + ) + (local.get $5) + ) + ) + (i32.store offset=4 + (local.get $1) + (i32.sub + (local.get $7) + (local.get $5) + ) + ) + (local.set $12 + (i32.sub + (local.get $12) + (local.get $3) + ) + ) + (br $while-in) + ) + ) + (i32.store offset=16 + (local.get $0) + (i32.add + (local.tee $1 + (i32.load + (local.get $14) + ) + ) + (i32.load offset=48 + (local.get $0) + ) + ) + ) + (i32.store + (local.get $6) + (local.get $1) + ) + (i32.store + (local.get $11) + (local.get $1) + ) + (br $__rjto$1) + ) + (i32.store offset=16 + (local.get $0) + (i32.const 0) + ) + (i32.store + (local.get $6) + (i32.const 0) + ) + (i32.store + (local.get $11) + (i32.const 0) + ) + (i32.store + (local.get $0) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (local.set $2 + (if (result i32) + (i32.eq + (local.get $4) + (i32.const 2) + ) + (i32.const 0) + (i32.sub + (local.get $2) + (i32.load offset=4 + (local.get $1) + ) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $8) + ) + (local.get $2) + ) + (func $_vfprintf (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local.set $3 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 224) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $5 + (i32.add + (local.get $3) + (i32.const 120) + ) + ) + (local.set $6 + (i32.add + (local.get $3) + (i32.const 136) + ) + ) + (local.set $8 + (i32.add + (local.tee $4 + (local.tee $7 + (i32.add + (local.get $3) + (i32.const 80) + ) + ) + ) + (i32.const 40) + ) + ) + (loop $do-in + (i32.store + (local.get $4) + (i32.const 0) + ) + (br_if $do-in + (i32.lt_s + (local.tee $4 + (i32.add + (local.get $4) + (i32.const 4) + ) + ) + (local.get $8) + ) + ) + ) + (i32.store + (local.get $5) + (i32.load + (local.get $2) + ) + ) + (local.set $0 + (if (result i32) + (i32.lt_s + (call $_printf_core + (i32.const 0) + (local.get $1) + (local.get $5) + (local.get $3) + (local.get $7) + ) + (i32.const 0) + ) + (i32.const -1) + (block (result i32) + (drop + (i32.load offset=76 + (local.get $0) + ) + ) + (local.set $4 + (i32.load + (local.get $0) + ) + ) + (if + (i32.lt_s + (i32.load8_s offset=74 + (local.get $0) + ) + (i32.const 1) + ) + (i32.store + (local.get $0) + (i32.and + (local.get $4) + (i32.const -33) + ) + ) + ) + (if + (i32.load + (local.tee $9 + (i32.add + (local.get $0) + (i32.const 48) + ) + ) + ) + (local.set $1 + (call $_printf_core + (local.get $0) + (local.get $1) + (local.get $5) + (local.get $3) + (local.get $7) + ) + ) + (block + (local.set $11 + (i32.load + (local.tee $10 + (i32.add + (local.get $0) + (i32.const 44) + ) + ) + ) + ) + (i32.store + (local.get $10) + (local.get $6) + ) + (i32.store + (local.tee $8 + (i32.add + (local.get $0) + (i32.const 28) + ) + ) + (local.get $6) + ) + (i32.store + (local.tee $12 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + (local.get $6) + ) + (i32.store + (local.get $9) + (i32.const 80) + ) + (i32.store + (local.tee $2 + (i32.add + (local.get $0) + (i32.const 16) + ) + ) + (i32.add + (local.get $6) + (i32.const 80) + ) + ) + (local.set $1 + (call $_printf_core + (local.get $0) + (local.get $1) + (local.get $5) + (local.get $3) + (local.get $7) + ) + ) + (if + (local.get $11) + (block + (drop + (call_indirect (type $i32_i32_i32_=>_i32) + (local.get $0) + (i32.const 0) + (i32.const 0) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $0) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (local.set $1 + (select + (local.get $1) + (i32.const -1) + (i32.load + (local.get $12) + ) + ) + ) + (i32.store + (local.get $10) + (local.get $11) + ) + (i32.store + (local.get $9) + (i32.const 0) + ) + (i32.store + (local.get $2) + (i32.const 0) + ) + (i32.store + (local.get $8) + (i32.const 0) + ) + (i32.store + (local.get $12) + (i32.const 0) + ) + ) + ) + ) + ) + (i32.store + (local.get $0) + (i32.or + (local.tee $0 + (i32.load + (local.get $0) + ) + ) + (i32.and + (local.get $4) + (i32.const 32) + ) + ) + ) + (select + (i32.const -1) + (local.get $1) + (i32.and + (local.get $0) + (i32.const 32) + ) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $3) + ) + (local.get $0) + ) + (func $___fwritex (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block $label$break$L5 + (block $__rjti$0 + (br_if $__rjti$0 + (local.tee $3 + (i32.load + (local.tee $4 + (i32.add + (local.get $2) + (i32.const 16) + ) + ) + ) + ) + ) + (if + (call $___towrite + (local.get $2) + ) + (local.set $3 + (i32.const 0) + ) + (block $block + (local.set $3 + (i32.load + (local.get $4) + ) + ) + (br $__rjti$0) + ) + ) + (br $label$break$L5) + ) + (if + (i32.lt_u + (i32.sub + (local.get $3) + (local.tee $4 + (i32.load + (local.tee $5 + (i32.add + (local.get $2) + (i32.const 20) + ) + ) + ) + ) + ) + (local.get $1) + ) + (block $block30 + (local.set $3 + (call_indirect (type $i32_i32_i32_=>_i32) + (local.get $2) + (local.get $0) + (local.get $1) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $2) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (br $label$break$L5) + ) + ) + (local.set $2 + (block $label$break$L10 (result i32) + (if (result i32) + (i32.gt_s + (i32.load8_s offset=75 + (local.get $2) + ) + (i32.const -1) + ) + (block $block32 (result i32) + (local.set $3 + (local.get $1) + ) + (loop $while-in + (drop + (br_if $label$break$L10 + (i32.const 0) + (i32.eqz + (local.get $3) + ) + ) + ) + (if + (i32.ne + (i32.load8_s + (i32.add + (local.get $0) + (local.tee $6 + (i32.add + (local.get $3) + (i32.const -1) + ) + ) + ) + ) + (i32.const 10) + ) + (block $block34 + (local.set $3 + (local.get $6) + ) + (br $while-in) + ) + ) + ) + (br_if $label$break$L5 + (i32.lt_u + (call_indirect (type $i32_i32_i32_=>_i32) + (local.get $2) + (local.get $0) + (local.get $3) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $2) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + (local.get $3) + ) + ) + (local.set $4 + (i32.load + (local.get $5) + ) + ) + (local.set $1 + (i32.sub + (local.get $1) + (local.get $3) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (local.get $3) + ) + ) + (local.get $3) + ) + (i32.const 0) + ) + ) + ) + (drop + (call $_memcpy + (local.get $4) + (local.get $0) + (local.get $1) + ) + ) + (i32.store + (local.get $5) + (i32.add + (i32.load + (local.get $5) + ) + (local.get $1) + ) + ) + (local.set $3 + (i32.add + (local.get $2) + (local.get $1) + ) + ) + ) + (local.get $3) + ) + (func $___towrite (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (i32.load8_s + (local.tee $2 + (i32.add + (local.get $0) + (i32.const 74) + ) + ) + ) + ) + (i32.store8 + (local.get $2) + (i32.or + (i32.add + (local.get $1) + (i32.const 255) + ) + (local.get $1) + ) + ) + (local.tee $0 + (if (result i32) + (i32.and + (local.tee $1 + (i32.load + (local.get $0) + ) + ) + (i32.const 8) + ) + (block $block (result i32) + (i32.store + (local.get $0) + (i32.or + (local.get $1) + (i32.const 32) + ) + ) + (i32.const -1) + ) + (block $block35 (result i32) + (i32.store offset=8 + (local.get $0) + (i32.const 0) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (i32.store offset=28 + (local.get $0) + (local.tee $1 + (i32.load offset=44 + (local.get $0) + ) + ) + ) + (i32.store offset=20 + (local.get $0) + (local.get $1) + ) + (i32.store offset=16 + (local.get $0) + (i32.add + (local.get $1) + (i32.load offset=48 + (local.get $0) + ) + ) + ) + (i32.const 0) + ) + ) + ) + ) + (func $_wcrtomb (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (block $do-once (result i32) + (if (result i32) + (local.get $0) + (block $block (result i32) + (if + (i32.lt_u + (local.get $1) + (i32.const 128) + ) + (block $block37 + (i32.store8 + (local.get $0) + (local.get $1) + ) + (br $do-once + (i32.const 1) + ) + ) + ) + (if + (i32.lt_u + (local.get $1) + (i32.const 2048) + ) + (block $block39 + (i32.store8 + (local.get $0) + (i32.or + (i32.shr_u + (local.get $1) + (i32.const 6) + ) + (i32.const 192) + ) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.or + (i32.and + (local.get $1) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (br $do-once + (i32.const 2) + ) + ) + ) + (if + (i32.or + (i32.lt_u + (local.get $1) + (i32.const 55296) + ) + (i32.eq + (i32.and + (local.get $1) + (i32.const -8192) + ) + (i32.const 57344) + ) + ) + (block $block41 + (i32.store8 + (local.get $0) + (i32.or + (i32.shr_u + (local.get $1) + (i32.const 12) + ) + (i32.const 224) + ) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.or + (i32.and + (i32.shr_u + (local.get $1) + (i32.const 6) + ) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.or + (i32.and + (local.get $1) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (br $do-once + (i32.const 3) + ) + ) + ) + (if (result i32) + (i32.lt_u + (i32.add + (local.get $1) + (i32.const -65536) + ) + (i32.const 1048576) + ) + (block $block43 (result i32) + (i32.store8 + (local.get $0) + (i32.or + (i32.shr_u + (local.get $1) + (i32.const 18) + ) + (i32.const 240) + ) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.or + (i32.and + (i32.shr_u + (local.get $1) + (i32.const 12) + ) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.or + (i32.and + (i32.shr_u + (local.get $1) + (i32.const 6) + ) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.store8 offset=3 + (local.get $0) + (i32.or + (i32.and + (local.get $1) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.const 4) + ) + (block $block44 (result i32) + (i32.store + (call $___errno_location) + (i32.const 84) + ) + (i32.const -1) + ) + ) + ) + (i32.const 1) + ) + ) + ) + (func $_wctomb (param $0 i32) (param $1 i32) (result i32) + (if (result i32) + (local.get $0) + (call $_wcrtomb + (local.get $0) + (local.get $1) + (i32.const 0) + ) + (i32.const 0) + ) + ) + (func $_memchr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $5 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + (block $label$break$L8 + (block $__rjti$2 + (if + (i32.and + (local.tee $4 + (i32.ne + (local.get $2) + (i32.const 0) + ) + ) + (i32.ne + (i32.and + (local.get $0) + (i32.const 3) + ) + (i32.const 0) + ) + ) + (block $block + (local.set $4 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $2 + (local.get $0) + ) + (loop $while-in + (br_if $__rjti$2 + (i32.eq + (i32.load8_u + (local.get $2) + ) + (i32.and + (local.get $4) + (i32.const 255) + ) + ) + ) + (br_if $while-in + (i32.and + (local.tee $0 + (i32.ne + (local.tee $3 + (i32.add + (local.get $3) + (i32.const -1) + ) + ) + (i32.const 0) + ) + ) + (i32.ne + (i32.and + (local.tee $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (i32.const 3) + ) + (i32.const 0) + ) + ) + ) + ) + ) + (block $block45 + (local.set $3 + (local.get $2) + ) + (local.set $2 + (local.get $0) + ) + (local.set $0 + (local.get $4) + ) + ) + ) + (br_if $__rjti$2 + (local.get $0) + ) + (local.set $0 + (i32.const 0) + ) + (br $label$break$L8) + ) + (local.set $0 + (local.get $3) + ) + (if + (i32.ne + (i32.load8_u + (local.get $2) + ) + (local.tee $1 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (block $block47 + (local.set $3 + (i32.mul + (local.get $5) + (i32.const 16843009) + ) + ) + (block $__rjto$0 + (block $__rjti$0 + (br_if $__rjti$0 + (i32.le_u + (local.get $0) + (i32.const 3) + ) + ) + (loop $while-in3 + (if + (i32.eqz + (i32.and + (i32.xor + (i32.and + (local.tee $4 + (i32.xor + (i32.load + (local.get $2) + ) + (local.get $3) + ) + ) + (i32.const -2139062144) + ) + (i32.const -2139062144) + ) + (i32.add + (local.get $4) + (i32.const -16843009) + ) + ) + ) + (block $block49 + (local.set $2 + (i32.add + (local.get $2) + (i32.const 4) + ) + ) + (br_if $while-in3 + (i32.gt_u + (local.tee $0 + (i32.add + (local.get $0) + (i32.const -4) + ) + ) + (i32.const 3) + ) + ) + (br $__rjti$0) + ) + ) + ) + (br $__rjto$0) + ) + (if + (i32.eqz + (local.get $0) + ) + (block $block51 + (local.set $0 + (i32.const 0) + ) + (br $label$break$L8) + ) + ) + ) + (loop $while-in5 + (br_if $label$break$L8 + (i32.eq + (i32.load8_u + (local.get $2) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (br_if $while-in5 + (local.tee $0 + (i32.add + (local.get $0) + (i32.const -1) + ) + ) + ) + (local.set $0 + (i32.const 0) + ) + ) + ) + ) + ) + (select + (local.get $2) + (i32.const 0) + (local.get $0) + ) + ) + (func $___syscall_ret (param $0 i32) (result i32) + (if (result i32) + (i32.gt_u + (local.get $0) + (i32.const -4096) + ) + (block $block (result i32) + (i32.store + (call $___errno_location) + (i32.sub + (i32.const 0) + (local.get $0) + ) + ) + (i32.const -1) + ) + (local.get $0) + ) + ) + (func $___fflush_unlocked (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local.tee $0 + (block $__rjto$0 (result i32) + (block $__rjti$0 + (br_if $__rjti$0 + (i32.le_u + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + ) + (i32.load + (local.tee $2 + (i32.add + (local.get $0) + (i32.const 28) + ) + ) + ) + ) + ) + (drop + (call_indirect (type $i32_i32_i32_=>_i32) + (local.get $0) + (i32.const 0) + (i32.const 0) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $0) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (br_if $__rjti$0 + (i32.load + (local.get $1) + ) + ) + (br $__rjto$0 + (i32.const -1) + ) + ) + (if + (i32.lt_u + (local.tee $4 + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + ) + ) + (local.tee $6 + (i32.load + (local.tee $5 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + ) + (drop + (call_indirect (type $i32_i32_i32_=>_i32) + (local.get $0) + (i32.sub + (local.get $4) + (local.get $6) + ) + (i32.const 1) + (i32.add + (i32.and + (i32.load offset=40 + (local.get $0) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.store offset=16 + (local.get $0) + (i32.const 0) + ) + (i32.store + (local.get $2) + (i32.const 0) + ) + (i32.store + (local.get $1) + (i32.const 0) + ) + (i32.store + (local.get $5) + (i32.const 0) + ) + (i32.store + (local.get $3) + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (func $_cleanup (param $0 i32) + (drop + (i32.load offset=68 + (local.get $0) + ) + ) + ) + (func $_printf_core (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 f64) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 i32) + (local $24 f64) + (local $25 i32) + (local $26 i32) + (local $27 i32) + (local $28 i32) + (local $29 i32) + (local $30 i32) + (local $31 i32) + (local $32 i32) + (local $33 i32) + (local $34 i32) + (local $35 i32) + (local $36 i32) + (local $37 i32) + (local $38 i32) + (local $39 i32) + (local $40 i32) + (local $41 i32) + (local $42 i32) + (local $43 i32) + (local $44 i32) + (local $45 i32) + (local $46 i32) + (local $47 i32) + (local $48 i32) + (local.set $13 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 624) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $21 + (i32.add + (local.get $13) + (i32.const 16) + ) + ) + (local.set $33 + (i32.add + (local.get $13) + (i32.const 528) + ) + ) + (local.set $28 + (i32.ne + (local.get $0) + (i32.const 0) + ) + ) + (local.set $37 + (local.tee $25 + (i32.add + (local.tee $5 + (i32.add + (local.get $13) + (i32.const 536) + ) + ) + (i32.const 40) + ) + ) + ) + (local.set $38 + (i32.add + (local.get $5) + (i32.const 39) + ) + ) + (local.set $42 + (i32.add + (local.tee $39 + (i32.add + (local.get $13) + (i32.const 8) + ) + ) + (i32.const 4) + ) + ) + (local.set $22 + (i32.add + (local.tee $5 + (i32.add + (local.get $13) + (i32.const 576) + ) + ) + (i32.const 12) + ) + ) + (local.set $40 + (i32.add + (local.get $5) + (i32.const 11) + ) + ) + (local.set $43 + (i32.sub + (local.get $22) + (local.tee $34 + (local.tee $23 + (i32.add + (local.get $13) + (i32.const 588) + ) + ) + ) + ) + ) + (local.set $44 + (i32.sub + (i32.const -2) + (local.get $34) + ) + ) + (local.set $45 + (i32.add + (local.get $22) + (i32.const 2) + ) + ) + (local.set $47 + (i32.add + (local.tee $46 + (i32.add + (local.get $13) + (i32.const 24) + ) + ) + (i32.const 288) + ) + ) + (local.set $41 + (local.tee $29 + (i32.add + (local.get $23) + (i32.const 9) + ) + ) + ) + (local.set $32 + (i32.add + (local.get $23) + (i32.const 8) + ) + ) + (local.set $5 + (local.get $1) + ) + (local.set $1 + (i32.const 0) + ) + (block $label$break$L343 + (block $__rjti$9 + (loop $label$continue$L1 + (block $label$break$L1 + (if + (i32.gt_s + (local.get $18) + (i32.const -1) + ) + (local.set $18 + (if (result i32) + (i32.gt_s + (local.get $10) + (i32.sub + (i32.const 2147483647) + (local.get $18) + ) + ) + (block (result i32) + (i32.store + (call $___errno_location) + (i32.const 75) + ) + (i32.const -1) + ) + (i32.add + (local.get $10) + (local.get $18) + ) + ) + ) + ) + (br_if $__rjti$9 + (i32.eqz + (local.tee $7 + (i32.load8_s + (local.get $5) + ) + ) + ) + ) + (local.set $10 + (local.get $5) + ) + (block $label$break$L12 + (block $__rjti$1 + (loop $label$continue$L9 + (block $label$break$L9 + (block $switch-default + (block $switch-case0 + (block $switch-case + (br_table $switch-case0 $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case $switch-default + (i32.shr_s + (i32.shl + (local.get $7) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (local.set $6 + (local.get $10) + ) + (br $__rjti$1) + ) + (local.set $6 + (local.get $10) + ) + (br $label$break$L9) + ) + (local.set $7 + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + ) + (br $label$continue$L9) + ) + ) + (br $label$break$L12) + ) + (loop $while-in + (br_if $label$break$L12 + (i32.ne + (i32.load8_s offset=1 + (local.get $6) + ) + (i32.const 37) + ) + ) + (local.set $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + (br_if $while-in + (i32.eq + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 2) + ) + ) + ) + (i32.const 37) + ) + ) + ) + ) + (local.set $7 + (i32.sub + (local.get $10) + (local.get $5) + ) + ) + (if + (local.get $28) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $5) + (local.get $7) + (local.get $0) + ) + ) + ) + ) + (if + (i32.ne + (local.get $5) + (local.get $10) + ) + (block + (local.set $5 + (local.get $6) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + ) + (local.set $8 + (if (result i32) + (i32.lt_u + (local.tee $8 + (i32.sub + (local.tee $12 + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $6) + (i32.const 1) + ) + ) + ) + ) + (i32.const 48) + ) + ) + (i32.const 10) + ) + (block (result i32) + (local.set $6 + (i32.load8_s + (local.tee $10 + (select + (i32.add + (local.get $6) + (i32.const 3) + ) + (local.get $10) + (local.tee $12 + (i32.eq + (i32.load8_s offset=2 + (local.get $6) + ) + (i32.const 36) + ) + ) + ) + ) + ) + ) + (local.set $19 + (select + (local.get $8) + (i32.const -1) + (local.get $12) + ) + ) + (select + (i32.const 1) + (local.get $1) + (local.get $12) + ) + ) + (block (result i32) + (local.set $6 + (local.get $12) + ) + (local.set $19 + (i32.const -1) + ) + (local.get $1) + ) + ) + ) + (local.set $1 + (if (result i32) + (i32.eq + (i32.and + (local.tee $12 + (i32.shr_s + (i32.shl + (local.get $6) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (i32.const -32) + ) + (i32.const 32) + ) + (block $label$break$L25 (result i32) + (local.set $1 + (local.get $6) + ) + (local.set $6 + (local.get $12) + ) + (local.set $12 + (i32.const 0) + ) + (loop $while-in4 (result i32) + (if + (i32.eqz + (i32.and + (i32.shl + (i32.const 1) + (i32.sub + (local.get $6) + (i32.const 32) + ) + ) + (i32.const 75913) + ) + ) + (block + (local.set $6 + (local.get $1) + ) + (br $label$break$L25 + (local.get $12) + ) + ) + ) + (local.set $12 + (i32.or + (i32.shl + (i32.const 1) + (i32.sub + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 32) + ) + ) + (local.get $12) + ) + ) + (br_if $while-in4 + (i32.eq + (i32.and + (local.tee $6 + (local.tee $1 + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + ) + ) + (i32.const -32) + ) + (i32.const 32) + ) + ) + (local.set $6 + (local.get $1) + ) + (local.get $12) + ) + ) + (i32.const 0) + ) + ) + (local.set $1 + (if (result i32) + (i32.eq + (i32.and + (local.get $6) + (i32.const 255) + ) + (i32.const 42) + ) + (block $do-once5 (result i32) + (local.set $10 + (block $__rjto$0 (result i32) + (block $__rjti$0 + (br_if $__rjti$0 + (i32.ge_u + (local.tee $12 + (i32.sub + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + (i32.const 48) + ) + ) + (i32.const 10) + ) + ) + (br_if $__rjti$0 + (i32.ne + (i32.load8_s offset=2 + (local.get $10) + ) + (i32.const 36) + ) + ) + (i32.store + (i32.add + (local.get $4) + (i32.shl + (local.get $12) + (i32.const 2) + ) + ) + (i32.const 10) + ) + (drop + (i32.load offset=4 + (local.tee $6 + (i32.add + (local.get $3) + (i32.shl + (i32.sub + (i32.load8_s + (local.get $6) + ) + (i32.const 48) + ) + (i32.const 3) + ) + ) + ) + ) + ) + (local.set $8 + (i32.const 1) + ) + (local.set $17 + (i32.load + (local.get $6) + ) + ) + (br $__rjto$0 + (i32.add + (local.get $10) + (i32.const 3) + ) + ) + ) + (if + (local.get $8) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (if + (i32.eqz + (local.get $28) + ) + (block + (local.set $12 + (local.get $1) + ) + (local.set $10 + (local.get $6) + ) + (local.set $17 + (i32.const 0) + ) + (br $do-once5 + (i32.const 0) + ) + ) + ) + (local.set $17 + (i32.load + (local.tee $10 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $10) + (i32.const 4) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.get $6) + ) + ) + (local.set $12 + (if (result i32) + (i32.lt_s + (local.get $17) + (i32.const 0) + ) + (block (result i32) + (local.set $17 + (i32.sub + (i32.const 0) + (local.get $17) + ) + ) + (i32.or + (local.get $1) + (i32.const 8192) + ) + ) + (local.get $1) + ) + ) + (local.get $8) + ) + (if (result i32) + (i32.lt_u + (local.tee $6 + (i32.sub + (i32.shr_s + (i32.shl + (local.get $6) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 48) + ) + ) + (i32.const 10) + ) + (block (result i32) + (local.set $12 + (i32.const 0) + ) + (loop $while-in8 + (local.set $6 + (i32.add + (i32.mul + (local.get $12) + (i32.const 10) + ) + (local.get $6) + ) + ) + (if + (i32.lt_u + (local.tee $9 + (i32.sub + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + (i32.const 48) + ) + ) + (i32.const 10) + ) + (block + (local.set $12 + (local.get $6) + ) + (local.set $6 + (local.get $9) + ) + (br $while-in8) + ) + ) + ) + (if (result i32) + (i32.lt_s + (local.get $6) + (i32.const 0) + ) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + (block (result i32) + (local.set $12 + (local.get $1) + ) + (local.set $17 + (local.get $6) + ) + (local.get $8) + ) + ) + ) + (block (result i32) + (local.set $12 + (local.get $1) + ) + (local.set $17 + (i32.const 0) + ) + (local.get $8) + ) + ) + ) + ) + (local.set $6 + (if (result i32) + (i32.eq + (i32.load8_s + (local.get $10) + ) + (i32.const 46) + ) + (block $label$break$L46 (result i32) + (if + (i32.ne + (local.tee $8 + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + ) + (i32.const 42) + ) + (block + (local.set $6 + (if (result i32) + (i32.lt_u + (local.tee $9 + (i32.sub + (local.get $8) + (i32.const 48) + ) + ) + (i32.const 10) + ) + (block (result i32) + (local.set $10 + (local.get $6) + ) + (local.set $8 + (i32.const 0) + ) + (local.get $9) + ) + (block + (local.set $10 + (local.get $6) + ) + (br $label$break$L46 + (i32.const 0) + ) + ) + ) + ) + (loop $while-in11 + (drop + (br_if $label$break$L46 + (local.tee $8 + (i32.add + (i32.mul + (local.get $8) + (i32.const 10) + ) + (local.get $6) + ) + ) + (i32.ge_u + (local.tee $6 + (i32.sub + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + (i32.const 48) + ) + ) + (i32.const 10) + ) + ) + ) + (br $while-in11) + ) + ) + ) + (if + (i32.lt_u + (local.tee $8 + (i32.sub + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $10) + (i32.const 2) + ) + ) + ) + (i32.const 48) + ) + ) + (i32.const 10) + ) + (if + (i32.eq + (i32.load8_s offset=3 + (local.get $10) + ) + (i32.const 36) + ) + (block + (i32.store + (i32.add + (local.get $4) + (i32.shl + (local.get $8) + (i32.const 2) + ) + ) + (i32.const 10) + ) + (drop + (i32.load offset=4 + (local.tee $6 + (i32.add + (local.get $3) + (i32.shl + (i32.sub + (i32.load8_s + (local.get $6) + ) + (i32.const 48) + ) + (i32.const 3) + ) + ) + ) + ) + ) + (local.set $10 + (i32.add + (local.get $10) + (i32.const 4) + ) + ) + (br $label$break$L46 + (i32.load + (local.get $6) + ) + ) + ) + ) + ) + (if + (local.get $1) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (if (result i32) + (local.get $28) + (block (result i32) + (local.set $8 + (i32.load + (local.tee $10 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $10) + (i32.const 4) + ) + ) + (local.set $10 + (local.get $6) + ) + (local.get $8) + ) + (block (result i32) + (local.set $10 + (local.get $6) + ) + (i32.const 0) + ) + ) + ) + (i32.const -1) + ) + ) + (local.set $8 + (local.get $10) + ) + (local.set $9 + (i32.const 0) + ) + (local.set $16 + (loop $while-in13 (result i32) + (if + (i32.gt_u + (local.tee $11 + (i32.sub + (i32.load8_s + (local.get $8) + ) + (i32.const 65) + ) + ) + (i32.const 57) + ) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (local.set $10 + (i32.add + (local.get $8) + (i32.const 1) + ) + ) + (if (result i32) + (i32.lt_u + (i32.sub + (local.tee $11 + (i32.and + (local.tee $15 + (i32.load8_s + (i32.add + (i32.add + (i32.mul + (local.get $9) + (i32.const 58) + ) + (i32.const 3611) + ) + (local.get $11) + ) + ) + ) + (i32.const 255) + ) + ) + (i32.const 1) + ) + (i32.const 8) + ) + (block + (local.set $8 + (local.get $10) + ) + (local.set $9 + (local.get $11) + ) + (br $while-in13) + ) + (local.get $8) + ) + ) + ) + (if + (i32.eqz + (i32.and + (local.get $15) + (i32.const 255) + ) + ) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (local.set $8 + (i32.gt_s + (local.get $19) + (i32.const -1) + ) + ) + (block $__rjto$2 + (block $__rjti$2 + (if + (i32.eq + (i32.and + (local.get $15) + (i32.const 255) + ) + (i32.const 19) + ) + (if + (local.get $8) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + (br $__rjti$2) + ) + (block + (if + (local.get $8) + (block + (i32.store + (i32.add + (local.get $4) + (i32.shl + (local.get $19) + (i32.const 2) + ) + ) + (local.get $11) + ) + (local.set $11 + (i32.load offset=4 + (local.tee $8 + (i32.add + (local.get $3) + (i32.shl + (local.get $19) + (i32.const 3) + ) + ) + ) + ) + ) + (i32.store + (local.get $13) + (i32.load + (local.get $8) + ) + ) + (i32.store offset=4 + (local.get $13) + (local.get $11) + ) + (br $__rjti$2) + ) + ) + (if + (i32.eqz + (local.get $28) + ) + (block + (local.set $18 + (i32.const 0) + ) + (br $label$break$L1) + ) + ) + (call $_pop_arg_336 + (local.get $13) + (local.get $11) + (local.get $2) + ) + ) + ) + (br $__rjto$2) + ) + (if + (i32.eqz + (local.get $28) + ) + (block + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + ) + ) + (local.set $12 + (select + (local.tee $8 + (i32.and + (local.get $12) + (i32.const -65537) + ) + ) + (local.get $12) + (i32.and + (local.get $12) + (i32.const 8192) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.tee $6 + (select + (local.tee $5 + (i32.add + (local.tee $11 + (select + (local.tee $16 + (i32.sub + (block $__rjto$8 (result i32) + (block $__rjti$8 + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.tee $7 + (block $__rjti$7 (result i32) + (block $__rjti$6 + (block $__rjti$5 + (block $__rjti$4 + (block $__rjti$3 + (block $switch-default120 + (block $switch-case42 + (block $switch-case41 + (block $switch-case40 + (block $switch-case39 + (block $switch-case38 + (block $switch-case37 + (block $switch-case36 + (block $switch-case34 + (block $switch-case33 + (block $switch-case29 + (block $switch-case28 + (block $switch-case27 + (br_table $switch-case42 $switch-default120 $switch-case40 $switch-default120 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case41 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case29 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case42 $switch-default120 $switch-case37 $switch-case34 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-case34 $switch-default120 $switch-default120 $switch-default120 $switch-case38 $switch-case27 $switch-case33 $switch-case28 $switch-default120 $switch-default120 $switch-case39 $switch-default120 $switch-case36 $switch-default120 $switch-default120 $switch-case29 $switch-default120 + (i32.sub + (local.tee $16 + (select + (i32.and + (local.tee $11 + (i32.load8_s + (local.get $16) + ) + ) + (i32.const -33) + ) + (local.get $11) + (i32.and + (i32.eq + (i32.and + (local.get $11) + (i32.const 15) + ) + (i32.const 3) + ) + (i32.ne + (local.get $9) + (i32.const 0) + ) + ) + ) + ) + (i32.const 65) + ) + ) + ) + (block $switch-default26 + (block $switch-case25 + (block $switch-case24 + (block $switch-case23 + (block $switch-case22 + (block $switch-case21 + (block $switch-case20 + (block $switch-case19 + (br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26 + (local.get $9) + ) + ) + (i32.store + (i32.load + (local.get $13) + ) + (local.get $18) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (i32.load + (local.get $13) + ) + (local.get $18) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (local.tee $5 + (i32.load + (local.get $13) + ) + ) + (local.get $18) + ) + (i32.store offset=4 + (local.get $5) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $18) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store16 + (i32.load + (local.get $13) + ) + (local.get $18) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store8 + (i32.load + (local.get $13) + ) + (local.get $18) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (i32.load + (local.get $13) + ) + (local.get $18) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (local.tee $5 + (i32.load + (local.get $13) + ) + ) + (local.get $18) + ) + (i32.store offset=4 + (local.get $5) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $18) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (local.set $7 + (i32.or + (local.get $12) + (i32.const 8) + ) + ) + (local.set $6 + (select + (local.get $6) + (i32.const 8) + (i32.gt_u + (local.get $6) + (i32.const 8) + ) + ) + ) + (local.set $16 + (i32.const 120) + ) + (br $__rjti$3) + ) + (local.set $7 + (local.get $12) + ) + (br $__rjti$3) + ) + (if + (i32.or + (local.tee $5 + (i32.load + (local.get $13) + ) + ) + (local.tee $7 + (i32.load offset=4 + (local.get $13) + ) + ) + ) + (block + (local.set $8 + (local.get $25) + ) + (loop $while-in32 + (i32.store8 + (local.tee $8 + (i32.sub + (local.get $8) + (i32.const 1) + ) + ) + (i32.or + (i32.and + (local.get $5) + (i32.const 7) + ) + (i32.const 48) + ) + ) + (br_if $while-in32 + (i32.or + (local.tee $5 + (call $_bitshift64Lshr + (local.get $5) + (local.get $7) + (i32.const 3) + ) + ) + (local.tee $7 + (global.get $tempRet0) + ) + ) + ) + ) + ) + (local.set $8 + (local.get $25) + ) + ) + (if + (i32.and + (local.get $12) + (i32.const 8) + ) + (block + (local.set $7 + (local.get $12) + ) + (local.set $6 + (select + (local.tee $5 + (i32.add + (i32.sub + (local.get $37) + (local.get $8) + ) + (i32.const 1) + ) + ) + (local.get $6) + (i32.gt_s + (local.get $5) + (local.get $6) + ) + ) + ) + ) + (local.set $7 + (local.get $12) + ) + ) + (local.set $5 + (local.get $8) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$8) + ) + (local.set $5 + (i32.load + (local.get $13) + ) + ) + (if + (i32.lt_s + (local.tee $7 + (i32.load offset=4 + (local.get $13) + ) + ) + (i32.const 0) + ) + (block + (global.set $tempRet0 + (i32.sub + (i32.sub + (i32.const 0) + (local.get $7) + ) + (i32.ne + (local.get $5) + (i32.const 0) + ) + ) + ) + (i32.store + (local.get $13) + (local.tee $5 + (i32.sub + (i32.const 0) + (local.get $5) + ) + ) + ) + (i32.store offset=4 + (local.get $13) + (local.tee $7 + (global.get $tempRet0) + ) + ) + (local.set $8 + (i32.const 1) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$4) + ) + ) + (local.set $9 + (if (result i32) + (i32.and + (local.get $12) + (i32.const 2048) + ) + (block (result i32) + (local.set $8 + (i32.const 1) + ) + (i32.const 4092) + ) + (block (result i32) + (local.set $8 + (local.tee $9 + (i32.and + (local.get $12) + (i32.const 1) + ) + ) + ) + (select + (i32.const 4093) + (i32.const 4091) + (local.get $9) + ) + ) + ) + ) + (br $__rjti$4) + ) + (local.set $5 + (i32.load + (local.get $13) + ) + ) + (local.set $7 + (i32.load offset=4 + (local.get $13) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$4) + ) + (drop + (i32.load offset=4 + (local.get $13) + ) + ) + (i32.store8 + (local.get $38) + (i32.load + (local.get $13) + ) + ) + (local.set $7 + (local.get $38) + ) + (local.set $12 + (local.get $8) + ) + (local.set $11 + (i32.const 1) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjto$8 + (local.get $25) + ) + ) + (local.set $5 + (call $_strerror + (i32.load + (call $___errno_location) + ) + ) + ) + (br $__rjti$5) + ) + (local.set $5 + (select + (local.tee $5 + (i32.load + (local.get $13) + ) + ) + (i32.const 4101) + (local.get $5) + ) + ) + (br $__rjti$5) + ) + (drop + (i32.load offset=4 + (local.get $13) + ) + ) + (i32.store + (local.get $39) + (i32.load + (local.get $13) + ) + ) + (i32.store + (local.get $42) + (i32.const 0) + ) + (i32.store + (local.get $13) + (local.get $39) + ) + (local.set $8 + (i32.const -1) + ) + (br $__rjti$6) + ) + (if + (local.get $6) + (block + (local.set $8 + (local.get $6) + ) + (br $__rjti$6) + ) + (block + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (i32.const 0) + (local.get $12) + ) + (br $__rjti$7 + (i32.const 0) + ) + ) + ) + ) + (local.set $14 + (f64.load + (local.get $13) + ) + ) + (i32.store + (local.get $21) + (i32.const 0) + ) + (f64.store + (global.get $tempDoublePtr) + (local.get $14) + ) + (drop + (i32.load + (global.get $tempDoublePtr) + ) + ) + (local.set $30 + (if (result i32) + (i32.lt_s + (i32.load offset=4 + (global.get $tempDoublePtr) + ) + (i32.const 0) + ) + (block (result i32) + (local.set $27 + (i32.const 1) + ) + (local.set $14 + (f64.neg + (local.get $14) + ) + ) + (i32.const 4108) + ) + (if (result i32) + (i32.and + (local.get $12) + (i32.const 2048) + ) + (block (result i32) + (local.set $27 + (i32.const 1) + ) + (i32.const 4111) + ) + (block (result i32) + (local.set $27 + (local.tee $5 + (i32.and + (local.get $12) + (i32.const 1) + ) + ) + ) + (select + (i32.const 4114) + (i32.const 4109) + (local.get $5) + ) + ) + ) + ) + ) + (f64.store + (global.get $tempDoublePtr) + (local.get $14) + ) + (drop + (i32.load + (global.get $tempDoublePtr) + ) + ) + (local.set $7 + (if (result i32) + (i32.lt_u + (i32.and + (i32.load offset=4 + (global.get $tempDoublePtr) + ) + (i32.const 2146435072) + ) + (i32.const 2146435072) + ) + (block $do-once49 (result i32) + (if + (local.tee $5 + (f64.ne + (local.tee $24 + (f64.mul + (call $_frexp + (local.get $14) + (local.get $21) + ) + (f64.const 2) + ) + ) + (f64.const 0) + ) + ) + (i32.store + (local.get $21) + (i32.sub + (i32.load + (local.get $21) + ) + (i32.const 1) + ) + ) + ) + (if + (i32.eq + (local.tee $26 + (i32.or + (local.get $16) + (i32.const 32) + ) + ) + (i32.const 97) + ) + (block + (local.set $9 + (select + (i32.add + (local.get $30) + (i32.const 9) + ) + (local.get $30) + (local.tee $15 + (i32.and + (local.get $16) + (i32.const 32) + ) + ) + ) + ) + (local.set $14 + (if (result f64) + (i32.or + (i32.eqz + (local.tee $5 + (i32.sub + (i32.const 12) + (local.get $6) + ) + ) + ) + (i32.gt_u + (local.get $6) + (i32.const 11) + ) + ) + (local.get $24) + (block (result f64) + (local.set $14 + (f64.const 8) + ) + (loop $while-in54 + (local.set $14 + (f64.mul + (local.get $14) + (f64.const 16) + ) + ) + (br_if $while-in54 + (local.tee $5 + (i32.sub + (local.get $5) + (i32.const 1) + ) + ) + ) + ) + (select + (f64.neg + (f64.add + (local.get $14) + (f64.sub + (f64.neg + (local.get $24) + ) + (local.get $14) + ) + ) + ) + (f64.sub + (f64.add + (local.get $24) + (local.get $14) + ) + (local.get $14) + ) + (i32.eq + (i32.load8_s + (local.get $9) + ) + (i32.const 45) + ) + ) + ) + ) + ) + (local.set $11 + (i32.or + (local.get $27) + (i32.const 2) + ) + ) + (if + (i32.eq + (local.tee $5 + (call $_fmt_u + (local.tee $5 + (select + (i32.sub + (i32.const 0) + (local.tee $7 + (i32.load + (local.get $21) + ) + ) + ) + (local.get $7) + (i32.lt_s + (local.get $7) + (i32.const 0) + ) + ) + ) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + (local.get $22) + ) + ) + (local.get $22) + ) + (block + (i32.store8 + (local.get $40) + (i32.const 48) + ) + (local.set $5 + (local.get $40) + ) + ) + ) + (i32.store8 + (i32.sub + (local.get $5) + (i32.const 1) + ) + (i32.add + (i32.and + (i32.shr_s + (local.get $7) + (i32.const 31) + ) + (i32.const 2) + ) + (i32.const 43) + ) + ) + (i32.store8 + (local.tee $8 + (i32.sub + (local.get $5) + (i32.const 2) + ) + ) + (i32.add + (local.get $16) + (i32.const 15) + ) + ) + (local.set $16 + (i32.lt_s + (local.get $6) + (i32.const 1) + ) + ) + (local.set $20 + (i32.eqz + (i32.and + (local.get $12) + (i32.const 8) + ) + ) + ) + (local.set $5 + (local.get $23) + ) + (loop $while-in56 + (i32.store8 + (local.get $5) + (i32.or + (i32.load8_u + (i32.add + (local.tee $7 + (if (result i32) + (f64.ne + (local.get $14) + (local.get $14) + ) + (i32.const -2147483648) + (if (result i32) + (f64.ge + (local.get $14) + (f64.const 2147483648) + ) + (i32.const -2147483648) + (if (result i32) + (f64.le + (local.get $14) + (f64.const -2147483649) + ) + (i32.const -2147483648) + (i32.trunc_f64_s + (local.get $14) + ) + ) + ) + ) + ) + (i32.const 4075) + ) + ) + (local.get $15) + ) + ) + (local.set $14 + (f64.mul + (f64.sub + (local.get $14) + (f64.convert_i32_s + (local.get $7) + ) + ) + (f64.const 16) + ) + ) + (local.set $5 + (if (result i32) + (i32.eq + (i32.sub + (local.tee $7 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (local.get $34) + ) + (i32.const 1) + ) + (if (result i32) + (i32.and + (local.get $20) + (i32.and + (local.get $16) + (f64.eq + (local.get $14) + (f64.const 0) + ) + ) + ) + (local.get $7) + (block (result i32) + (i32.store8 + (local.get $7) + (i32.const 46) + ) + (i32.add + (local.get $5) + (i32.const 2) + ) + ) + ) + (local.get $7) + ) + ) + (br_if $while-in56 + (f64.ne + (local.get $14) + (f64.const 0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.tee $7 + (i32.add + (local.tee $6 + (select + (i32.sub + (i32.add + (local.get $6) + (local.get $45) + ) + (local.get $8) + ) + (i32.add + (i32.sub + (local.get $43) + (local.get $8) + ) + (local.get $5) + ) + (i32.and + (i32.ne + (local.get $6) + (i32.const 0) + ) + (i32.lt_s + (i32.add + (local.get $5) + (local.get $44) + ) + (local.get $6) + ) + ) + ) + ) + (local.get $11) + ) + ) + (local.get $12) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $9) + (local.get $11) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $17) + (local.get $7) + (i32.xor + (local.get $12) + (i32.const 65536) + ) + ) + (local.set $5 + (i32.sub + (local.get $5) + (local.get $34) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $23) + (local.get $5) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (i32.sub + (local.get $6) + (i32.add + (local.get $5) + (local.tee $6 + (i32.sub + (local.get $22) + (local.get $8) + ) + ) + ) + ) + (i32.const 0) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $8) + (local.get $6) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.get $7) + (i32.xor + (local.get $12) + (i32.const 8192) + ) + ) + (br $do-once49 + (select + (local.get $17) + (local.get $7) + (i32.lt_s + (local.get $7) + (local.get $17) + ) + ) + ) + ) + ) + (local.set $14 + (if (result f64) + (local.get $5) + (block (result f64) + (i32.store + (local.get $21) + (local.tee $5 + (i32.sub + (i32.load + (local.get $21) + ) + (i32.const 28) + ) + ) + ) + (f64.mul + (local.get $24) + (f64.const 268435456) + ) + ) + (block (result f64) + (local.set $5 + (i32.load + (local.get $21) + ) + ) + (local.get $24) + ) + ) + ) + (local.set $7 + (local.tee $8 + (select + (local.get $46) + (local.get $47) + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + ) + ) + ) + (loop $while-in60 + (i32.store + (local.get $7) + (local.tee $5 + (if (result i32) + (f64.ne + (local.get $14) + (local.get $14) + ) + (i32.const -2147483648) + (if (result i32) + (f64.ge + (local.get $14) + (f64.const 2147483648) + ) + (i32.const -2147483648) + (if (result i32) + (f64.le + (local.get $14) + (f64.const -2147483649) + ) + (i32.const -2147483648) + (i32.trunc_f64_s + (local.get $14) + ) + ) + ) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (br_if $while-in60 + (f64.ne + (local.tee $14 + (f64.mul + (f64.sub + (local.get $14) + (f64.convert_i32_u + (local.get $5) + ) + ) + (f64.const 1e9) + ) + ) + (f64.const 0) + ) + ) + ) + (if + (i32.gt_s + (local.tee $9 + (i32.load + (local.get $21) + ) + ) + (i32.const 0) + ) + (block + (local.set $5 + (local.get $8) + ) + (loop $while-in62 + (local.set $15 + (select + (i32.const 29) + (local.get $9) + (i32.gt_s + (local.get $9) + (i32.const 29) + ) + ) + ) + (if + (i32.ge_u + (local.tee $9 + (i32.sub + (local.get $7) + (i32.const 4) + ) + ) + (local.get $5) + ) + (block $do-once63 + (local.set $11 + (i32.const 0) + ) + (loop $while-in66 + (i32.store + (local.get $9) + (call $___uremdi3 + (block (result i32) + (global.set $tempRet0 + (i32.add + (i32.gt_u + (local.tee $20 + (call $_bitshift64Shl + (i32.load + (local.get $9) + ) + (i32.const 0) + (local.get $15) + ) + ) + (local.tee $11 + (i32.add + (local.get $11) + (local.get $20) + ) + ) + ) + (global.get $tempRet0) + ) + ) + (local.get $11) + ) + (local.tee $20 + (global.get $tempRet0) + ) + (i32.const 1000000000) + (i32.const 0) + ) + ) + (local.set $11 + (call $___udivdi3 + (local.get $11) + (local.get $20) + (i32.const 1000000000) + (i32.const 0) + ) + ) + (br_if $while-in66 + (i32.ge_u + (local.tee $9 + (i32.sub + (local.get $9) + (i32.const 4) + ) + ) + (local.get $5) + ) + ) + ) + (br_if $do-once63 + (i32.eqz + (local.get $11) + ) + ) + (i32.store + (local.tee $5 + (i32.sub + (local.get $5) + (i32.const 4) + ) + ) + (local.get $11) + ) + ) + ) + (loop $while-in68 + (if + (i32.lt_u + (local.get $5) + (local.get $7) + ) + (if + (i32.eqz + (i32.load + (local.tee $9 + (i32.sub + (local.get $7) + (i32.const 4) + ) + ) + ) + ) + (block + (local.set $7 + (local.get $9) + ) + (br $while-in68) + ) + ) + ) + ) + (i32.store + (local.get $21) + (local.tee $9 + (i32.sub + (i32.load + (local.get $21) + ) + (local.get $15) + ) + ) + ) + (br_if $while-in62 + (i32.gt_s + (local.get $9) + (i32.const 0) + ) + ) + ) + ) + (local.set $5 + (local.get $8) + ) + ) + (local.set $19 + (select + (i32.const 6) + (local.get $6) + (i32.lt_s + (local.get $6) + (i32.const 0) + ) + ) + ) + (if + (i32.lt_s + (local.get $9) + (i32.const 0) + ) + (block + (local.set $20 + (i32.add + (i32.div_s + (i32.add + (local.get $19) + (i32.const 25) + ) + (i32.const 9) + ) + (i32.const 1) + ) + ) + (local.set $31 + (i32.eq + (local.get $26) + (i32.const 102) + ) + ) + (local.set $6 + (local.get $5) + ) + (local.set $5 + (local.get $7) + ) + (local.set $5 + (loop $while-in70 (result i32) + (local.set $15 + (select + (i32.const 9) + (local.tee $7 + (i32.sub + (i32.const 0) + (local.get $9) + ) + ) + (i32.gt_s + (local.get $7) + (i32.const 9) + ) + ) + ) + (if + (i32.gt_u + (local.get $5) + (local.get $6) + ) + (block $do-once71 + (local.set $11 + (i32.sub + (i32.shl + (i32.const 1) + (local.get $15) + ) + (i32.const 1) + ) + ) + (local.set $35 + (i32.shr_u + (i32.const 1000000000) + (local.get $15) + ) + ) + (local.set $9 + (i32.const 0) + ) + (local.set $7 + (local.get $6) + ) + (loop $while-in74 + (i32.store + (local.get $7) + (i32.add + (local.get $9) + (i32.shr_u + (local.tee $9 + (i32.load + (local.get $7) + ) + ) + (local.get $15) + ) + ) + ) + (local.set $9 + (i32.mul + (i32.and + (local.get $9) + (local.get $11) + ) + (local.get $35) + ) + ) + (br_if $while-in74 + (i32.lt_u + (local.tee $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (local.get $5) + ) + ) + ) + (local.set $7 + (select + (local.get $6) + (i32.add + (local.get $6) + (i32.const 4) + ) + (i32.load + (local.get $6) + ) + ) + ) + (br_if $do-once71 + (i32.eqz + (local.get $9) + ) + ) + (i32.store + (local.get $5) + (local.get $9) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 4) + ) + ) + ) + (local.set $7 + (select + (local.get $6) + (i32.add + (local.get $6) + (i32.const 4) + ) + (i32.load + (local.get $6) + ) + ) + ) + ) + (local.set $11 + (select + (i32.add + (local.tee $6 + (select + (local.get $8) + (local.get $7) + (local.get $31) + ) + ) + (i32.shl + (local.get $20) + (i32.const 2) + ) + ) + (local.get $5) + (i32.gt_s + (i32.shr_s + (i32.sub + (local.get $5) + (local.get $6) + ) + (i32.const 2) + ) + (local.get $20) + ) + ) + ) + (i32.store + (local.get $21) + (local.tee $9 + (i32.add + (i32.load + (local.get $21) + ) + (local.get $15) + ) + ) + ) + (if (result i32) + (i32.lt_s + (local.get $9) + (i32.const 0) + ) + (block + (local.set $6 + (local.get $7) + ) + (local.set $5 + (local.get $11) + ) + (br $while-in70) + ) + (block (result i32) + (local.set $9 + (local.get $11) + ) + (local.get $7) + ) + ) + ) + ) + ) + (local.set $9 + (local.get $7) + ) + ) + (local.set $20 + (local.get $8) + ) + (if + (i32.lt_u + (local.get $5) + (local.get $9) + ) + (block $do-once75 + (local.set $7 + (i32.mul + (i32.shr_s + (i32.sub + (local.get $20) + (local.get $5) + ) + (i32.const 2) + ) + (i32.const 9) + ) + ) + (br_if $do-once75 + (i32.lt_u + (local.tee $8 + (i32.load + (local.get $5) + ) + ) + (i32.const 10) + ) + ) + (local.set $6 + (i32.const 10) + ) + (loop $while-in78 + (local.set $7 + (i32.add + (local.get $7) + (i32.const 1) + ) + ) + (br_if $while-in78 + (i32.ge_u + (local.get $8) + (local.tee $6 + (i32.mul + (local.get $6) + (i32.const 10) + ) + ) + ) + ) + ) + ) + (local.set $7 + (i32.const 0) + ) + ) + (local.set $5 + (if (result i32) + (i32.lt_s + (local.tee $6 + (i32.add + (i32.sub + (local.get $19) + (select + (local.get $7) + (i32.const 0) + (i32.ne + (local.get $26) + (i32.const 102) + ) + ) + ) + (i32.shr_s + (i32.shl + (i32.and + (local.tee $31 + (i32.ne + (local.get $19) + (i32.const 0) + ) + ) + (local.tee $35 + (i32.eq + (local.get $26) + (i32.const 103) + ) + ) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + ) + (i32.sub + (i32.mul + (i32.shr_s + (i32.sub + (local.get $9) + (local.get $20) + ) + (i32.const 2) + ) + (i32.const 9) + ) + (i32.const 9) + ) + ) + (block (result i32) + (local.set $8 + (i32.div_s + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 9216) + ) + ) + (i32.const 9) + ) + ) + (if + (i32.lt_s + (local.tee $6 + (i32.add + (i32.rem_s + (local.get $6) + (i32.const 9) + ) + (i32.const 1) + ) + ) + (i32.const 9) + ) + (block + (local.set $11 + (i32.const 10) + ) + (loop $while-in80 + (local.set $11 + (i32.mul + (local.get $11) + (i32.const 10) + ) + ) + (br_if $while-in80 + (i32.ne + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 1) + ) + ) + (i32.const 9) + ) + ) + ) + ) + (local.set $11 + (i32.const 10) + ) + ) + (local.set $15 + (local.tee $8 + (i32.load + (local.tee $6 + (i32.sub + (i32.add + (local.get $20) + (i32.shl + (local.get $8) + (i32.const 2) + ) + ) + (i32.const 4092) + ) + ) + ) + ) + ) + (local.set $15 + (if (result i32) + (local.get $11) + (i32.rem_u + (local.get $15) + (local.get $11) + ) + (i32.const 0) + ) + ) + (if + (i32.eqz + (i32.and + (local.tee $26 + (i32.eq + (i32.add + (local.get $6) + (i32.const 4) + ) + (local.get $9) + ) + ) + (i32.eqz + (local.get $15) + ) + ) + ) + (block $do-once81 + (local.set $36 + (if (result i32) + (local.get $11) + (i32.div_u + (local.get $8) + (local.get $11) + ) + (i32.const 0) + ) + ) + (local.set $14 + (if (result f64) + (i32.lt_u + (local.get $15) + (local.tee $48 + (i32.div_s + (local.get $11) + (i32.const 2) + ) + ) + ) + (f64.const 0.5) + (select + (f64.const 1) + (f64.const 1.5) + (i32.and + (local.get $26) + (i32.eq + (local.get $15) + (local.get $48) + ) + ) + ) + ) + ) + (local.set $24 + (select + (f64.const 9007199254740994) + (f64.const 9007199254740992) + (i32.and + (local.get $36) + (i32.const 1) + ) + ) + ) + (if + (local.get $27) + (if + (i32.eq + (i32.load8_s + (local.get $30) + ) + (i32.const 45) + ) + (block + (local.set $24 + (f64.neg + (local.get $24) + ) + ) + (local.set $14 + (f64.neg + (local.get $14) + ) + ) + ) + ) + ) + (i32.store + (local.get $6) + (local.tee $8 + (i32.sub + (local.get $8) + (local.get $15) + ) + ) + ) + (br_if $do-once81 + (f64.eq + (f64.add + (local.get $24) + (local.get $14) + ) + (local.get $24) + ) + ) + (i32.store + (local.get $6) + (local.tee $7 + (i32.add + (local.get $8) + (local.get $11) + ) + ) + ) + (if + (i32.gt_u + (local.get $7) + (i32.const 999999999) + ) + (loop $while-in86 + (i32.store + (local.get $6) + (i32.const 0) + ) + (if + (i32.lt_u + (local.tee $6 + (i32.sub + (local.get $6) + (i32.const 4) + ) + ) + (local.get $5) + ) + (i32.store + (local.tee $5 + (i32.sub + (local.get $5) + (i32.const 4) + ) + ) + (i32.const 0) + ) + ) + (i32.store + (local.get $6) + (local.tee $7 + (i32.add + (i32.load + (local.get $6) + ) + (i32.const 1) + ) + ) + ) + (br_if $while-in86 + (i32.gt_u + (local.get $7) + (i32.const 999999999) + ) + ) + ) + ) + (local.set $7 + (i32.mul + (i32.shr_s + (i32.sub + (local.get $20) + (local.get $5) + ) + (i32.const 2) + ) + (i32.const 9) + ) + ) + (br_if $do-once81 + (i32.lt_u + (local.tee $8 + (i32.load + (local.get $5) + ) + ) + (i32.const 10) + ) + ) + (local.set $11 + (i32.const 10) + ) + (loop $while-in88 + (local.set $7 + (i32.add + (local.get $7) + (i32.const 1) + ) + ) + (br_if $while-in88 + (i32.ge_u + (local.get $8) + (local.tee $11 + (i32.mul + (local.get $11) + (i32.const 10) + ) + ) + ) + ) + ) + ) + ) + (local.set $11 + (local.get $5) + ) + (local.set $8 + (local.get $7) + ) + (select + (local.tee $5 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (local.get $9) + (i32.lt_u + (local.get $5) + (local.get $9) + ) + ) + ) + (block (result i32) + (local.set $11 + (local.get $5) + ) + (local.set $8 + (local.get $7) + ) + (local.get $9) + ) + ) + ) + (local.set $36 + (i32.sub + (i32.const 0) + (local.get $8) + ) + ) + (local.set $9 + (loop $while-in90 (result i32) + (block $while-out89 (result i32) + (if + (i32.le_u + (local.get $5) + (local.get $11) + ) + (block + (local.set $26 + (i32.const 0) + ) + (br $while-out89 + (local.get $5) + ) + ) + ) + (if (result i32) + (i32.load + (local.tee $7 + (i32.sub + (local.get $5) + (i32.const 4) + ) + ) + ) + (block (result i32) + (local.set $26 + (i32.const 1) + ) + (local.get $5) + ) + (block + (local.set $5 + (local.get $7) + ) + (br $while-in90) + ) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.tee $8 + (i32.add + (i32.add + (i32.add + (local.tee $5 + (if (result i32) + (local.get $35) + (block $do-once91 (result i32) + (local.set $7 + (if (result i32) + (i32.and + (i32.gt_s + (local.tee $5 + (i32.add + (i32.xor + (local.get $31) + (i32.const 1) + ) + (local.get $19) + ) + ) + (local.get $8) + ) + (i32.gt_s + (local.get $8) + (i32.const -5) + ) + ) + (block (result i32) + (local.set $19 + (i32.sub + (i32.sub + (local.get $5) + (i32.const 1) + ) + (local.get $8) + ) + ) + (i32.sub + (local.get $16) + (i32.const 1) + ) + ) + (block (result i32) + (local.set $19 + (i32.sub + (local.get $5) + (i32.const 1) + ) + ) + (i32.sub + (local.get $16) + (i32.const 2) + ) + ) + ) + ) + (drop + (br_if $do-once91 + (local.get $19) + (local.tee $15 + (i32.and + (local.get $12) + (i32.const 8) + ) + ) + ) + ) + (if + (local.get $26) + (block $do-once93 + (if + (i32.eqz + (local.tee $16 + (i32.load + (i32.sub + (local.get $9) + (i32.const 4) + ) + ) + ) + ) + (block + (local.set $5 + (i32.const 9) + ) + (br $do-once93) + ) + ) + (local.set $5 + (if (result i32) + (i32.rem_u + (local.get $16) + (i32.const 10) + ) + (block + (local.set $5 + (i32.const 0) + ) + (br $do-once93) + ) + (block (result i32) + (local.set $6 + (i32.const 10) + ) + (i32.const 0) + ) + ) + ) + (loop $while-in96 + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br_if $while-in96 + (i32.eqz + (if (result i32) + (local.tee $15 + (local.tee $6 + (i32.mul + (local.get $6) + (i32.const 10) + ) + ) + ) + (i32.rem_u + (local.get $16) + (local.get $15) + ) + (i32.const 0) + ) + ) + ) + ) + ) + (local.set $5 + (i32.const 9) + ) + ) + (local.set $6 + (i32.sub + (i32.mul + (i32.shr_s + (i32.sub + (local.get $9) + (local.get $20) + ) + (i32.const 2) + ) + (i32.const 9) + ) + (i32.const 9) + ) + ) + (if (result i32) + (i32.eq + (i32.or + (local.get $7) + (i32.const 32) + ) + (i32.const 102) + ) + (block (result i32) + (local.set $15 + (i32.const 0) + ) + (select + (local.get $19) + (local.tee $5 + (select + (i32.const 0) + (local.tee $5 + (i32.sub + (local.get $6) + (local.get $5) + ) + ) + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + ) + ) + (i32.gt_s + (local.get $5) + (local.get $19) + ) + ) + ) + (block (result i32) + (local.set $15 + (i32.const 0) + ) + (select + (local.get $19) + (local.tee $5 + (select + (i32.const 0) + (local.tee $5 + (i32.sub + (i32.add + (local.get $6) + (local.get $8) + ) + (local.get $5) + ) + ) + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + ) + ) + (i32.gt_s + (local.get $5) + (local.get $19) + ) + ) + ) + ) + ) + (block (result i32) + (local.set $15 + (i32.and + (local.get $12) + (i32.const 8) + ) + ) + (local.set $7 + (local.get $16) + ) + (local.get $19) + ) + ) + ) + (i32.add + (local.get $27) + (i32.const 1) + ) + ) + (i32.ne + (local.tee $19 + (i32.or + (local.get $5) + (local.get $15) + ) + ) + (i32.const 0) + ) + ) + (if (result i32) + (local.tee $31 + (i32.eq + (i32.or + (local.get $7) + (i32.const 32) + ) + (i32.const 102) + ) + ) + (block (result i32) + (local.set $16 + (i32.const 0) + ) + (select + (local.get $8) + (i32.const 0) + (i32.gt_s + (local.get $8) + (i32.const 0) + ) + ) + ) + (block (result i32) + (if + (i32.lt_s + (i32.sub + (local.get $22) + (local.tee $6 + (call $_fmt_u + (local.tee $6 + (select + (local.get $36) + (local.get $8) + (i32.lt_s + (local.get $8) + (i32.const 0) + ) + ) + ) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $6) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + (local.get $22) + ) + ) + ) + (i32.const 2) + ) + (loop $while-in98 + (i32.store8 + (local.tee $6 + (i32.sub + (local.get $6) + (i32.const 1) + ) + ) + (i32.const 48) + ) + (br_if $while-in98 + (i32.lt_s + (i32.sub + (local.get $22) + (local.get $6) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.store8 + (i32.sub + (local.get $6) + (i32.const 1) + ) + (i32.add + (i32.and + (i32.shr_s + (local.get $8) + (i32.const 31) + ) + (i32.const 2) + ) + (i32.const 43) + ) + ) + (i32.store8 + (local.tee $16 + (i32.sub + (local.get $6) + (i32.const 2) + ) + ) + (local.get $7) + ) + (i32.sub + (local.get $22) + (local.get $16) + ) + ) + ) + ) + ) + (local.get $12) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $30) + (local.get $27) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $17) + (local.get $8) + (i32.xor + (local.get $12) + (i32.const 65536) + ) + ) + (if + (local.get $31) + (block + (local.set $6 + (local.tee $11 + (select + (local.get $20) + (local.get $11) + (i32.gt_u + (local.get $11) + (local.get $20) + ) + ) + ) + ) + (loop $while-in102 + (local.set $7 + (call $_fmt_u + (i32.load + (local.get $6) + ) + (i32.const 0) + (local.get $29) + ) + ) + (block $do-once103 + (if + (i32.eq + (local.get $6) + (local.get $11) + ) + (block + (br_if $do-once103 + (i32.ne + (local.get $7) + (local.get $29) + ) + ) + (i32.store8 + (local.get $32) + (i32.const 48) + ) + (local.set $7 + (local.get $32) + ) + ) + (block + (br_if $do-once103 + (i32.le_u + (local.get $7) + (local.get $23) + ) + ) + (loop $while-in106 + (i32.store8 + (local.tee $7 + (i32.sub + (local.get $7) + (i32.const 1) + ) + ) + (i32.const 48) + ) + (br_if $while-in106 + (i32.gt_u + (local.get $7) + (local.get $23) + ) + ) + ) + ) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $7) + (i32.sub + (local.get $41) + (local.get $7) + ) + (local.get $0) + ) + ) + ) + (if + (i32.le_u + (local.tee $7 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (local.get $20) + ) + (block + (local.set $6 + (local.get $7) + ) + (br $while-in102) + ) + ) + ) + (if + (local.get $19) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (i32.const 4143) + (i32.const 1) + (local.get $0) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (i32.add + (if (result i32) + (i32.and + (i32.lt_u + (local.get $7) + (local.get $9) + ) + (i32.gt_s + (local.get $5) + (i32.const 0) + ) + ) + (loop $while-in110 (result i32) + (if + (i32.gt_u + (local.tee $6 + (call $_fmt_u + (i32.load + (local.get $7) + ) + (i32.const 0) + (local.get $29) + ) + ) + (local.get $23) + ) + (loop $while-in112 + (i32.store8 + (local.tee $6 + (i32.sub + (local.get $6) + (i32.const 1) + ) + ) + (i32.const 48) + ) + (br_if $while-in112 + (i32.gt_u + (local.get $6) + (local.get $23) + ) + ) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $6) + (select + (i32.const 9) + (local.get $5) + (i32.gt_s + (local.get $5) + (i32.const 9) + ) + ) + (local.get $0) + ) + ) + ) + (local.set $6 + (i32.sub + (local.get $5) + (i32.const 9) + ) + ) + (if (result i32) + (i32.and + (i32.lt_u + (local.tee $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (local.get $9) + ) + (i32.gt_s + (local.get $5) + (i32.const 9) + ) + ) + (block + (local.set $5 + (local.get $6) + ) + (br $while-in110) + ) + (local.get $6) + ) + ) + (local.get $5) + ) + (i32.const 9) + ) + (i32.const 9) + (i32.const 0) + ) + ) + (block $do-once99 + (local.set $20 + (select + (local.get $9) + (i32.add + (local.get $11) + (i32.const 4) + ) + (local.get $26) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (i32.add + (if (result i32) + (i32.gt_s + (local.get $5) + (i32.const -1) + ) + (block (result i32) + (local.set $15 + (i32.eqz + (local.get $15) + ) + ) + (local.set $6 + (local.get $11) + ) + (local.set $7 + (local.get $5) + ) + (loop $while-in114 (result i32) + (if + (i32.eq + (local.tee $5 + (call $_fmt_u + (i32.load + (local.get $6) + ) + (i32.const 0) + (local.get $29) + ) + ) + (local.get $29) + ) + (block + (i32.store8 + (local.get $32) + (i32.const 48) + ) + (local.set $5 + (local.get $32) + ) + ) + ) + (block $do-once115 + (if + (i32.eq + (local.get $6) + (local.get $11) + ) + (block + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $5) + (i32.const 1) + (local.get $0) + ) + ) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br_if $do-once115 + (i32.and + (local.get $15) + (i32.lt_s + (local.get $7) + (i32.const 1) + ) + ) + ) + (br_if $do-once115 + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (i32.const 4143) + (i32.const 1) + (local.get $0) + ) + ) + ) + (block + (br_if $do-once115 + (i32.le_u + (local.get $5) + (local.get $23) + ) + ) + (loop $while-in118 + (i32.store8 + (local.tee $5 + (i32.sub + (local.get $5) + (i32.const 1) + ) + ) + (i32.const 48) + ) + (br_if $while-in118 + (i32.gt_u + (local.get $5) + (local.get $23) + ) + ) + ) + ) + ) + ) + (local.set $9 + (i32.sub + (local.get $41) + (local.get $5) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $5) + (select + (local.get $9) + (local.get $7) + (i32.gt_s + (local.get $7) + (local.get $9) + ) + ) + (local.get $0) + ) + ) + ) + (br_if $while-in114 + (i32.and + (i32.lt_u + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (local.get $20) + ) + (i32.gt_s + (local.tee $7 + (i32.sub + (local.get $7) + (local.get $9) + ) + ) + (i32.const -1) + ) + ) + ) + (local.get $7) + ) + ) + (local.get $5) + ) + (i32.const 18) + ) + (i32.const 18) + (i32.const 0) + ) + (br_if $do-once99 + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $16) + (i32.sub + (local.get $22) + (local.get $16) + ) + (local.get $0) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.get $8) + (i32.xor + (local.get $12) + (i32.const 8192) + ) + ) + (select + (local.get $17) + (local.get $8) + (i32.lt_s + (local.get $8) + (local.get $17) + ) + ) + ) + (block (result i32) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.tee $7 + (i32.add + (local.tee $9 + (select + (i32.const 0) + (local.get $27) + (local.tee $6 + (f64.ne + (local.get $14) + (local.get $14) + ) + ) + ) + ) + (i32.const 3) + ) + ) + (local.get $8) + ) + (local.set $6 + (select + (select + (i32.const 4135) + (i32.const 4139) + (local.tee $8 + (i32.ne + (i32.and + (local.get $16) + (i32.const 32) + ) + (i32.const 0) + ) + ) + ) + (select + (i32.const 4127) + (i32.const 4131) + (local.get $8) + ) + (local.get $6) + ) + ) + (if + (i32.eqz + (i32.and + (if (result i32) + (i32.and + (local.tee $5 + (i32.load + (local.get $0) + ) + ) + (i32.const 32) + ) + (local.get $5) + (block (result i32) + (drop + (call $___fwritex + (local.get $30) + (local.get $9) + (local.get $0) + ) + ) + (i32.load + (local.get $0) + ) + ) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $6) + (i32.const 3) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.get $7) + (i32.xor + (local.get $12) + (i32.const 8192) + ) + ) + (select + (local.get $17) + (local.get $7) + (i32.lt_s + (local.get $7) + (local.get $17) + ) + ) + ) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (local.set $7 + (local.get $5) + ) + (local.set $11 + (local.get $6) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjto$8 + (local.get $25) + ) + ) + (local.set $9 + (i32.and + (local.get $16) + (i32.const 32) + ) + ) + (if + (i32.or + (local.tee $5 + (i32.load + (local.get $13) + ) + ) + (local.tee $12 + (i32.load offset=4 + (local.get $13) + ) + ) + ) + (block + (local.set $8 + (local.get $25) + ) + (local.set $5 + (loop $while-in123 (result i32) + (i32.store8 + (local.tee $8 + (i32.sub + (local.get $8) + (i32.const 1) + ) + ) + (i32.or + (i32.load8_u + (i32.add + (i32.and + (local.get $5) + (i32.const 15) + ) + (i32.const 4075) + ) + ) + (local.get $9) + ) + ) + (br_if $while-in123 + (i32.or + (local.tee $5 + (call $_bitshift64Lshr + (local.get $5) + (local.get $12) + (i32.const 4) + ) + ) + (local.tee $12 + (global.get $tempRet0) + ) + ) + ) + (local.get $8) + ) + ) + (local.set $8 + (if (result i32) + (i32.or + (i32.eqz + (i32.and + (local.get $7) + (i32.const 8) + ) + ) + (i32.eqz + (i32.or + (i32.load + (local.get $13) + ) + (i32.load offset=4 + (local.get $13) + ) + ) + ) + ) + (block (result i32) + (local.set $9 + (i32.const 4091) + ) + (i32.const 0) + ) + (block (result i32) + (local.set $9 + (i32.add + (i32.shr_s + (local.get $16) + (i32.const 4) + ) + (i32.const 4091) + ) + ) + (i32.const 2) + ) + ) + ) + ) + (block + (local.set $5 + (local.get $25) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + ) + ) + (br $__rjti$8) + ) + (local.set $5 + (call $_fmt_u + (local.get $5) + (local.get $7) + (local.get $25) + ) + ) + (local.set $7 + (local.get $12) + ) + (br $__rjti$8) + ) + (local.set $15 + (i32.eqz + (local.tee $16 + (call $_memchr + (local.get $5) + (i32.const 0) + (local.get $6) + ) + ) + ) + ) + (local.set $12 + (local.get $8) + ) + (local.set $11 + (select + (local.get $6) + (i32.sub + (local.get $16) + (local.tee $7 + (local.get $5) + ) + ) + (local.get $15) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjto$8 + (select + (i32.add + (local.get $5) + (local.get $6) + ) + (local.get $16) + (local.get $15) + ) + ) + ) + (local.set $5 + (i32.const 0) + ) + (local.set $7 + (i32.const 0) + ) + (local.set $6 + (i32.load + (local.get $13) + ) + ) + (loop $while-in125 + (block $while-out124 + (br_if $while-out124 + (i32.eqz + (local.tee $9 + (i32.load + (local.get $6) + ) + ) + ) + ) + (br_if $while-out124 + (i32.or + (i32.lt_s + (local.tee $7 + (call $_wctomb + (local.get $33) + (local.get $9) + ) + ) + (i32.const 0) + ) + (i32.gt_u + (local.get $7) + (i32.sub + (local.get $8) + (local.get $5) + ) + ) + ) + ) + (local.set $6 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (br_if $while-in125 + (i32.gt_u + (local.get $8) + (local.tee $5 + (i32.add + (local.get $5) + (local.get $7) + ) + ) + ) + ) + ) + ) + (if + (i32.lt_s + (local.get $7) + (i32.const 0) + ) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $17) + (local.get $5) + (local.get $12) + ) + (if (result i32) + (local.get $5) + (block (result i32) + (local.set $6 + (i32.const 0) + ) + (local.set $7 + (i32.load + (local.get $13) + ) + ) + (loop $while-in127 (result i32) + (drop + (br_if $__rjti$7 + (local.get $5) + (i32.eqz + (local.tee $8 + (i32.load + (local.get $7) + ) + ) + ) + ) + ) + (drop + (br_if $__rjti$7 + (local.get $5) + (i32.gt_s + (local.tee $6 + (i32.add + (local.tee $8 + (call $_wctomb + (local.get $33) + (local.get $8) + ) + ) + (local.get $6) + ) + ) + (local.get $5) + ) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $33) + (local.get $8) + (local.get $0) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (br_if $while-in127 + (i32.gt_u + (local.get $5) + (local.get $6) + ) + ) + (local.get $5) + ) + ) + (i32.const 0) + ) + ) + ) + (i32.xor + (local.get $12) + (i32.const 8192) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (select + (local.get $17) + (local.get $7) + (i32.lt_s + (local.get $7) + (local.get $17) + ) + ) + ) + (br $label$continue$L1) + ) + (local.set $12 + (select + (i32.and + (local.get $7) + (i32.const -65537) + ) + (local.get $7) + (i32.gt_s + (local.get $6) + (i32.const -1) + ) + ) + ) + (local.set $11 + (if (result i32) + (i32.or + (local.get $6) + (local.tee $11 + (i32.or + (i32.ne + (i32.load + (local.get $13) + ) + (i32.const 0) + ) + (i32.ne + (i32.load offset=4 + (local.get $13) + ) + (i32.const 0) + ) + ) + ) + ) + (select + (local.get $6) + (local.tee $5 + (i32.add + (i32.sub + (local.get $37) + (local.tee $7 + (local.get $5) + ) + ) + (i32.xor + (local.get $11) + (i32.const 1) + ) + ) + ) + (i32.lt_s + (local.get $5) + (local.get $6) + ) + ) + (block (result i32) + (local.set $7 + (local.get $25) + ) + (i32.const 0) + ) + ) + ) + (local.get $25) + ) + (local.get $7) + ) + ) + (local.get $11) + (i32.lt_s + (local.get $11) + (local.get $16) + ) + ) + ) + (local.get $8) + ) + ) + (local.get $17) + (i32.gt_s + (local.get $5) + (local.get $17) + ) + ) + ) + (local.get $5) + (local.get $12) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $9) + (local.get $8) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $6) + (local.get $5) + (i32.xor + (local.get $12) + (i32.const 65536) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $11) + (local.get $16) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $7) + (local.get $16) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $6) + (local.get $5) + (i32.xor + (local.get $12) + (i32.const 8192) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $6) + ) + (br $label$continue$L1) + ) + ) + (br $label$break$L343) + ) + (if + (i32.eqz + (local.get $0) + ) + (local.set $18 + (if (result i32) + (local.get $1) + (block (result i32) + (local.set $0 + (i32.const 1) + ) + (loop $while-in130 + (if + (local.tee $1 + (i32.load + (i32.add + (local.get $4) + (i32.shl + (local.get $0) + (i32.const 2) + ) + ) + ) + ) + (block + (call $_pop_arg_336 + (i32.add + (local.get $3) + (i32.shl + (local.get $0) + (i32.const 3) + ) + ) + (local.get $1) + (local.get $2) + ) + (br_if $while-in130 + (i32.lt_s + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (i32.const 10) + ) + ) + (local.set $18 + (i32.const 1) + ) + (br $label$break$L343) + ) + ) + ) + (if (result i32) + (i32.lt_s + (local.get $0) + (i32.const 10) + ) + (loop $while-in132 (result i32) + (if + (i32.load + (i32.add + (local.get $4) + (i32.shl + (local.get $0) + (i32.const 2) + ) + ) + ) + (block + (local.set $18 + (i32.const -1) + ) + (br $label$break$L343) + ) + ) + (br_if $while-in132 + (i32.lt_s + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (i32.const 10) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + (i32.const 0) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $13) + ) + (local.get $18) + ) + (func $_pop_arg_336 (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 f64) + (local $5 i32) + (block $label$break$L1 + (if + (i32.le_u + (local.get $1) + (i32.const 20) + ) + (block $switch-default + (block $switch-case9 + (block $switch-case8 + (block $switch-case7 + (block $switch-case6 + (block $switch-case5 + (block $switch-case4 + (block $switch-case3 + (block $switch-case2 + (block $switch-case1 + (block $switch-case + (br_table $switch-case $switch-case1 $switch-case2 $switch-case3 $switch-case4 $switch-case5 $switch-case6 $switch-case7 $switch-case8 $switch-case9 $switch-default + (i32.sub + (local.get $1) + (i32.const 9) + ) + ) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.get $3) + ) + (br $label$break$L1) + ) + (local.set $1 + (i32.load + (local.tee $3 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $3) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.get $1) + ) + (i32.store offset=4 + (local.get $0) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.get $3) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (br $label$break$L1) + ) + (local.set $5 + (i32.load + (local.tee $3 + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + ) + ) + ) + (local.set $3 + (i32.load offset=4 + (local.get $3) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (i32.store + (local.get $0) + (local.get $5) + ) + (i32.store offset=4 + (local.get $0) + (local.get $3) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.tee $1 + (i32.shr_s + (i32.shl + (i32.and + (local.get $3) + (i32.const 65535) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (i32.and + (local.get $3) + (i32.const 65535) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.tee $1 + (i32.shr_s + (i32.shl + (i32.and + (local.get $3) + (i32.const 255) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (i32.and + (local.get $3) + (i32.const 255) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (br $label$break$L1) + ) + (local.set $4 + (f64.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (f64.store + (local.get $0) + (local.get $4) + ) + (br $label$break$L1) + ) + (local.set $4 + (f64.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (f64.store + (local.get $0) + (local.get $4) + ) + ) + ) + ) + ) + (func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (local.get $1) + (loop $while-in + (i32.store8 + (local.tee $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (i32.or + (call $___uremdi3 + (local.get $0) + (local.get $1) + (i32.const 10) + (i32.const 0) + ) + (i32.const 48) + ) + ) + (local.set $0 + (call $___udivdi3 + (local.get $0) + (local.get $1) + (i32.const 10) + (i32.const 0) + ) + ) + (local.set $3 + (global.get $tempRet0) + ) + (if + (i32.gt_u + (local.get $1) + (i32.const 9) + ) + (block + (local.set $1 + (local.get $3) + ) + (br $while-in) + ) + ) + ) + ) + (if + (local.get $0) + (loop $while-in1 + (i32.store8 + (local.tee $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (i32.or + (i32.rem_u + (local.get $0) + (i32.const 10) + ) + (i32.const 48) + ) + ) + (local.set $1 + (i32.div_u + (local.get $0) + (i32.const 10) + ) + ) + (if + (i32.ge_u + (local.get $0) + (i32.const 10) + ) + (block + (local.set $0 + (local.get $1) + ) + (br $while-in1) + ) + ) + ) + ) + (local.get $2) + ) + (func $_pad (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $7 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 256) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $6 + (local.get $7) + ) + (block $do-once + (if + (i32.and + (i32.gt_s + (local.get $2) + (local.get $3) + ) + (i32.eqz + (i32.and + (local.get $4) + (i32.const 73728) + ) + ) + ) + (block $block + (drop + (call $_memset + (local.get $6) + (local.get $1) + (select + (i32.const 256) + (local.tee $5 + (i32.sub + (local.get $2) + (local.get $3) + ) + ) + (i32.gt_u + (local.get $5) + (i32.const 256) + ) + ) + ) + ) + (local.set $4 + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (local.get $0) + ) + ) + (i32.const 32) + ) + ) + ) + (if + (i32.gt_u + (local.get $5) + (i32.const 255) + ) + (block $block271 + (loop $while-in + (if + (local.get $4) + (block $block273 + (drop + (call $___fwritex + (local.get $6) + (i32.const 256) + (local.get $0) + ) + ) + (local.set $1 + (i32.load + (local.get $0) + ) + ) + ) + ) + (local.set $4 + (i32.eqz + (i32.and + (local.get $1) + (i32.const 32) + ) + ) + ) + (br_if $while-in + (i32.gt_u + (local.tee $5 + (i32.add + (local.get $5) + (i32.const -256) + ) + ) + (i32.const 255) + ) + ) + ) + (br_if $do-once + (i32.eqz + (local.get $4) + ) + ) + (local.set $5 + (i32.and + (i32.sub + (local.get $2) + (local.get $3) + ) + (i32.const 255) + ) + ) + ) + (br_if $do-once + (i32.eqz + (local.get $4) + ) + ) + ) + (drop + (call $___fwritex + (local.get $6) + (local.get $5) + (local.get $0) + ) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $7) + ) + ) + (func $_malloc (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (block $folding-inner0 + (block $do-once + (if + (i32.lt_u + (local.get $0) + (i32.const 245) + ) + (block $block + (if + (i32.and + (local.tee $5 + (i32.shr_u + (local.tee $11 + (i32.load + (i32.const 176) + ) + ) + (local.tee $13 + (i32.shr_u + (local.tee $4 + (select + (i32.const 16) + (i32.and + (i32.add + (local.get $0) + (i32.const 11) + ) + (i32.const -8) + ) + (i32.lt_u + (local.get $0) + (i32.const 11) + ) + ) + ) + (i32.const 3) + ) + ) + ) + ) + (i32.const 3) + ) + (block $block275 + (local.set $10 + (i32.load + (local.tee $1 + (i32.add + (local.tee $7 + (i32.load + (local.tee $3 + (i32.add + (local.tee $2 + (i32.add + (i32.shl + (local.tee $4 + (i32.add + (i32.xor + (i32.and + (local.get $5) + (i32.const 1) + ) + (i32.const 1) + ) + (local.get $13) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.eq + (local.get $2) + (local.get $10) + ) + (i32.store + (i32.const 176) + (i32.and + (local.get $11) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $4) + ) + (i32.const -1) + ) + ) + ) + (block $block277 + (if + (i32.lt_u + (local.get $10) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $10) + (i32.const 12) + ) + ) + ) + (local.get $7) + ) + (block $block280 + (i32.store + (local.get $0) + (local.get $2) + ) + (i32.store + (local.get $3) + (local.get $10) + ) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=4 + (local.get $7) + (i32.or + (local.tee $0 + (i32.shl + (local.get $4) + (i32.const 3) + ) + ) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $7) + (local.get $0) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + (return + (local.get $1) + ) + ) + ) + (if + (i32.gt_u + (local.get $4) + (local.tee $0 + (i32.load + (i32.const 184) + ) + ) + ) + (block $block282 + (if + (local.get $5) + (block $block284 + (local.set $10 + (i32.and + (i32.shr_u + (local.tee $3 + (i32.add + (i32.and + (local.tee $3 + (i32.and + (i32.shl + (local.get $5) + (local.get $13) + ) + (i32.or + (local.tee $3 + (i32.shl + (i32.const 2) + (local.get $13) + ) + ) + (i32.sub + (i32.const 0) + (local.get $3) + ) + ) + ) + ) + (i32.sub + (i32.const 0) + (local.get $3) + ) + ) + (i32.const -1) + ) + ) + (i32.const 12) + ) + (i32.const 16) + ) + ) + (local.set $9 + (i32.load + (local.tee $7 + (i32.add + (local.tee $12 + (i32.load + (local.tee $3 + (i32.add + (local.tee $10 + (i32.add + (i32.shl + (local.tee $5 + (i32.add + (i32.or + (i32.or + (i32.or + (i32.or + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $3) + (local.get $10) + ) + ) + (i32.const 5) + ) + (i32.const 8) + ) + ) + (local.get $10) + ) + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + (i32.const 2) + ) + (i32.const 4) + ) + ) + ) + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + (i32.const 1) + ) + (i32.const 2) + ) + ) + ) + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + ) + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.eq + (local.get $10) + (local.get $9) + ) + (block $block286 + (i32.store + (i32.const 176) + (i32.and + (local.get $11) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $5) + ) + (i32.const -1) + ) + ) + ) + (local.set $8 + (local.get $0) + ) + ) + (block $block287 + (if + (i32.lt_u + (local.get $9) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $9) + (i32.const 12) + ) + ) + ) + (local.get $12) + ) + (block $block290 + (i32.store + (local.get $0) + (local.get $10) + ) + (i32.store + (local.get $3) + (local.get $9) + ) + (local.set $8 + (i32.load + (i32.const 184) + ) + ) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.or + (local.get $4) + (i32.const 3) + ) + ) + (i32.store offset=4 + (local.tee $10 + (i32.add + (local.get $12) + (local.get $4) + ) + ) + (i32.or + (local.tee $5 + (i32.sub + (i32.shl + (local.get $5) + (i32.const 3) + ) + (local.get $4) + ) + ) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $10) + (local.get $5) + ) + (local.get $5) + ) + (if + (local.get $8) + (block $block292 + (local.set $12 + (i32.load + (i32.const 196) + ) + ) + (local.set $4 + (i32.add + (i32.shl + (local.tee $0 + (i32.shr_u + (local.get $8) + (i32.const 3) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $3 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $3 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block295 + (local.set $2 + (local.get $3) + ) + (local.set $1 + (local.get $0) + ) + ) + ) + (block $block296 + (i32.store + (i32.const 176) + (i32.or + (local.get $3) + (local.get $0) + ) + ) + (local.set $2 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + (local.set $1 + (local.get $4) + ) + ) + ) + (i32.store + (local.get $2) + (local.get $12) + ) + (i32.store offset=12 + (local.get $1) + (local.get $12) + ) + (i32.store offset=8 + (local.get $12) + (local.get $1) + ) + (i32.store offset=12 + (local.get $12) + (local.get $4) + ) + ) + ) + (i32.store + (i32.const 184) + (local.get $5) + ) + (i32.store + (i32.const 196) + (local.get $10) + ) + (return + (local.get $7) + ) + ) + ) + (if + (local.tee $0 + (i32.load + (i32.const 180) + ) + ) + (block $block298 + (local.set $2 + (i32.and + (i32.shr_u + (local.tee $0 + (i32.add + (i32.and + (local.get $0) + (i32.sub + (i32.const 0) + (local.get $0) + ) + ) + (i32.const -1) + ) + ) + (i32.const 12) + ) + (i32.const 16) + ) + ) + (local.set $7 + (i32.sub + (i32.and + (i32.load offset=4 + (local.tee $0 + (i32.load offset=480 + (i32.shl + (i32.add + (i32.or + (i32.or + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $0) + (local.get $2) + ) + ) + (i32.const 5) + ) + (i32.const 8) + ) + ) + (local.get $2) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 2) + ) + (i32.const 4) + ) + ) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 1) + ) + (i32.const 2) + ) + ) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + ) + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.const -8) + ) + (local.get $4) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (local.get $0) + ) + (loop $while-in + (block $while-out + (if + (i32.eqz + (local.tee $0 + (i32.load offset=16 + (local.get $1) + ) + ) + ) + (if + (i32.eqz + (local.tee $0 + (i32.load offset=20 + (local.get $1) + ) + ) + ) + (block $block301 + (local.set $10 + (local.get $7) + ) + (local.set $5 + (local.get $2) + ) + (br $while-out) + ) + ) + ) + (local.set $10 + (i32.lt_u + (local.tee $1 + (i32.sub + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $4) + ) + ) + (local.get $7) + ) + ) + (local.set $7 + (select + (local.get $1) + (local.get $7) + (local.get $10) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (select + (local.get $0) + (local.get $2) + (local.get $10) + ) + ) + (br $while-in) + ) + ) + (if + (i32.lt_u + (local.get $5) + (local.tee $12 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (if + (i32.ge_u + (local.get $5) + (local.tee $11 + (i32.add + (local.get $5) + (local.get $4) + ) + ) + ) + (call $_abort) + ) + (local.set $8 + (i32.load offset=24 + (local.get $5) + ) + ) + (block $do-once4 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $5) + ) + ) + (local.get $5) + ) + (block $block305 + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $5) + (i32.const 20) + ) + ) + ) + ) + ) + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + ) + ) + ) + (block $block308 + (local.set $9 + (i32.const 0) + ) + (br $do-once4) + ) + ) + ) + (loop $while-in7 + (if + (local.tee $2 + (i32.load + (local.tee $7 + (i32.add + (local.get $1) + (i32.const 20) + ) + ) + ) + ) + (block $block310 + (local.set $1 + (local.get $2) + ) + (local.set $0 + (local.get $7) + ) + (br $while-in7) + ) + ) + (if + (local.tee $2 + (i32.load + (local.tee $7 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (block $block312 + (local.set $1 + (local.get $2) + ) + (local.set $0 + (local.get $7) + ) + (br $while-in7) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (local.get $12) + ) + (call $_abort) + (block $block314 + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $9 + (local.get $1) + ) + ) + ) + ) + (block $block315 + (if + (i32.lt_u + (local.tee $7 + (i32.load offset=8 + (local.get $5) + ) + ) + (local.get $12) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $2 + (i32.add + (local.get $7) + (i32.const 12) + ) + ) + ) + (local.get $5) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $5) + ) + (block $block319 + (i32.store + (local.get $2) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $7) + ) + (local.set $9 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (block $do-once8 + (if + (local.get $8) + (block $block321 + (if + (i32.eq + (local.get $5) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $1 + (i32.load offset=28 + (local.get $5) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block $block323 + (i32.store + (local.get $0) + (local.get $9) + ) + (if + (i32.eqz + (local.get $9) + ) + (block $block325 + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $do-once8) + ) + ) + ) + (block $block326 + (if + (i32.lt_u + (local.get $8) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + ) + (local.get $5) + ) + (i32.store + (local.get $0) + (local.get $9) + ) + (i32.store offset=20 + (local.get $8) + (local.get $9) + ) + ) + (br_if $do-once8 + (i32.eqz + (local.get $9) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $9) + (local.tee $0 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $9) + (local.get $8) + ) + (if + (local.tee $1 + (i32.load offset=16 + (local.get $5) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.get $0) + ) + (call $_abort) + (block $block332 + (i32.store offset=16 + (local.get $9) + (local.get $1) + ) + (i32.store offset=24 + (local.get $1) + (local.get $9) + ) + ) + ) + ) + (if + (local.tee $0 + (i32.load offset=20 + (local.get $5) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block335 + (i32.store offset=20 + (local.get $9) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $9) + ) + ) + ) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $10) + (i32.const 16) + ) + (block $block337 + (i32.store offset=4 + (local.get $5) + (i32.or + (local.tee $0 + (i32.add + (local.get $10) + (local.get $4) + ) + ) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $5) + (local.get $0) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + ) + (block $block338 + (i32.store offset=4 + (local.get $5) + (i32.or + (local.get $4) + (i32.const 3) + ) + ) + (i32.store offset=4 + (local.get $11) + (i32.or + (local.get $10) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $11) + (local.get $10) + ) + (local.get $10) + ) + (if + (local.tee $0 + (i32.load + (i32.const 184) + ) + ) + (block $block340 + (local.set $4 + (i32.load + (i32.const 196) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (local.tee $0 + (i32.shr_u + (local.get $0) + (i32.const 3) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $1 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block343 + (local.set $6 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + (block $block344 + (i32.store + (i32.const 176) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (local.set $6 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (local.set $3 + (local.get $2) + ) + ) + ) + (i32.store + (local.get $6) + (local.get $4) + ) + (i32.store offset=12 + (local.get $3) + (local.get $4) + ) + (i32.store offset=8 + (local.get $4) + (local.get $3) + ) + (i32.store offset=12 + (local.get $4) + (local.get $2) + ) + ) + ) + (i32.store + (i32.const 184) + (local.get $10) + ) + (i32.store + (i32.const 196) + (local.get $11) + ) + ) + ) + (return + (i32.add + (local.get $5) + (i32.const 8) + ) + ) + ) + (local.set $0 + (local.get $4) + ) + ) + ) + (local.set $0 + (local.get $4) + ) + ) + ) + (if + (i32.gt_u + (local.get $0) + (i32.const -65) + ) + (local.set $0 + (i32.const -1) + ) + (block $block346 + (local.set $2 + (i32.and + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 11) + ) + ) + (i32.const -8) + ) + ) + (if + (local.tee $18 + (i32.load + (i32.const 180) + ) + ) + (block $block348 + (local.set $14 + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $0) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $2) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $2) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $3 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $3) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (local.set $3 + (i32.sub + (i32.const 0) + (local.get $2) + ) + ) + (block $__rjto$3 + (block $__rjti$3 + (if + (local.tee $0 + (i32.load offset=480 + (i32.shl + (local.get $14) + (i32.const 2) + ) + ) + ) + (block $block352 + (local.set $6 + (i32.const 0) + ) + (local.set $8 + (i32.shl + (local.get $2) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $14) + (i32.const 1) + ) + ) + (i32.eq + (local.get $14) + (i32.const 31) + ) + ) + ) + ) + (local.set $1 + (i32.const 0) + ) + (loop $while-in14 + (if + (i32.lt_u + (local.tee $4 + (i32.sub + (local.tee $9 + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + ) + (local.get $2) + ) + ) + (local.get $3) + ) + (if + (i32.eq + (local.get $9) + (local.get $2) + ) + (block $block355 + (local.set $1 + (local.get $4) + ) + (local.set $3 + (local.get $0) + ) + (br $__rjti$3) + ) + (block $block356 + (local.set $3 + (local.get $4) + ) + (local.set $1 + (local.get $0) + ) + ) + ) + ) + (local.set $0 + (select + (local.get $6) + (local.tee $4 + (i32.load offset=20 + (local.get $0) + ) + ) + (i32.or + (i32.eqz + (local.get $4) + ) + (i32.eq + (local.get $4) + (local.tee $9 + (i32.load + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $8) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + ) + ) + ) + (local.set $4 + (i32.shl + (local.get $8) + (i32.xor + (local.tee $6 + (i32.eqz + (local.get $9) + ) + ) + (i32.const 1) + ) + ) + ) + (if + (local.get $6) + (block $block358 + (local.set $4 + (local.get $0) + ) + (local.set $0 + (local.get $1) + ) + ) + (block $block359 + (local.set $6 + (local.get $0) + ) + (local.set $8 + (local.get $4) + ) + (local.set $0 + (local.get $9) + ) + (br $while-in14) + ) + ) + ) + ) + (block $block360 + (local.set $4 + (i32.const 0) + ) + (local.set $0 + (i32.const 0) + ) + ) + ) + (if + (i32.and + (i32.eqz + (local.get $4) + ) + (i32.eqz + (local.get $0) + ) + ) + (block $block362 + (if + (i32.eqz + (local.tee $1 + (i32.and + (local.get $18) + (i32.or + (local.tee $1 + (i32.shl + (i32.const 2) + (local.get $14) + ) + ) + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + ) + ) + ) + (block $block364 + (local.set $0 + (local.get $2) + ) + (br $do-once) + ) + ) + (local.set $9 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.add + (i32.and + (local.get $1) + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + (i32.const -1) + ) + ) + (i32.const 12) + ) + (i32.const 16) + ) + ) + (local.set $4 + (i32.load offset=480 + (i32.shl + (i32.add + (i32.or + (i32.or + (i32.or + (i32.or + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $1) + (local.get $9) + ) + ) + (i32.const 5) + ) + (i32.const 8) + ) + ) + (local.get $9) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 2) + ) + (i32.const 4) + ) + ) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 1) + ) + (i32.const 2) + ) + ) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + ) + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (if + (local.get $4) + (block $block366 + (local.set $1 + (local.get $3) + ) + (local.set $3 + (local.get $4) + ) + (br $__rjti$3) + ) + (local.set $4 + (local.get $0) + ) + ) + (br $__rjto$3) + ) + (loop $while-in16 + (local.set $9 + (i32.lt_u + (local.tee $4 + (i32.sub + (i32.and + (i32.load offset=4 + (local.get $3) + ) + (i32.const -8) + ) + (local.get $2) + ) + ) + (local.get $1) + ) + ) + (local.set $1 + (select + (local.get $4) + (local.get $1) + (local.get $9) + ) + ) + (local.set $0 + (select + (local.get $3) + (local.get $0) + (local.get $9) + ) + ) + (if + (local.tee $4 + (i32.load offset=16 + (local.get $3) + ) + ) + (block $block368 + (local.set $3 + (local.get $4) + ) + (br $while-in16) + ) + ) + (br_if $while-in16 + (local.tee $3 + (i32.load offset=20 + (local.get $3) + ) + ) + ) + (local.set $3 + (local.get $1) + ) + (local.set $4 + (local.get $0) + ) + ) + ) + (if + (local.get $4) + (if + (i32.lt_u + (local.get $3) + (i32.sub + (i32.load + (i32.const 184) + ) + (local.get $2) + ) + ) + (block $block371 + (if + (i32.lt_u + (local.get $4) + (local.tee $12 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (if + (i32.ge_u + (local.get $4) + (local.tee $6 + (i32.add + (local.get $4) + (local.get $2) + ) + ) + ) + (call $_abort) + ) + (local.set $9 + (i32.load offset=24 + (local.get $4) + ) + ) + (block $do-once17 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $4) + ) + ) + (local.get $4) + ) + (block $block375 + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 20) + ) + ) + ) + ) + ) + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 16) + ) + ) + ) + ) + ) + (block $block378 + (local.set $11 + (i32.const 0) + ) + (br $do-once17) + ) + ) + ) + (loop $while-in20 + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $1) + (i32.const 20) + ) + ) + ) + ) + (block $block380 + (local.set $1 + (local.get $7) + ) + (local.set $0 + (local.get $10) + ) + (br $while-in20) + ) + ) + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (block $block382 + (local.set $1 + (local.get $7) + ) + (local.set $0 + (local.get $10) + ) + (br $while-in20) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (local.get $12) + ) + (call $_abort) + (block $block384 + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $11 + (local.get $1) + ) + ) + ) + ) + (block $block385 + (if + (i32.lt_u + (local.tee $10 + (i32.load offset=8 + (local.get $4) + ) + ) + (local.get $12) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $7 + (i32.add + (local.get $10) + (i32.const 12) + ) + ) + ) + (local.get $4) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $4) + ) + (block $block389 + (i32.store + (local.get $7) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $10) + ) + (local.set $11 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (block $do-once21 + (if + (local.get $9) + (block $block391 + (if + (i32.eq + (local.get $4) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $1 + (i32.load offset=28 + (local.get $4) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block $block393 + (i32.store + (local.get $0) + (local.get $11) + ) + (if + (i32.eqz + (local.get $11) + ) + (block $block395 + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $do-once21) + ) + ) + ) + (block $block396 + (if + (i32.lt_u + (local.get $9) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $9) + (i32.const 16) + ) + ) + ) + (local.get $4) + ) + (i32.store + (local.get $0) + (local.get $11) + ) + (i32.store offset=20 + (local.get $9) + (local.get $11) + ) + ) + (br_if $do-once21 + (i32.eqz + (local.get $11) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $11) + (local.tee $0 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $11) + (local.get $9) + ) + (if + (local.tee $1 + (i32.load offset=16 + (local.get $4) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.get $0) + ) + (call $_abort) + (block $block402 + (i32.store offset=16 + (local.get $11) + (local.get $1) + ) + (i32.store offset=24 + (local.get $1) + (local.get $11) + ) + ) + ) + ) + (if + (local.tee $0 + (i32.load offset=20 + (local.get $4) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block405 + (i32.store offset=20 + (local.get $11) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $11) + ) + ) + ) + ) + ) + ) + ) + (block $do-once25 + (if + (i32.lt_u + (local.get $3) + (i32.const 16) + ) + (block $block407 + (i32.store offset=4 + (local.get $4) + (i32.or + (local.tee $0 + (i32.add + (local.get $3) + (local.get $2) + ) + ) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $4) + (local.get $0) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + ) + (block $block408 + (i32.store offset=4 + (local.get $4) + (i32.or + (local.get $2) + (i32.const 3) + ) + ) + (i32.store offset=4 + (local.get $6) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $6) + (local.get $3) + ) + (local.get $3) + ) + (local.set $0 + (i32.shr_u + (local.get $3) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $3) + (i32.const 256) + ) + (block $block410 + (local.set $3 + (i32.add + (i32.shl + (local.get $0) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $1 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block413 + (local.set $13 + (local.get $1) + ) + (local.set $5 + (local.get $0) + ) + ) + ) + (block $block414 + (i32.store + (i32.const 176) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (local.set $13 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + (local.set $5 + (local.get $3) + ) + ) + ) + (i32.store + (local.get $13) + (local.get $6) + ) + (i32.store offset=12 + (local.get $5) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $5) + ) + (i32.store offset=12 + (local.get $6) + (local.get $3) + ) + (br $do-once25) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (local.tee $7 + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $3) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $3) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $2 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $2) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $6) + (local.get $7) + ) + (i32.store offset=4 + (local.tee $0 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + (i32.const 0) + ) + (i32.store + (local.get $0) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (i32.const 180) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $7) + ) + ) + ) + ) + (block $block418 + (i32.store + (i32.const 180) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (i32.store + (local.get $2) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $2) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once25) + ) + ) + (local.set $7 + (i32.shl + (local.get $3) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $7) + (i32.const 1) + ) + ) + (i32.eq + (local.get $7) + (i32.const 31) + ) + ) + ) + ) + (local.set $0 + (i32.load + (local.get $2) + ) + ) + (block $__rjto$1 + (block $__rjti$1 + (loop $while-in28 + (br_if $__rjti$1 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $3) + ) + ) + (local.set $2 + (i32.shl + (local.get $7) + (i32.const 1) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $7 + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $7) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block $block420 + (local.set $7 + (local.get $2) + ) + (local.set $0 + (local.get $1) + ) + (br $while-in28) + ) + ) + ) + (if + (i32.lt_u + (local.get $7) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block422 + (i32.store + (local.get $7) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $0) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once25) + ) + ) + (br $__rjto$1) + ) + (if + (i32.and + (i32.ge_u + (local.tee $2 + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + (local.tee $1 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $0) + (local.get $1) + ) + ) + (block $block424 + (i32.store offset=12 + (local.get $2) + (local.get $6) + ) + (i32.store + (local.get $3) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $2) + ) + (i32.store offset=12 + (local.get $6) + (local.get $0) + ) + (i32.store offset=24 + (local.get $6) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + ) + ) + (return + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + (local.set $0 + (local.get $2) + ) + ) + (local.set $0 + (local.get $2) + ) + ) + ) + (local.set $0 + (local.get $2) + ) + ) + ) + ) + ) + ) + (if + (i32.ge_u + (local.tee $1 + (i32.load + (i32.const 184) + ) + ) + (local.get $0) + ) + (block $block426 + (local.set $2 + (i32.load + (i32.const 196) + ) + ) + (if + (i32.gt_u + (local.tee $3 + (i32.sub + (local.get $1) + (local.get $0) + ) + ) + (i32.const 15) + ) + (block $block428 + (i32.store + (i32.const 196) + (local.tee $1 + (i32.add + (local.get $2) + (local.get $0) + ) + ) + ) + (i32.store + (i32.const 184) + (local.get $3) + ) + (i32.store offset=4 + (local.get $1) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $1) + (local.get $3) + ) + (local.get $3) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 3) + ) + ) + ) + (block $block429 + (i32.store + (i32.const 184) + (i32.const 0) + ) + (i32.store + (i32.const 196) + (i32.const 0) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $1) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $2) + (local.get $1) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + ) + ) + (return + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + ) + (br_if $folding-inner0 + (i32.gt_u + (local.tee $1 + (i32.load + (i32.const 188) + ) + ) + (local.get $0) + ) + ) + (if + (i32.eqz + (i32.load + (i32.const 648) + ) + ) + (if + (i32.and + (i32.add + (local.tee $1 + (call $_sysconf + (i32.const 30) + ) + ) + (i32.const -1) + ) + (local.get $1) + ) + (call $_abort) + (block $block432 + (i32.store + (i32.const 656) + (local.get $1) + ) + (i32.store + (i32.const 652) + (local.get $1) + ) + (i32.store + (i32.const 660) + (i32.const -1) + ) + (i32.store + (i32.const 664) + (i32.const -1) + ) + (i32.store + (i32.const 668) + (i32.const 0) + ) + (i32.store + (i32.const 620) + (i32.const 0) + ) + (i32.store + (i32.const 648) + (i32.xor + (i32.and + (call $_time + (i32.const 0) + ) + (i32.const -16) + ) + (i32.const 1431655768) + ) + ) + ) + ) + ) + (if + (i32.le_u + (local.tee $5 + (i32.and + (local.tee $6 + (i32.add + (local.tee $1 + (i32.load + (i32.const 656) + ) + ) + (local.tee $8 + (i32.add + (local.get $0) + (i32.const 47) + ) + ) + ) + ) + (local.tee $9 + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + ) + ) + (local.get $0) + ) + (return + (i32.const 0) + ) + ) + (if + (local.tee $2 + (i32.load + (i32.const 616) + ) + ) + (if + (i32.or + (i32.le_u + (local.tee $1 + (i32.add + (local.tee $3 + (i32.load + (i32.const 608) + ) + ) + (local.get $5) + ) + ) + (local.get $3) + ) + (i32.gt_u + (local.get $1) + (local.get $2) + ) + ) + (return + (i32.const 0) + ) + ) + ) + (local.set $11 + (i32.add + (local.get $0) + (i32.const 48) + ) + ) + (block $__rjto$13 + (block $__rjti$13 + (if + (i32.eqz + (i32.and + (i32.load + (i32.const 620) + ) + (i32.const 4) + ) + ) + (block $block437 + (block $label$break$L279 + (block $__rjti$5 + (block $__rjti$4 + (br_if $__rjti$4 + (i32.eqz + (local.tee $4 + (i32.load + (i32.const 200) + ) + ) + ) + ) + (local.set $1 + (i32.const 624) + ) + (loop $while-in34 + (block $while-out33 + (if + (i32.le_u + (local.tee $3 + (i32.load + (local.get $1) + ) + ) + (local.get $4) + ) + (if + (i32.gt_u + (i32.add + (local.get $3) + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + ) + ) + (local.get $4) + ) + (block $block440 + (local.set $4 + (local.get $1) + ) + (br $while-out33) + ) + ) + ) + (br_if $while-in34 + (local.tee $1 + (i32.load offset=8 + (local.get $1) + ) + ) + ) + (br $__rjti$4) + ) + ) + (if + (i32.lt_u + (local.tee $3 + (i32.and + (i32.sub + (local.get $6) + (i32.load + (i32.const 188) + ) + ) + (local.get $9) + ) + ) + (i32.const 2147483647) + ) + (if + (i32.eq + (local.tee $1 + (call $_sbrk + (local.get $3) + ) + ) + (i32.add + (i32.load + (local.get $4) + ) + (i32.load + (local.get $2) + ) + ) + ) + (br_if $__rjti$13 + (i32.ne + (local.get $1) + (i32.const -1) + ) + ) + (block $block443 + (local.set $2 + (local.get $1) + ) + (br $__rjti$5) + ) + ) + ) + (br $label$break$L279) + ) + (if + (i32.ne + (local.tee $1 + (call $_sbrk + (i32.const 0) + ) + ) + (i32.const -1) + ) + (block $block445 + (local.set $3 + (if (result i32) + (i32.and + (local.tee $2 + (i32.add + (local.tee $4 + (i32.load + (i32.const 652) + ) + ) + (i32.const -1) + ) + ) + (local.tee $3 + (local.get $1) + ) + ) + (i32.add + (i32.sub + (local.get $5) + (local.get $3) + ) + (i32.and + (i32.add + (local.get $2) + (local.get $3) + ) + (i32.sub + (i32.const 0) + (local.get $4) + ) + ) + ) + (local.get $5) + ) + ) + (local.set $9 + (i32.add + (local.tee $4 + (i32.load + (i32.const 608) + ) + ) + (local.get $3) + ) + ) + (if + (i32.and + (i32.gt_u + (local.get $3) + (local.get $0) + ) + (i32.lt_u + (local.get $3) + (i32.const 2147483647) + ) + ) + (block $block448 + (if + (local.tee $2 + (i32.load + (i32.const 616) + ) + ) + (br_if $label$break$L279 + (i32.or + (i32.le_u + (local.get $9) + (local.get $4) + ) + (i32.gt_u + (local.get $9) + (local.get $2) + ) + ) + ) + ) + (br_if $__rjti$13 + (i32.eq + (local.tee $2 + (call $_sbrk + (local.get $3) + ) + ) + (local.get $1) + ) + ) + (br $__rjti$5) + ) + ) + ) + ) + (br $label$break$L279) + ) + (local.set $1 + (local.get $3) + ) + (local.set $4 + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + (if + (i32.and + (i32.gt_u + (local.get $11) + (local.get $1) + ) + (i32.and + (i32.lt_u + (local.get $1) + (i32.const 2147483647) + ) + (i32.ne + (local.get $2) + (i32.const -1) + ) + ) + ) + (if + (i32.lt_u + (local.tee $3 + (i32.and + (i32.add + (i32.sub + (local.get $8) + (local.get $1) + ) + (local.tee $3 + (i32.load + (i32.const 656) + ) + ) + ) + (i32.sub + (i32.const 0) + (local.get $3) + ) + ) + ) + (i32.const 2147483647) + ) + (if + (i32.eq + (call $_sbrk + (local.get $3) + ) + (i32.const -1) + ) + (block $block453 + (drop + (call $_sbrk + (local.get $4) + ) + ) + (br $label$break$L279) + ) + (local.set $3 + (i32.add + (local.get $3) + (local.get $1) + ) + ) + ) + (local.set $3 + (local.get $1) + ) + ) + (local.set $3 + (local.get $1) + ) + ) + (if + (i32.ne + (local.get $2) + (i32.const -1) + ) + (block $block455 + (local.set $1 + (local.get $2) + ) + (br $__rjti$13) + ) + ) + ) + (i32.store + (i32.const 620) + (i32.or + (i32.load + (i32.const 620) + ) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $5) + (i32.const 2147483647) + ) + (if + (i32.and + (i32.lt_u + (local.tee $1 + (call $_sbrk + (local.get $5) + ) + ) + (local.tee $3 + (call $_sbrk + (i32.const 0) + ) + ) + ) + (i32.and + (i32.ne + (local.get $1) + (i32.const -1) + ) + (i32.ne + (local.get $3) + (i32.const -1) + ) + ) + ) + (br_if $__rjti$13 + (i32.gt_u + (local.tee $3 + (i32.sub + (local.get $3) + (local.get $1) + ) + ) + (i32.add + (local.get $0) + (i32.const 40) + ) + ) + ) + ) + ) + (br $__rjto$13) + ) + (i32.store + (i32.const 608) + (local.tee $2 + (i32.add + (i32.load + (i32.const 608) + ) + (local.get $3) + ) + ) + ) + (if + (i32.gt_u + (local.get $2) + (i32.load + (i32.const 612) + ) + ) + (i32.store + (i32.const 612) + (local.get $2) + ) + ) + (block $do-once40 + (if + (local.tee $6 + (i32.load + (i32.const 200) + ) + ) + (block $block460 + (local.set $2 + (i32.const 624) + ) + (block $__rjto$10 + (block $__rjti$10 + (loop $while-in45 + (br_if $__rjti$10 + (i32.eq + (local.get $1) + (i32.add + (local.tee $11 + (i32.load + (local.get $2) + ) + ) + (local.tee $5 + (i32.load + (local.tee $4 + (i32.add + (local.get $2) + (i32.const 4) + ) + ) + ) + ) + ) + ) + ) + (br_if $while-in45 + (local.tee $2 + (i32.load offset=8 + (local.get $2) + ) + ) + ) + ) + (br $__rjto$10) + ) + (if + (i32.eqz + (i32.and + (i32.load offset=12 + (local.get $2) + ) + (i32.const 8) + ) + ) + (if + (i32.and + (i32.lt_u + (local.get $6) + (local.get $1) + ) + (i32.ge_u + (local.get $6) + (local.get $11) + ) + ) + (block $block463 + (i32.store + (local.get $4) + (i32.add + (local.get $5) + (local.get $3) + ) + ) + (local.set $2 + (i32.add + (local.get $6) + (local.tee $1 + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $6) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + ) + (local.set $1 + (i32.add + (i32.sub + (local.get $3) + (local.get $1) + ) + (i32.load + (i32.const 188) + ) + ) + ) + (i32.store + (i32.const 200) + (local.get $2) + ) + (i32.store + (i32.const 188) + (local.get $1) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $1) + (i32.const 1) + ) + ) + (i32.store offset=4 + (i32.add + (local.get $2) + (local.get $1) + ) + (i32.const 40) + ) + (i32.store + (i32.const 204) + (i32.load + (i32.const 664) + ) + ) + (br $do-once40) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.tee $4 + (i32.load + (i32.const 192) + ) + ) + ) + (block $block465 + (i32.store + (i32.const 192) + (local.get $1) + ) + (local.set $4 + (local.get $1) + ) + ) + ) + (local.set $11 + (i32.add + (local.get $1) + (local.get $3) + ) + ) + (local.set $2 + (i32.const 624) + ) + (block $__rjto$11 + (block $__rjti$11 + (loop $while-in47 + (if + (i32.eq + (i32.load + (local.get $2) + ) + (local.get $11) + ) + (block $block467 + (local.set $5 + (local.get $2) + ) + (br $__rjti$11) + ) + ) + (br_if $while-in47 + (local.tee $2 + (i32.load offset=8 + (local.get $2) + ) + ) + ) + (local.set $4 + (i32.const 624) + ) + ) + (br $__rjto$11) + ) + (if + (i32.and + (i32.load offset=12 + (local.get $2) + ) + (i32.const 8) + ) + (local.set $4 + (i32.const 624) + ) + (block $block469 + (i32.store + (local.get $5) + (local.get $1) + ) + (i32.store + (local.tee $2 + (i32.add + (local.get $2) + (i32.const 4) + ) + ) + (i32.add + (i32.load + (local.get $2) + ) + (local.get $3) + ) + ) + (local.set $8 + (i32.add + (local.tee $9 + (i32.add + (local.get $1) + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + (local.get $0) + ) + ) + (local.set $7 + (i32.sub + (i32.sub + (local.tee $5 + (i32.add + (local.get $11) + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $11) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + (local.get $9) + ) + (local.get $0) + ) + ) + (i32.store offset=4 + (local.get $9) + (i32.or + (local.get $0) + (i32.const 3) + ) + ) + (block $do-once48 + (if + (i32.eq + (local.get $5) + (local.get $6) + ) + (block $block471 + (i32.store + (i32.const 188) + (local.tee $0 + (i32.add + (i32.load + (i32.const 188) + ) + (local.get $7) + ) + ) + ) + (i32.store + (i32.const 200) + (local.get $8) + ) + (i32.store offset=4 + (local.get $8) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + ) + (block $block472 + (if + (i32.eq + (local.get $5) + (i32.load + (i32.const 196) + ) + ) + (block $block474 + (i32.store + (i32.const 184) + (local.tee $0 + (i32.add + (i32.load + (i32.const 184) + ) + (local.get $7) + ) + ) + ) + (i32.store + (i32.const 196) + (local.get $8) + ) + (i32.store offset=4 + (local.get $8) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $8) + (local.get $0) + ) + (local.get $0) + ) + (br $do-once48) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (local.tee $0 + (if (result i32) + (i32.eq + (i32.and + (local.tee $0 + (i32.load offset=4 + (local.get $5) + ) + ) + (i32.const 3) + ) + (i32.const 1) + ) + (block $block476 (result i32) + (local.set $11 + (i32.and + (local.get $0) + (i32.const -8) + ) + ) + (local.set $1 + (i32.shr_u + (local.get $0) + (i32.const 3) + ) + ) + (block $label$break$L331 + (if + (i32.lt_u + (local.get $0) + (i32.const 256) + ) + (block $block478 + (local.set $2 + (i32.load offset=12 + (local.get $5) + ) + ) + (block $do-once51 + (if + (i32.ne + (local.tee $3 + (i32.load offset=8 + (local.get $5) + ) + ) + (local.tee $0 + (i32.add + (i32.shl + (local.get $1) + (i32.const 3) + ) + (i32.const 216) + ) + ) + ) + (block $block480 + (if + (i32.lt_u + (local.get $3) + (local.get $4) + ) + (call $_abort) + ) + (br_if $do-once51 + (i32.eq + (i32.load offset=12 + (local.get $3) + ) + (local.get $5) + ) + ) + (call $_abort) + ) + ) + ) + (if + (i32.eq + (local.get $2) + (local.get $3) + ) + (block $block483 + (i32.store + (i32.const 176) + (i32.and + (i32.load + (i32.const 176) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $label$break$L331) + ) + ) + (block $do-once53 + (if + (i32.eq + (local.get $2) + (local.get $0) + ) + (local.set $15 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (block $block485 + (if + (i32.lt_u + (local.get $2) + (local.get $4) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + (local.get $5) + ) + (block $block488 + (local.set $15 + (local.get $0) + ) + (br $do-once53) + ) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=12 + (local.get $3) + (local.get $2) + ) + (i32.store + (local.get $15) + (local.get $3) + ) + ) + (block $block489 + (local.set $6 + (i32.load offset=24 + (local.get $5) + ) + ) + (block $do-once55 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $5) + ) + ) + (local.get $5) + ) + (block $block491 + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.tee $3 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (if + (local.tee $1 + (i32.load + (local.get $3) + ) + ) + (local.set $0 + (local.get $3) + ) + (block $block494 + (local.set $12 + (i32.const 0) + ) + (br $do-once55) + ) + ) + ) + (loop $while-in58 + (if + (local.tee $3 + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 20) + ) + ) + ) + ) + (block $block496 + (local.set $1 + (local.get $3) + ) + (local.set $0 + (local.get $2) + ) + (br $while-in58) + ) + ) + (if + (local.tee $3 + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (block $block498 + (local.set $1 + (local.get $3) + ) + (local.set $0 + (local.get $2) + ) + (br $while-in58) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (local.get $4) + ) + (call $_abort) + (block $block500 + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $12 + (local.get $1) + ) + ) + ) + ) + (block $block501 + (if + (i32.lt_u + (local.tee $2 + (i32.load offset=8 + (local.get $5) + ) + ) + (local.get $4) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $3 + (i32.add + (local.get $2) + (i32.const 12) + ) + ) + ) + (local.get $5) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $5) + ) + (block $block505 + (i32.store + (local.get $3) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $2) + ) + (local.set $12 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (br_if $label$break$L331 + (i32.eqz + (local.get $6) + ) + ) + (block $do-once59 + (if + (i32.eq + (local.get $5) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $1 + (i32.load offset=28 + (local.get $5) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block $block507 + (i32.store + (local.get $0) + (local.get $12) + ) + (br_if $do-once59 + (local.get $12) + ) + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $label$break$L331) + ) + (block $block508 + (if + (i32.lt_u + (local.get $6) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + ) + (local.get $5) + ) + (i32.store + (local.get $0) + (local.get $12) + ) + (i32.store offset=20 + (local.get $6) + (local.get $12) + ) + ) + (br_if $label$break$L331 + (i32.eqz + (local.get $12) + ) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $12) + (local.tee $1 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $12) + (local.get $6) + ) + (if + (local.tee $3 + (i32.load + (local.tee $0 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $3) + (local.get $1) + ) + (call $_abort) + (block $block514 + (i32.store offset=16 + (local.get $12) + (local.get $3) + ) + (i32.store offset=24 + (local.get $3) + (local.get $12) + ) + ) + ) + ) + (br_if $label$break$L331 + (i32.eqz + (local.tee $0 + (i32.load offset=4 + (local.get $0) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block516 + (i32.store offset=20 + (local.get $12) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $12) + ) + ) + ) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $11) + (local.get $7) + ) + ) + (i32.add + (local.get $5) + (local.get $11) + ) + ) + (local.get $5) + ) + ) + (i32.const 4) + ) + ) + (i32.and + (i32.load + (local.get $0) + ) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $8) + (i32.or + (local.get $7) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $8) + (local.get $7) + ) + (local.get $7) + ) + (local.set $0 + (i32.shr_u + (local.get $7) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $7) + (i32.const 256) + ) + (block $block518 + (local.set $3 + (i32.add + (i32.shl + (local.get $0) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (block $do-once63 + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (block $block520 + (if + (i32.ge_u + (local.tee $0 + (i32.load + (local.tee $1 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (block $block522 + (local.set $16 + (local.get $1) + ) + (local.set $10 + (local.get $0) + ) + (br $do-once63) + ) + ) + (call $_abort) + ) + (block $block523 + (i32.store + (i32.const 176) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (local.set $16 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + (local.set $10 + (local.get $3) + ) + ) + ) + ) + (i32.store + (local.get $16) + (local.get $8) + ) + (i32.store offset=12 + (local.get $10) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $10) + ) + (i32.store offset=12 + (local.get $8) + (local.get $3) + ) + (br $do-once48) + ) + ) + (local.set $3 + (i32.add + (i32.shl + (local.tee $2 + (block $do-once65 (result i32) + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $7) + (i32.const 8) + ) + ) + (block $block525 (result i32) + (drop + (br_if $do-once65 + (i32.const 31) + (i32.gt_u + (local.get $7) + (i32.const 16777215) + ) + ) + ) + (i32.or + (i32.and + (i32.shr_u + (local.get $7) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $3 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $3) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $8) + (local.get $2) + ) + (i32.store offset=4 + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + (i32.const 0) + ) + (i32.store + (local.get $0) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (i32.const 180) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $2) + ) + ) + ) + ) + (block $block527 + (i32.store + (i32.const 180) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (i32.store + (local.get $3) + (local.get $8) + ) + (i32.store offset=24 + (local.get $8) + (local.get $3) + ) + (i32.store offset=12 + (local.get $8) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $8) + ) + (br $do-once48) + ) + ) + (local.set $2 + (i32.shl + (local.get $7) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $2) + (i32.const 1) + ) + ) + (i32.eq + (local.get $2) + (i32.const 31) + ) + ) + ) + ) + (local.set $0 + (i32.load + (local.get $3) + ) + ) + (block $__rjto$7 + (block $__rjti$7 + (loop $while-in68 + (br_if $__rjti$7 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $7) + ) + ) + (local.set $3 + (i32.shl + (local.get $2) + (i32.const 1) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $2 + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $2) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block $block529 + (local.set $2 + (local.get $3) + ) + (local.set $0 + (local.get $1) + ) + (br $while-in68) + ) + ) + ) + (if + (i32.lt_u + (local.get $2) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block531 + (i32.store + (local.get $2) + (local.get $8) + ) + (i32.store offset=24 + (local.get $8) + (local.get $0) + ) + (i32.store offset=12 + (local.get $8) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $8) + ) + (br $do-once48) + ) + ) + (br $__rjto$7) + ) + (if + (i32.and + (i32.ge_u + (local.tee $2 + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + (local.tee $1 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $0) + (local.get $1) + ) + ) + (block $block533 + (i32.store offset=12 + (local.get $2) + (local.get $8) + ) + (i32.store + (local.get $3) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $2) + ) + (i32.store offset=12 + (local.get $8) + (local.get $0) + ) + (i32.store offset=24 + (local.get $8) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + ) + ) + (return + (i32.add + (local.get $9) + (i32.const 8) + ) + ) + ) + ) + ) + (loop $while-in70 + (block $while-out69 + (if + (i32.le_u + (local.tee $2 + (i32.load + (local.get $4) + ) + ) + (local.get $6) + ) + (br_if $while-out69 + (i32.gt_u + (local.tee $2 + (i32.add + (local.get $2) + (i32.load offset=4 + (local.get $4) + ) + ) + ) + (local.get $6) + ) + ) + ) + (local.set $4 + (i32.load offset=8 + (local.get $4) + ) + ) + (br $while-in70) + ) + ) + (local.set $10 + (i32.add + (local.tee $4 + (i32.add + (local.get $2) + (i32.const -47) + ) + ) + (i32.const 8) + ) + ) + (local.set $12 + (i32.add + (local.tee $11 + (select + (local.get $6) + (local.tee $4 + (i32.add + (local.get $4) + (select + (i32.and + (i32.sub + (i32.const 0) + (local.get $10) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $10) + (i32.const 7) + ) + ) + ) + ) + (i32.lt_u + (local.get $4) + (local.tee $10 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + ) + ) + ) + (i32.const 8) + ) + ) + (i32.store + (i32.const 200) + (local.tee $5 + (i32.add + (local.get $1) + (local.tee $4 + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $4 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $4) + (i32.const 7) + ) + ) + ) + ) + ) + ) + (i32.store + (i32.const 188) + (local.tee $4 + (i32.sub + (i32.add + (local.get $3) + (i32.const -40) + ) + (local.get $4) + ) + ) + ) + (i32.store offset=4 + (local.get $5) + (i32.or + (local.get $4) + (i32.const 1) + ) + ) + (i32.store offset=4 + (i32.add + (local.get $5) + (local.get $4) + ) + (i32.const 40) + ) + (i32.store + (i32.const 204) + (i32.load + (i32.const 664) + ) + ) + (i32.store + (local.tee $4 + (i32.add + (local.get $11) + (i32.const 4) + ) + ) + (i32.const 27) + ) + (i32.store + (local.get $12) + (i32.load + (i32.const 624) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.load + (i32.const 628) + ) + ) + (i32.store offset=8 + (local.get $12) + (i32.load + (i32.const 632) + ) + ) + (i32.store offset=12 + (local.get $12) + (i32.load + (i32.const 636) + ) + ) + (i32.store + (i32.const 624) + (local.get $1) + ) + (i32.store + (i32.const 628) + (local.get $3) + ) + (i32.store + (i32.const 636) + (i32.const 0) + ) + (i32.store + (i32.const 632) + (local.get $12) + ) + (local.set $1 + (i32.add + (local.get $11) + (i32.const 24) + ) + ) + (loop $while-in72 + (i32.store + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.const 7) + ) + (br_if $while-in72 + (i32.lt_u + (i32.add + (local.get $1) + (i32.const 4) + ) + (local.get $2) + ) + ) + ) + (if + (i32.ne + (local.get $11) + (local.get $6) + ) + (block $block536 + (i32.store + (local.get $4) + (i32.and + (i32.load + (local.get $4) + ) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $6) + (i32.or + (local.tee $5 + (i32.sub + (local.get $11) + (local.get $6) + ) + ) + (i32.const 1) + ) + ) + (i32.store + (local.get $11) + (local.get $5) + ) + (local.set $1 + (i32.shr_u + (local.get $5) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $5) + (i32.const 256) + ) + (block $block538 + (local.set $2 + (i32.add + (i32.shl + (local.get $1) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $3 + (i32.load + (i32.const 176) + ) + ) + (local.tee $1 + (i32.shl + (i32.const 1) + (local.get $1) + ) + ) + ) + (if + (i32.lt_u + (local.tee $1 + (i32.load + (local.tee $3 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block541 + (local.set $17 + (local.get $3) + ) + (local.set $7 + (local.get $1) + ) + ) + ) + (block $block542 + (i32.store + (i32.const 176) + (i32.or + (local.get $3) + (local.get $1) + ) + ) + (local.set $17 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (local.set $7 + (local.get $2) + ) + ) + ) + (i32.store + (local.get $17) + (local.get $6) + ) + (i32.store offset=12 + (local.get $7) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $7) + ) + (i32.store offset=12 + (local.get $6) + (local.get $2) + ) + (br $do-once40) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (local.tee $4 + (if (result i32) + (local.tee $1 + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $5) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $5) + (i32.add + (local.tee $1 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $1 + (i32.and + (i32.shr_u + (i32.add + (local.tee $3 + (i32.shl + (local.get $1) + (local.tee $2 + (i32.and + (i32.shr_u + (i32.add + (local.get $1) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $2) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (i32.add + (local.tee $3 + (i32.shl + (local.get $3) + (local.get $1) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $3) + (local.get $1) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $1) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $6) + (local.get $4) + ) + (i32.store offset=20 + (local.get $6) + (i32.const 0) + ) + (i32.store + (local.get $10) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (local.tee $3 + (i32.load + (i32.const 180) + ) + ) + (local.tee $1 + (i32.shl + (i32.const 1) + (local.get $4) + ) + ) + ) + ) + (block $block546 + (i32.store + (i32.const 180) + (i32.or + (local.get $3) + (local.get $1) + ) + ) + (i32.store + (local.get $2) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $2) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once40) + ) + ) + (local.set $4 + (i32.shl + (local.get $5) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $4) + (i32.const 1) + ) + ) + (i32.eq + (local.get $4) + (i32.const 31) + ) + ) + ) + ) + (local.set $1 + (i32.load + (local.get $2) + ) + ) + (block $__rjto$9 + (block $__rjti$9 + (loop $while-in74 + (br_if $__rjti$9 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $1) + ) + (i32.const -8) + ) + (local.get $5) + ) + ) + (local.set $2 + (i32.shl + (local.get $4) + (i32.const 1) + ) + ) + (if + (local.tee $3 + (i32.load + (local.tee $4 + (i32.add + (i32.add + (local.get $1) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $4) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block $block548 + (local.set $4 + (local.get $2) + ) + (local.set $1 + (local.get $3) + ) + (br $while-in74) + ) + ) + ) + (if + (i32.lt_u + (local.get $4) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block550 + (i32.store + (local.get $4) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $1) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once40) + ) + ) + (br $__rjto$9) + ) + (if + (i32.and + (i32.ge_u + (local.tee $4 + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + ) + (local.tee $3 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $1) + (local.get $3) + ) + ) + (block $block552 + (i32.store offset=12 + (local.get $4) + (local.get $6) + ) + (i32.store + (local.get $2) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $4) + ) + (i32.store offset=12 + (local.get $6) + (local.get $1) + ) + (i32.store offset=24 + (local.get $6) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + ) + ) + (block $block553 + (if + (i32.or + (i32.eqz + (local.tee $2 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.lt_u + (local.get $1) + (local.get $2) + ) + ) + (i32.store + (i32.const 192) + (local.get $1) + ) + ) + (i32.store + (i32.const 624) + (local.get $1) + ) + (i32.store + (i32.const 628) + (local.get $3) + ) + (i32.store + (i32.const 636) + (i32.const 0) + ) + (i32.store + (i32.const 212) + (i32.load + (i32.const 648) + ) + ) + (i32.store + (i32.const 208) + (i32.const -1) + ) + (local.set $2 + (i32.const 0) + ) + (loop $while-in43 + (i32.store offset=12 + (local.tee $4 + (i32.add + (i32.shl + (local.get $2) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (local.get $4) + ) + (i32.store offset=8 + (local.get $4) + (local.get $4) + ) + (br_if $while-in43 + (i32.ne + (local.tee $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (i32.const 32) + ) + ) + ) + (i32.store + (i32.const 200) + (local.tee $2 + (i32.add + (local.get $1) + (local.tee $1 + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + ) + ) + (i32.store + (i32.const 188) + (local.tee $1 + (i32.sub + (i32.add + (local.get $3) + (i32.const -40) + ) + (local.get $1) + ) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $1) + (i32.const 1) + ) + ) + (i32.store offset=4 + (i32.add + (local.get $2) + (local.get $1) + ) + (i32.const 40) + ) + (i32.store + (i32.const 204) + (i32.load + (i32.const 664) + ) + ) + ) + ) + ) + (br_if $folding-inner0 + (i32.gt_u + (local.tee $1 + (i32.load + (i32.const 188) + ) + ) + (local.get $0) + ) + ) + ) + (i32.store + (call $___errno_location) + (i32.const 12) + ) + (return + (i32.const 0) + ) + ) + (i32.store + (i32.const 188) + (local.tee $3 + (i32.sub + (local.get $1) + (local.get $0) + ) + ) + ) + (i32.store + (i32.const 200) + (local.tee $1 + (i32.add + (local.tee $2 + (i32.load + (i32.const 200) + ) + ) + (local.get $0) + ) + ) + ) + (i32.store offset=4 + (local.get $1) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 3) + ) + ) + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (func $_free (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (if + (i32.eqz + (local.get $0) + ) + (return) + ) + (if + (i32.lt_u + (local.tee $1 + (i32.add + (local.get $0) + (i32.const -8) + ) + ) + (local.tee $11 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (local.tee $5 + (i32.and + (local.tee $7 + (i32.load + (i32.add + (local.get $0) + (i32.const -4) + ) + ) + ) + (i32.const 3) + ) + ) + (i32.const 1) + ) + (call $_abort) + ) + (local.set $8 + (i32.add + (local.get $1) + (local.tee $0 + (i32.and + (local.get $7) + (i32.const -8) + ) + ) + ) + ) + (block $do-once + (if + (i32.and + (local.get $7) + (i32.const 1) + ) + (block $block + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + (block $block558 + (local.set $7 + (i32.load + (local.get $1) + ) + ) + (if + (i32.eqz + (local.get $5) + ) + (return) + ) + (if + (i32.lt_u + (local.tee $1 + (i32.add + (local.get $1) + (i32.sub + (i32.const 0) + (local.get $7) + ) + ) + ) + (local.get $11) + ) + (call $_abort) + ) + (local.set $0 + (i32.add + (local.get $7) + (local.get $0) + ) + ) + (if + (i32.eq + (local.get $1) + (i32.load + (i32.const 196) + ) + ) + (block $block562 + (if + (i32.ne + (i32.and + (local.tee $3 + (i32.load + (local.tee $2 + (i32.add + (local.get $8) + (i32.const 4) + ) + ) + ) + ) + (i32.const 3) + ) + (i32.const 3) + ) + (block $block564 + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + (i32.store + (i32.const 184) + (local.get $0) + ) + (i32.store + (local.get $2) + (i32.and + (local.get $3) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $1) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $1) + (local.get $0) + ) + (local.get $0) + ) + (return) + ) + ) + (local.set $5 + (i32.shr_u + (local.get $7) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $7) + (i32.const 256) + ) + (block $block566 + (local.set $6 + (i32.load offset=12 + (local.get $1) + ) + ) + (if + (i32.ne + (local.tee $2 + (i32.load offset=8 + (local.get $1) + ) + ) + (local.tee $3 + (i32.add + (i32.shl + (local.get $5) + (i32.const 3) + ) + (i32.const 216) + ) + ) + ) + (block $block568 + (if + (i32.lt_u + (local.get $2) + (local.get $11) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load offset=12 + (local.get $2) + ) + (local.get $1) + ) + (call $_abort) + ) + ) + ) + (if + (i32.eq + (local.get $6) + (local.get $2) + ) + (block $block572 + (i32.store + (i32.const 176) + (i32.and + (i32.load + (i32.const 176) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $5) + ) + (i32.const -1) + ) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + (if + (i32.eq + (local.get $6) + (local.get $3) + ) + (local.set $4 + (i32.add + (local.get $6) + (i32.const 8) + ) + ) + (block $block574 + (if + (i32.lt_u + (local.get $6) + (local.get $11) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $3 + (i32.add + (local.get $6) + (i32.const 8) + ) + ) + ) + (local.get $1) + ) + (local.set $4 + (local.get $3) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=12 + (local.get $2) + (local.get $6) + ) + (i32.store + (local.get $4) + (local.get $2) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + (local.set $12 + (i32.load offset=24 + (local.get $1) + ) + ) + (block $do-once0 + (if + (i32.eq + (local.tee $4 + (i32.load offset=12 + (local.get $1) + ) + ) + (local.get $1) + ) + (block $block578 + (if + (i32.eqz + (local.tee $5 + (i32.load + (local.tee $4 + (i32.add + (local.tee $7 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (if + (local.tee $5 + (i32.load + (local.get $7) + ) + ) + (local.set $4 + (local.get $7) + ) + (block $block581 + (local.set $6 + (i32.const 0) + ) + (br $do-once0) + ) + ) + ) + (loop $while-in + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $5) + (i32.const 20) + ) + ) + ) + ) + (block $block583 + (local.set $5 + (local.get $7) + ) + (local.set $4 + (local.get $10) + ) + (br $while-in) + ) + ) + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + ) + ) + (block $block585 + (local.set $5 + (local.get $7) + ) + (local.set $4 + (local.get $10) + ) + (br $while-in) + ) + ) + ) + (if + (i32.lt_u + (local.get $4) + (local.get $11) + ) + (call $_abort) + (block $block587 + (i32.store + (local.get $4) + (i32.const 0) + ) + (local.set $6 + (local.get $5) + ) + ) + ) + ) + (block $block588 + (if + (i32.lt_u + (local.tee $10 + (i32.load offset=8 + (local.get $1) + ) + ) + (local.get $11) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $7 + (i32.add + (local.get $10) + (i32.const 12) + ) + ) + ) + (local.get $1) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $5 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + (local.get $1) + ) + (block $block592 + (i32.store + (local.get $7) + (local.get $4) + ) + (i32.store + (local.get $5) + (local.get $10) + ) + (local.set $6 + (local.get $4) + ) + ) + (call $_abort) + ) + ) + ) + ) + (if + (local.get $12) + (block $block594 + (if + (i32.eq + (local.get $1) + (i32.load + (local.tee $4 + (i32.add + (i32.shl + (local.tee $5 + (i32.load offset=28 + (local.get $1) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block $block596 + (i32.store + (local.get $4) + (local.get $6) + ) + (if + (i32.eqz + (local.get $6) + ) + (block $block598 + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $5) + ) + (i32.const -1) + ) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + ) + (block $block599 + (if + (i32.lt_u + (local.get $12) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $4 + (i32.add + (local.get $12) + (i32.const 16) + ) + ) + ) + (local.get $1) + ) + (i32.store + (local.get $4) + (local.get $6) + ) + (i32.store offset=20 + (local.get $12) + (local.get $6) + ) + ) + (if + (i32.eqz + (local.get $6) + ) + (block $block603 + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $6) + (local.tee $5 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $6) + (local.get $12) + ) + (if + (local.tee $7 + (i32.load + (local.tee $4 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $7) + (local.get $5) + ) + (call $_abort) + (block $block607 + (i32.store offset=16 + (local.get $6) + (local.get $7) + ) + (i32.store offset=24 + (local.get $7) + (local.get $6) + ) + ) + ) + ) + (if + (local.tee $4 + (i32.load offset=4 + (local.get $4) + ) + ) + (if + (i32.lt_u + (local.get $4) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block610 + (i32.store offset=20 + (local.get $6) + (local.get $4) + ) + (i32.store offset=24 + (local.get $4) + (local.get $6) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + (block $block611 + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + ) + (block $block612 + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + ) + ) + ) + (if + (i32.ge_u + (local.get $2) + (local.get $8) + ) + (call $_abort) + ) + (if + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 4) + ) + ) + ) + ) + (i32.const 1) + ) + ) + (call $_abort) + ) + (if + (i32.and + (local.get $1) + (i32.const 2) + ) + (block $block616 + (i32.store + (local.get $0) + (i32.and + (local.get $1) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $2) + (local.get $3) + ) + (local.get $3) + ) + ) + (block $block617 + (if + (i32.eq + (local.get $8) + (i32.load + (i32.const 200) + ) + ) + (block $block619 + (i32.store + (i32.const 188) + (local.tee $0 + (i32.add + (i32.load + (i32.const 188) + ) + (local.get $3) + ) + ) + ) + (i32.store + (i32.const 200) + (local.get $2) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (if + (i32.ne + (local.get $2) + (i32.load + (i32.const 196) + ) + ) + (return) + ) + (i32.store + (i32.const 196) + (i32.const 0) + ) + (i32.store + (i32.const 184) + (i32.const 0) + ) + (return) + ) + ) + (if + (i32.eq + (local.get $8) + (i32.load + (i32.const 196) + ) + ) + (block $block622 + (i32.store + (i32.const 184) + (local.tee $0 + (i32.add + (i32.load + (i32.const 184) + ) + (local.get $3) + ) + ) + ) + (i32.store + (i32.const 196) + (local.get $2) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $2) + (local.get $0) + ) + (local.get $0) + ) + (return) + ) + ) + (local.set $5 + (i32.add + (i32.and + (local.get $1) + (i32.const -8) + ) + (local.get $3) + ) + ) + (local.set $3 + (i32.shr_u + (local.get $1) + (i32.const 3) + ) + ) + (block $do-once4 + (if + (i32.lt_u + (local.get $1) + (i32.const 256) + ) + (block $block624 + (local.set $4 + (i32.load offset=12 + (local.get $8) + ) + ) + (if + (i32.ne + (local.tee $1 + (i32.load offset=8 + (local.get $8) + ) + ) + (local.tee $0 + (i32.add + (i32.shl + (local.get $3) + (i32.const 3) + ) + (i32.const 216) + ) + ) + ) + (block $block626 + (if + (i32.lt_u + (local.get $1) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load offset=12 + (local.get $1) + ) + (local.get $8) + ) + (call $_abort) + ) + ) + ) + (if + (i32.eq + (local.get $4) + (local.get $1) + ) + (block $block630 + (i32.store + (i32.const 176) + (i32.and + (i32.load + (i32.const 176) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $3) + ) + (i32.const -1) + ) + ) + ) + (br $do-once4) + ) + ) + (if + (i32.eq + (local.get $4) + (local.get $0) + ) + (local.set $14 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + (block $block632 + (if + (i32.lt_u + (local.get $4) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + (local.get $8) + ) + (local.set $14 + (local.get $0) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=12 + (local.get $1) + (local.get $4) + ) + (i32.store + (local.get $14) + (local.get $1) + ) + ) + (block $block635 + (local.set $6 + (i32.load offset=24 + (local.get $8) + ) + ) + (block $do-once6 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $8) + ) + ) + (local.get $8) + ) + (block $block637 + (if + (i32.eqz + (local.tee $3 + (i32.load + (local.tee $0 + (i32.add + (local.tee $1 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (if + (local.tee $3 + (i32.load + (local.get $1) + ) + ) + (local.set $0 + (local.get $1) + ) + (block $block640 + (local.set $9 + (i32.const 0) + ) + (br $do-once6) + ) + ) + ) + (loop $while-in9 + (if + (local.tee $1 + (i32.load + (local.tee $4 + (i32.add + (local.get $3) + (i32.const 20) + ) + ) + ) + ) + (block $block642 + (local.set $3 + (local.get $1) + ) + (local.set $0 + (local.get $4) + ) + (br $while-in9) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $4 + (i32.add + (local.get $3) + (i32.const 16) + ) + ) + ) + ) + (block $block644 + (local.set $3 + (local.get $1) + ) + (local.set $0 + (local.get $4) + ) + (br $while-in9) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block646 + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $9 + (local.get $3) + ) + ) + ) + ) + (block $block647 + (if + (i32.lt_u + (local.tee $4 + (i32.load offset=8 + (local.get $8) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $1 + (i32.add + (local.get $4) + (i32.const 12) + ) + ) + ) + (local.get $8) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $8) + ) + (block $block651 + (i32.store + (local.get $1) + (local.get $0) + ) + (i32.store + (local.get $3) + (local.get $4) + ) + (local.set $9 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (if + (local.get $6) + (block $block653 + (if + (i32.eq + (local.get $8) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $3 + (i32.load offset=28 + (local.get $8) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block $block655 + (i32.store + (local.get $0) + (local.get $9) + ) + (if + (i32.eqz + (local.get $9) + ) + (block $block657 + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $3) + ) + (i32.const -1) + ) + ) + ) + (br $do-once4) + ) + ) + ) + (block $block658 + (if + (i32.lt_u + (local.get $6) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + ) + (local.get $8) + ) + (i32.store + (local.get $0) + (local.get $9) + ) + (i32.store offset=20 + (local.get $6) + (local.get $9) + ) + ) + (br_if $do-once4 + (i32.eqz + (local.get $9) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $9) + (local.tee $3 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $9) + (local.get $6) + ) + (if + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.get $3) + ) + (call $_abort) + (block $block664 + (i32.store offset=16 + (local.get $9) + (local.get $1) + ) + (i32.store offset=24 + (local.get $1) + (local.get $9) + ) + ) + ) + ) + (if + (local.tee $0 + (i32.load offset=4 + (local.get $0) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block667 + (i32.store offset=20 + (local.get $9) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $9) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $5) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $2) + (local.get $5) + ) + (local.get $5) + ) + (if + (i32.eq + (local.get $2) + (i32.load + (i32.const 196) + ) + ) + (block $block669 + (i32.store + (i32.const 184) + (local.get $5) + ) + (return) + ) + (local.set $3 + (local.get $5) + ) + ) + ) + ) + (local.set $0 + (i32.shr_u + (local.get $3) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $3) + (i32.const 256) + ) + (block $block671 + (local.set $1 + (i32.add + (i32.shl + (local.get $0) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $3 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $3 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block674 + (local.set $15 + (local.get $3) + ) + (local.set $13 + (local.get $0) + ) + ) + ) + (block $block675 + (i32.store + (i32.const 176) + (i32.or + (local.get $3) + (local.get $0) + ) + ) + (local.set $15 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (local.set $13 + (local.get $1) + ) + ) + ) + (i32.store + (local.get $15) + (local.get $2) + ) + (i32.store offset=12 + (local.get $13) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $13) + ) + (i32.store offset=12 + (local.get $2) + (local.get $1) + ) + (return) + ) + ) + (local.set $4 + (i32.add + (i32.shl + (local.tee $5 + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $3) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $3) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $4 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $4) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $2) + (local.get $5) + ) + (i32.store offset=20 + (local.get $2) + (i32.const 0) + ) + (i32.store offset=16 + (local.get $2) + (i32.const 0) + ) + (block $do-once12 + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 180) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $5) + ) + ) + ) + (block $block679 + (local.set $5 + (i32.shl + (local.get $3) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $5) + (i32.const 1) + ) + ) + (i32.eq + (local.get $5) + (i32.const 31) + ) + ) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + (block $__rjto$1 + (block $__rjti$1 + (loop $while-in15 + (br_if $__rjti$1 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $3) + ) + ) + (local.set $4 + (i32.shl + (local.get $5) + (i32.const 1) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $5 + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $5) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block $block681 + (local.set $5 + (local.get $4) + ) + (local.set $0 + (local.get $1) + ) + (br $while-in15) + ) + ) + ) + (if + (i32.lt_u + (local.get $5) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block $block683 + (i32.store + (local.get $5) + (local.get $2) + ) + (i32.store offset=24 + (local.get $2) + (local.get $0) + ) + (i32.store offset=12 + (local.get $2) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $2) + ) + (br $do-once12) + ) + ) + (br $__rjto$1) + ) + (if + (i32.and + (i32.ge_u + (local.tee $4 + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + (local.tee $3 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $0) + (local.get $3) + ) + ) + (block $block685 + (i32.store offset=12 + (local.get $4) + (local.get $2) + ) + (i32.store + (local.get $1) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $4) + ) + (i32.store offset=12 + (local.get $2) + (local.get $0) + ) + (i32.store offset=24 + (local.get $2) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + (block $block686 + (i32.store + (i32.const 180) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (i32.store + (local.get $4) + (local.get $2) + ) + (i32.store offset=24 + (local.get $2) + (local.get $4) + ) + (i32.store offset=12 + (local.get $2) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $2) + ) + ) + ) + ) + (i32.store + (i32.const 208) + (local.tee $0 + (i32.add + (i32.load + (i32.const 208) + ) + (i32.const -1) + ) + ) + ) + (if + (local.get $0) + (return) + (local.set $0 + (i32.const 632) + ) + ) + (loop $while-in17 + (local.set $0 + (i32.add + (local.tee $3 + (i32.load + (local.get $0) + ) + ) + (i32.const 8) + ) + ) + (br_if $while-in17 + (local.get $3) + ) + ) + (i32.store + (i32.const 208) + (i32.const -1) + ) + ) + (func $runPostSets + (nop) + ) + (func $_i64Subtract (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (global.set $tempRet0 + (i32.sub + (i32.sub + (local.get $1) + (local.get $3) + ) + (i32.gt_u + (local.get $2) + (local.get $0) + ) + ) + ) + (i32.sub + (local.get $0) + (local.get $2) + ) + ) + (func $_i64Add (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local $4 i32) + (global.set $tempRet0 + (i32.add + (i32.add + (local.get $1) + (local.get $3) + ) + (i32.lt_u + (local.tee $4 + (i32.add + (local.get $0) + (local.get $2) + ) + ) + (local.get $0) + ) + ) + ) + (local.get $4) + ) + (func $_memset (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $4 + (i32.add + (local.get $0) + (local.get $2) + ) + ) + (if + (i32.ge_s + (local.get $2) + (i32.const 20) + ) + (block $block + (local.set $1 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + (if + (local.tee $3 + (i32.and + (local.get $0) + (i32.const 3) + ) + ) + (block $block689 + (local.set $3 + (i32.sub + (i32.add + (local.get $0) + (i32.const 4) + ) + (local.get $3) + ) + ) + (loop $while-in + (if + (i32.lt_s + (local.get $0) + (local.get $3) + ) + (block $block691 + (i32.store8 + (local.get $0) + (local.get $1) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (br $while-in) + ) + ) + ) + ) + ) + (local.set $3 + (i32.or + (i32.or + (i32.or + (local.get $1) + (i32.shl + (local.get $1) + (i32.const 8) + ) + ) + (i32.shl + (local.get $1) + (i32.const 16) + ) + ) + (i32.shl + (local.get $1) + (i32.const 24) + ) + ) + ) + (local.set $5 + (i32.and + (local.get $4) + (i32.const -4) + ) + ) + (loop $while-in1 + (if + (i32.lt_s + (local.get $0) + (local.get $5) + ) + (block $block693 + (i32.store + (local.get $0) + (local.get $3) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (br $while-in1) + ) + ) + ) + ) + ) + (loop $while-in3 + (if + (i32.lt_s + (local.get $0) + (local.get $4) + ) + (block $block695 + (i32.store8 + (local.get $0) + (local.get $1) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (br $while-in3) + ) + ) + ) + (i32.sub + (local.get $0) + (local.get $2) + ) + ) + (func $_bitshift64Lshr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (if + (i32.lt_s + (local.get $2) + (i32.const 32) + ) + (block $block + (global.set $tempRet0 + (i32.shr_u + (local.get $1) + (local.get $2) + ) + ) + (return + (i32.or + (i32.shr_u + (local.get $0) + (local.get $2) + ) + (i32.shl + (i32.and + (local.get $1) + (i32.sub + (i32.shl + (i32.const 1) + (local.get $2) + ) + (i32.const 1) + ) + ) + (i32.sub + (i32.const 32) + (local.get $2) + ) + ) + ) + ) + ) + ) + (global.set $tempRet0 + (i32.const 0) + ) + (i32.shr_u + (local.get $1) + (i32.sub + (local.get $2) + (i32.const 32) + ) + ) + ) + (func $_bitshift64Shl (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (if + (i32.lt_s + (local.get $2) + (i32.const 32) + ) + (block $block + (global.set $tempRet0 + (i32.or + (i32.shl + (local.get $1) + (local.get $2) + ) + (i32.shr_u + (i32.and + (local.get $0) + (i32.shl + (i32.sub + (i32.shl + (i32.const 1) + (local.get $2) + ) + (i32.const 1) + ) + (i32.sub + (i32.const 32) + (local.get $2) + ) + ) + ) + (i32.sub + (i32.const 32) + (local.get $2) + ) + ) + ) + ) + (return + (i32.shl + (local.get $0) + (local.get $2) + ) + ) + ) + ) + (global.set $tempRet0 + (i32.shl + (local.get $0) + (i32.sub + (local.get $2) + (i32.const 32) + ) + ) + ) + (i32.const 0) + ) + (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (i32.ge_s + (local.get $2) + (i32.const 4096) + ) + (return + (call $_emscripten_memcpy_big + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + ) + (local.set $3 + (local.get $0) + ) + (if + (i32.eq + (i32.and + (local.get $0) + (i32.const 3) + ) + (i32.and + (local.get $1) + (i32.const 3) + ) + ) + (block $block + (loop $while-in + (if + (i32.and + (local.get $0) + (i32.const 3) + ) + (block $block698 + (if + (i32.eqz + (local.get $2) + ) + (return + (local.get $3) + ) + ) + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (br $while-in) + ) + ) + ) + (loop $while-in1 + (if + (i32.ge_s + (local.get $2) + (i32.const 4) + ) + (block $block701 + (i32.store + (local.get $0) + (i32.load + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 4) + ) + ) + (br $while-in1) + ) + ) + ) + ) + ) + (loop $while-in3 + (if + (i32.gt_s + (local.get $2) + (i32.const 0) + ) + (block $block703 + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (br $while-in3) + ) + ) + ) + (local.get $3) + ) + (func $___udivdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (call $___udivmoddi4 + (local.get $0) + (local.get $1) + (local.get $2) + (local.get $3) + (i32.const 0) + ) + ) + (func $___uremdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local $4 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (drop + (call $___udivmoddi4 + (local.get $0) + (local.get $1) + (local.get $2) + (local.get $3) + (local.tee $0 + (local.get $4) + ) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (global.set $tempRet0 + (i32.load offset=4 + (local.get $0) + ) + ) + (i32.load + (local.get $0) + ) + ) + (func $___udivmoddi4 (param $xl i32) (param $xh i32) (param $yl i32) (param $yh i32) (param $r i32) (result i32) + (local $x64 i64) + (local $y64 i64) + (local.set $x64 + (i64.or + (i64.extend_i32_u + (local.get $xl) + ) + (i64.shl + (i64.extend_i32_u + (local.get $xh) + ) + (i64.const 32) + ) + ) + ) + (local.set $y64 + (i64.or + (i64.extend_i32_u + (local.get $yl) + ) + (i64.shl + (i64.extend_i32_u + (local.get $yh) + ) + (i64.const 32) + ) + ) + ) + (if + (local.get $r) + (i64.store + (local.get $r) + (i64.rem_u + (local.get $x64) + (local.get $y64) + ) + ) + ) + (local.set $x64 + (i64.div_u + (local.get $x64) + (local.get $y64) + ) + ) + (global.set $tempRet0 + (i32.wrap_i64 + (i64.shr_u + (local.get $x64) + (i64.const 32) + ) + ) + ) + (i32.wrap_i64 + (local.get $x64) + ) + ) + (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) + (call_indirect (type $i32_=>_i32) + (local.get $1) + (i32.and + (local.get $0) + (i32.const 1) + ) + ) + ) + (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (call_indirect (type $i32_i32_i32_=>_i32) + (local.get $1) + (local.get $2) + (local.get $3) + (i32.add + (i32.and + (local.get $0) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (func $dynCall_vi (param $0 i32) (param $1 i32) + (call_indirect (type $i32_=>_none) + (local.get $1) + (i32.add + (i32.and + (local.get $0) + (i32.const 7) + ) + (i32.const 10) + ) + ) + ) + (func $b0 (param $0 i32) (result i32) + (call $nullFunc_ii + (i32.const 0) + ) + (i32.const 0) + ) + (func $b1 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (call $nullFunc_iiii + (i32.const 1) + ) + (i32.const 0) + ) + (func $b2 (param $0 i32) + (call $nullFunc_vi + (i32.const 2) + ) + ) +) diff -Nru binaryen-108/test/passes/inlining-optimizing_optimize-level=3.wast binaryen-99/test/passes/inlining-optimizing_optimize-level=3.wast --- binaryen-108/test/passes/inlining-optimizing_optimize-level=3.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/inlining-optimizing_optimize-level=3.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,15703 @@ +;; similar to test/emcc_hello_world.fromasm.clamp ;; +(module + (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$vi (func (param i32))) + (type $FUNCSIG$v (func)) + (type $FUNCSIG$i (func (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $FUNCSIG$vii (func (param i32 i32))) + (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) + (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) + (import "env" "tempDoublePtr" (global $tempDoublePtr$asm2wasm$import i32)) + (import "env" "abort" (func $abort)) + (import "env" "nullFunc_ii" (func $nullFunc_ii (param i32))) + (import "env" "nullFunc_iiii" (func $nullFunc_iiii (param i32))) + (import "env" "nullFunc_vi" (func $nullFunc_vi (param i32))) + (import "env" "_pthread_cleanup_pop" (func $_pthread_cleanup_pop (param i32))) + (import "env" "___lock" (func $___lock (param i32))) + (import "env" "_pthread_self" (func $_pthread_self (result i32))) + (import "env" "_abort" (func $_abort)) + (import "env" "___syscall6" (func $___syscall6 (param i32 i32) (result i32))) + (import "env" "_sbrk" (func $_sbrk (param i32) (result i32))) + (import "env" "_time" (func $_time (param i32) (result i32))) + (import "env" "_emscripten_memcpy_big" (func $_emscripten_memcpy_big (param i32 i32 i32) (result i32))) + (import "env" "___syscall54" (func $___syscall54 (param i32 i32) (result i32))) + (import "env" "___unlock" (func $___unlock (param i32))) + (import "env" "___syscall140" (func $___syscall140 (param i32 i32) (result i32))) + (import "env" "_pthread_cleanup_push" (func $_pthread_cleanup_push (param i32 i32))) + (import "env" "_sysconf" (func $_sysconf (param i32) (result i32))) + (import "env" "___syscall146" (func $___syscall146 (param i32 i32) (result i32))) + (import "env" "memory" (memory $0 256 256)) + (import "env" "table" (table 18 18 funcref)) + (import "env" "memoryBase" (global $memoryBase i32)) + (import "env" "tableBase" (global $tableBase i32)) + (global $STACKTOP (mut i32) (global.get $STACKTOP$asm2wasm$import)) + (global $STACK_MAX (mut i32) (global.get $STACK_MAX$asm2wasm$import)) + (global $tempDoublePtr (mut i32) (global.get $tempDoublePtr$asm2wasm$import)) + (global $__THREW__ (mut i32) (i32.const 0)) + (global $threwValue (mut i32) (i32.const 0)) + (global $tempRet0 (mut i32) (i32.const 0)) + (elem (global.get $tableBase) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) + (data (i32.const 1024) "emcc_hello_world.asm.js") + (export "_i64Subtract" (func $_i64Subtract)) + (export "_free" (func $_free)) + (export "_main" (func $_main)) + (export "_i64Add" (func $_i64Add)) + (export "_memset" (func $_memset)) + (export "_malloc" (func $_malloc)) + (export "_memcpy" (func $_memcpy)) + (export "_bitshift64Lshr" (func $_bitshift64Lshr)) + (export "_fflush" (func $_fflush)) + (export "___errno_location" (func $___errno_location)) + (export "_bitshift64Shl" (func $_bitshift64Shl)) + (export "runPostSets" (func $runPostSets)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackSave" (func $stackSave)) + (export "stackRestore" (func $stackRestore)) + (export "establishStackSpace" (func $establishStackSpace)) + (export "setThrew" (func $setThrew)) + (export "setTempRet0" (func $setTempRet0)) + (export "getTempRet0" (func $getTempRet0)) + (export "dynCall_ii" (func $dynCall_ii)) + (export "dynCall_iiii" (func $dynCall_iiii)) + (export "dynCall_vi" (func $dynCall_vi)) + (export "___udivmoddi4" (func $___udivmoddi4)) + (func $stackAlloc (param $0 i32) (result i32) + (local $1 i32) + (local.set $1 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (local.get $0) + ) + ) + (global.set $STACKTOP + (i32.and + (i32.add + (global.get $STACKTOP) + (i32.const 15) + ) + (i32.const -16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.get $1) + ) + (func $stackSave (result i32) + (global.get $STACKTOP) + ) + (func $stackRestore (param $0 i32) + (global.set $STACKTOP + (local.get $0) + ) + ) + (func $establishStackSpace (param $0 i32) (param $1 i32) + (global.set $STACKTOP + (local.get $0) + ) + (global.set $STACK_MAX + (local.get $1) + ) + ) + (func $setThrew (param $0 i32) (param $1 i32) + (if + (i32.eqz + (global.get $__THREW__) + ) + (block + (global.set $__THREW__ + (local.get $0) + ) + (global.set $threwValue + (local.get $1) + ) + ) + ) + ) + (func $setTempRet0 (param $0 i32) + (global.set $tempRet0 + (local.get $0) + ) + ) + (func $getTempRet0 (result i32) + (global.get $tempRet0) + ) + (func $_main (result i32) + (local $0 i32) + (local.set $0 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (drop + (call $_printf + (i32.const 672) + (local.get $0) + ) + ) + (global.set $STACKTOP + (local.get $0) + ) + (i32.const 0) + ) + (func $_frexp (param $0 f64) (param $1 i32) (result f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (f64.store + (global.get $tempDoublePtr) + (local.get $0) + ) + (block $switch + (block $switch-default + (block $switch-case0 + (block $switch-case + (br_table $switch-case $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case0 $switch-default + (local.tee $3 + (i32.and + (local.tee $3 + (call $_bitshift64Lshr + (local.tee $2 + (i32.load + (global.get $tempDoublePtr) + ) + ) + (local.tee $4 + (i32.load offset=4 + (global.get $tempDoublePtr) + ) + ) + (i32.const 52) + ) + ) + (i32.const 2047) + ) + ) + ) + ) + (i32.store + (local.get $1) + (local.tee $2 + (if (result i32) + (f64.ne + (local.get $0) + (f64.const 0) + ) + (block (result i32) + (local.set $0 + (call $_frexp + (f64.mul + (local.get $0) + (f64.const 18446744073709551615) + ) + (local.get $1) + ) + ) + (i32.add + (i32.load + (local.get $1) + ) + (i32.const -64) + ) + ) + (i32.const 0) + ) + ) + ) + (br $switch) + ) + (br $switch) + ) + (i32.store + (local.get $1) + (i32.add + (local.get $3) + (i32.const -1022) + ) + ) + (i32.store + (global.get $tempDoublePtr) + (local.get $2) + ) + (i32.store offset=4 + (global.get $tempDoublePtr) + (i32.or + (i32.and + (local.get $4) + (i32.const -2146435073) + ) + (i32.const 1071644672) + ) + ) + (local.set $0 + (f64.load + (global.get $tempDoublePtr) + ) + ) + ) + (local.get $0) + ) + (func $_strerror (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (i32.const 0) + ) + (block $__rjto$1 + (block $__rjti$1 + (block $__rjti$0 + (loop $while-in + (br_if $__rjti$0 + (i32.eq + (i32.load8_u offset=687 + (local.get $1) + ) + (local.get $0) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 87) + ) + ) + (local.set $1 + (i32.const 87) + ) + (br $__rjti$1) + ) + ) + (br_if $__rjti$1 + (local.get $1) + ) + (local.set $0 + (i32.const 775) + ) + (br $__rjto$1) + ) + (local.set $0 + (i32.const 775) + ) + (loop $while-in1 + (loop $while-in3 + (local.set $2 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (if + (i32.load8_s + (local.get $0) + ) + (block + (local.set $0 + (local.get $2) + ) + (br $while-in3) + ) + (local.set $0 + (local.get $2) + ) + ) + ) + (br_if $while-in1 + (local.tee $1 + (i32.add + (local.get $1) + (i32.const -1) + ) + ) + ) + ) + ) + (local.get $0) + ) + (func $___errno_location (result i32) + (if (result i32) + (i32.load + (i32.const 16) + ) + (i32.load offset=60 + (call $_pthread_self) + ) + (i32.const 60) + ) + ) + (func $___stdio_close (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (i32.store + (local.tee $2 + (local.get $1) + ) + (i32.load offset=60 + (local.get $0) + ) + ) + (local.set $0 + (call $___syscall_ret + (call $___syscall6 + (i32.const 6) + (local.get $2) + ) + ) + ) + (global.set $STACKTOP + (local.get $1) + ) + (local.get $0) + ) + (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 80) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $3 + (local.get $4) + ) + (local.set $5 + (i32.add + (local.get $4) + (i32.const 12) + ) + ) + (i32.store offset=36 + (local.get $0) + (i32.const 4) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 64) + ) + ) + (block + (i32.store + (local.get $3) + (i32.load offset=60 + (local.get $0) + ) + ) + (i32.store offset=4 + (local.get $3) + (i32.const 21505) + ) + (i32.store offset=8 + (local.get $3) + (local.get $5) + ) + (if + (call $___syscall54 + (i32.const 54) + (local.get $3) + ) + (i32.store8 offset=75 + (local.get $0) + (i32.const -1) + ) + ) + ) + ) + (local.set $0 + (call $___stdio_write + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (local.get $0) + ) + (func $___stdio_seek (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 32) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (i32.store + (local.tee $3 + (local.get $4) + ) + (i32.load offset=60 + (local.get $0) + ) + ) + (i32.store offset=4 + (local.get $3) + (i32.const 0) + ) + (i32.store offset=8 + (local.get $3) + (local.get $1) + ) + (i32.store offset=12 + (local.get $3) + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 20) + ) + ) + ) + (i32.store offset=16 + (local.get $3) + (local.get $2) + ) + (local.set $0 + (if (result i32) + (i32.lt_s + (call $___syscall_ret + (call $___syscall140 + (i32.const 140) + (local.get $3) + ) + ) + (i32.const 0) + ) + (block (result i32) + (i32.store + (local.get $0) + (i32.const -1) + ) + (i32.const -1) + ) + (i32.load + (local.get $0) + ) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (local.get $0) + ) + (func $_fflush (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (block $do-once + (if + (local.get $0) + (block + (if + (i32.le_s + (i32.load offset=76 + (local.get $0) + ) + (i32.const -1) + ) + (block + (local.set $0 + (call $___fflush_unlocked + (local.get $0) + ) + ) + (br $do-once) + ) + ) + (local.set $2 + (i32.eqz + (call $___lockfile + (local.get $0) + ) + ) + ) + (local.set $1 + (call $___fflush_unlocked + (local.get $0) + ) + ) + (local.set $0 + (if (result i32) + (local.get $2) + (local.get $1) + (block (result i32) + (call $___unlockfile + (local.get $0) + ) + (local.get $1) + ) + ) + ) + ) + (block + (local.set $0 + (if (result i32) + (i32.load + (i32.const 12) + ) + (call $_fflush + (i32.load + (i32.const 12) + ) + ) + (i32.const 0) + ) + ) + (call $___lock + (i32.const 44) + ) + (if + (local.tee $1 + (i32.load + (i32.const 40) + ) + ) + (loop $while-in + (local.set $2 + (if (result i32) + (i32.gt_s + (i32.load offset=76 + (local.get $1) + ) + (i32.const -1) + ) + (call $___lockfile + (local.get $1) + ) + (i32.const 0) + ) + ) + (if + (i32.gt_u + (i32.load offset=20 + (local.get $1) + ) + (i32.load offset=28 + (local.get $1) + ) + ) + (local.set $0 + (i32.or + (call $___fflush_unlocked + (local.get $1) + ) + (local.get $0) + ) + ) + ) + (if + (local.get $2) + (call $___unlockfile + (local.get $1) + ) + ) + (br_if $while-in + (local.tee $1 + (i32.load offset=56 + (local.get $1) + ) + ) + ) + ) + ) + (call $___unlock + (i32.const 44) + ) + ) + ) + ) + (local.get $0) + ) + (func $_printf (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local.set $2 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (i32.store + (local.tee $3 + (local.get $2) + ) + (local.get $1) + ) + (local.set $0 + (call $_vfprintf + (i32.load + (i32.const 8) + ) + (local.get $0) + (local.get $3) + ) + ) + (global.set $STACKTOP + (local.get $2) + ) + (local.get $0) + ) + (func $___lockfile (param $0 i32) (result i32) + (i32.const 0) + ) + (func $___unlockfile (param $0 i32) + (nop) + ) + (func $___stdio_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local.set $8 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 48) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $9 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + (local.set $10 + (local.get $8) + ) + (i32.store + (local.tee $4 + (i32.add + (local.get $8) + (i32.const 32) + ) + ) + (local.tee $3 + (i32.load + (local.tee $6 + (i32.add + (local.get $0) + (i32.const 28) + ) + ) + ) + ) + ) + (i32.store offset=4 + (local.get $4) + (local.tee $3 + (i32.sub + (i32.load + (local.tee $11 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + ) + (local.get $3) + ) + ) + ) + (i32.store offset=8 + (local.get $4) + (local.get $1) + ) + (i32.store offset=12 + (local.get $4) + (local.get $2) + ) + (local.set $13 + (i32.add + (local.get $0) + (i32.const 60) + ) + ) + (local.set $14 + (i32.add + (local.get $0) + (i32.const 44) + ) + ) + (local.set $1 + (local.get $4) + ) + (local.set $4 + (i32.const 2) + ) + (local.set $12 + (i32.add + (local.get $3) + (local.get $2) + ) + ) + (block $__rjto$1 + (block $__rjti$1 + (block $__rjti$0 + (loop $while-in + (if + (i32.load + (i32.const 16) + ) + (block + (call $_pthread_cleanup_push + (i32.const 5) + (local.get $0) + ) + (i32.store + (local.get $10) + (i32.load + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $10) + (local.get $1) + ) + (i32.store offset=8 + (local.get $10) + (local.get $4) + ) + (local.set $3 + (call $___syscall_ret + (call $___syscall146 + (i32.const 146) + (local.get $10) + ) + ) + ) + (call $_pthread_cleanup_pop + (i32.const 0) + ) + ) + (block + (i32.store + (local.get $9) + (i32.load + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $9) + (local.get $1) + ) + (i32.store offset=8 + (local.get $9) + (local.get $4) + ) + (local.set $3 + (call $___syscall_ret + (call $___syscall146 + (i32.const 146) + (local.get $9) + ) + ) + ) + ) + ) + (br_if $__rjti$0 + (i32.eq + (local.get $12) + (local.get $3) + ) + ) + (br_if $__rjti$1 + (i32.lt_s + (local.get $3) + (i32.const 0) + ) + ) + (local.set $5 + (if (result i32) + (i32.gt_u + (local.get $3) + (local.tee $5 + (i32.load offset=4 + (local.get $1) + ) + ) + ) + (block (result i32) + (i32.store + (local.get $6) + (local.tee $7 + (i32.load + (local.get $14) + ) + ) + ) + (i32.store + (local.get $11) + (local.get $7) + ) + (local.set $7 + (i32.load offset=12 + (local.get $1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (local.set $4 + (i32.add + (local.get $4) + (i32.const -1) + ) + ) + (i32.sub + (local.get $3) + (local.get $5) + ) + ) + (block (result i32) + (if + (i32.eq + (local.get $4) + (i32.const 2) + ) + (block + (i32.store + (local.get $6) + (i32.add + (i32.load + (local.get $6) + ) + (local.get $3) + ) + ) + (local.set $7 + (local.get $5) + ) + (local.set $4 + (i32.const 2) + ) + ) + (local.set $7 + (local.get $5) + ) + ) + (local.get $3) + ) + ) + ) + (i32.store + (local.get $1) + (i32.add + (i32.load + (local.get $1) + ) + (local.get $5) + ) + ) + (i32.store offset=4 + (local.get $1) + (i32.sub + (local.get $7) + (local.get $5) + ) + ) + (local.set $12 + (i32.sub + (local.get $12) + (local.get $3) + ) + ) + (br $while-in) + ) + ) + (i32.store offset=16 + (local.get $0) + (i32.add + (local.tee $1 + (i32.load + (local.get $14) + ) + ) + (i32.load offset=48 + (local.get $0) + ) + ) + ) + (i32.store + (local.get $6) + (local.get $1) + ) + (i32.store + (local.get $11) + (local.get $1) + ) + (br $__rjto$1) + ) + (i32.store offset=16 + (local.get $0) + (i32.const 0) + ) + (i32.store + (local.get $6) + (i32.const 0) + ) + (i32.store + (local.get $11) + (i32.const 0) + ) + (i32.store + (local.get $0) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (local.set $2 + (if (result i32) + (i32.eq + (local.get $4) + (i32.const 2) + ) + (i32.const 0) + (i32.sub + (local.get $2) + (i32.load offset=4 + (local.get $1) + ) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $8) + ) + (local.get $2) + ) + (func $_vfprintf (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 224) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $5 + (i32.add + (local.get $4) + (i32.const 120) + ) + ) + (local.set $7 + (local.get $4) + ) + (local.set $6 + (i32.add + (local.get $4) + (i32.const 136) + ) + ) + (local.set $9 + (i32.add + (local.tee $3 + (local.tee $8 + (i32.add + (local.get $4) + (i32.const 80) + ) + ) + ) + (i32.const 40) + ) + ) + (loop $do-in + (i32.store + (local.get $3) + (i32.const 0) + ) + (br_if $do-in + (i32.lt_s + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 4) + ) + ) + (local.get $9) + ) + ) + ) + (i32.store + (local.get $5) + (i32.load + (local.get $2) + ) + ) + (local.set $0 + (if (result i32) + (i32.lt_s + (call $_printf_core + (i32.const 0) + (local.get $1) + (local.get $5) + (local.get $7) + (local.get $8) + ) + (i32.const 0) + ) + (i32.const -1) + (block (result i32) + (local.set $14 + (if (result i32) + (i32.gt_s + (i32.load offset=76 + (local.get $0) + ) + (i32.const -1) + ) + (call $___lockfile + (local.get $0) + ) + (i32.const 0) + ) + ) + (local.set $10 + (i32.load + (local.get $0) + ) + ) + (if + (i32.lt_s + (i32.load8_s offset=74 + (local.get $0) + ) + (i32.const 1) + ) + (i32.store + (local.get $0) + (i32.and + (local.get $10) + (i32.const -33) + ) + ) + ) + (if + (i32.load + (local.tee $11 + (i32.add + (local.get $0) + (i32.const 48) + ) + ) + ) + (local.set $1 + (call $_printf_core + (local.get $0) + (local.get $1) + (local.get $5) + (local.get $7) + (local.get $8) + ) + ) + (block + (local.set $13 + (i32.load + (local.tee $12 + (i32.add + (local.get $0) + (i32.const 44) + ) + ) + ) + ) + (i32.store + (local.get $12) + (local.get $6) + ) + (i32.store + (local.tee $9 + (i32.add + (local.get $0) + (i32.const 28) + ) + ) + (local.get $6) + ) + (i32.store + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + (local.get $6) + ) + (i32.store + (local.get $11) + (i32.const 80) + ) + (i32.store + (local.tee $2 + (i32.add + (local.get $0) + (i32.const 16) + ) + ) + (i32.add + (local.get $6) + (i32.const 80) + ) + ) + (local.set $1 + (call $_printf_core + (local.get $0) + (local.get $1) + (local.get $5) + (local.get $7) + (local.get $8) + ) + ) + (if + (local.get $13) + (block + (drop + (call_indirect (type $FUNCSIG$iiii) + (local.get $0) + (i32.const 0) + (i32.const 0) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $0) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (local.set $1 + (select + (local.get $1) + (i32.const -1) + (i32.load + (local.get $3) + ) + ) + ) + (i32.store + (local.get $12) + (local.get $13) + ) + (i32.store + (local.get $11) + (i32.const 0) + ) + (i32.store + (local.get $2) + (i32.const 0) + ) + (i32.store + (local.get $9) + (i32.const 0) + ) + (i32.store + (local.get $3) + (i32.const 0) + ) + ) + ) + ) + ) + (i32.store + (local.get $0) + (i32.or + (local.tee $2 + (i32.load + (local.get $0) + ) + ) + (i32.and + (local.get $10) + (i32.const 32) + ) + ) + ) + (if + (local.get $14) + (call $___unlockfile + (local.get $0) + ) + ) + (select + (i32.const -1) + (local.get $1) + (i32.and + (local.get $2) + (i32.const 32) + ) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (local.get $0) + ) + (func $___fwritex (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (block $label$break$L5 + (block $__rjti$0 + (br_if $__rjti$0 + (local.tee $3 + (i32.load + (local.tee $4 + (i32.add + (local.get $2) + (i32.const 16) + ) + ) + ) + ) + ) + (if + (call $___towrite + (local.get $2) + ) + (local.set $3 + (i32.const 0) + ) + (block + (local.set $3 + (i32.load + (local.get $4) + ) + ) + (br $__rjti$0) + ) + ) + (br $label$break$L5) + ) + (if + (i32.lt_u + (i32.sub + (local.get $3) + (local.tee $4 + (i32.load + (local.tee $5 + (i32.add + (local.get $2) + (i32.const 20) + ) + ) + ) + ) + ) + (local.get $1) + ) + (block + (local.set $3 + (call_indirect (type $FUNCSIG$iiii) + (local.get $2) + (local.get $0) + (local.get $1) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $2) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (br $label$break$L5) + ) + ) + (local.set $2 + (block $label$break$L10 (result i32) + (if (result i32) + (i32.gt_s + (i32.load8_s offset=75 + (local.get $2) + ) + (i32.const -1) + ) + (block (result i32) + (local.set $3 + (local.get $1) + ) + (loop $while-in + (drop + (br_if $label$break$L10 + (i32.const 0) + (i32.eqz + (local.get $3) + ) + ) + ) + (if + (i32.ne + (i32.load8_s + (i32.add + (local.get $0) + (local.tee $6 + (i32.add + (local.get $3) + (i32.const -1) + ) + ) + ) + ) + (i32.const 10) + ) + (block + (local.set $3 + (local.get $6) + ) + (br $while-in) + ) + ) + ) + (br_if $label$break$L5 + (i32.lt_u + (call_indirect (type $FUNCSIG$iiii) + (local.get $2) + (local.get $0) + (local.get $3) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $2) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + (local.get $3) + ) + ) + (local.set $4 + (i32.load + (local.get $5) + ) + ) + (local.set $1 + (i32.sub + (local.get $1) + (local.get $3) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (local.get $3) + ) + ) + (local.get $3) + ) + (i32.const 0) + ) + ) + ) + (drop + (call $_memcpy + (local.get $4) + (local.get $0) + (local.get $1) + ) + ) + (i32.store + (local.get $5) + (i32.add + (i32.load + (local.get $5) + ) + (local.get $1) + ) + ) + (local.set $3 + (i32.add + (local.get $2) + (local.get $1) + ) + ) + ) + (local.get $3) + ) + (func $___towrite (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (i32.load8_s + (local.tee $2 + (i32.add + (local.get $0) + (i32.const 74) + ) + ) + ) + ) + (i32.store8 + (local.get $2) + (i32.or + (i32.add + (local.get $1) + (i32.const 255) + ) + (local.get $1) + ) + ) + (local.tee $0 + (if (result i32) + (i32.and + (local.tee $1 + (i32.load + (local.get $0) + ) + ) + (i32.const 8) + ) + (block (result i32) + (i32.store + (local.get $0) + (i32.or + (local.get $1) + (i32.const 32) + ) + ) + (i32.const -1) + ) + (block (result i32) + (i32.store offset=8 + (local.get $0) + (i32.const 0) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (i32.store offset=28 + (local.get $0) + (local.tee $1 + (i32.load offset=44 + (local.get $0) + ) + ) + ) + (i32.store offset=20 + (local.get $0) + (local.get $1) + ) + (i32.store offset=16 + (local.get $0) + (i32.add + (local.get $1) + (i32.load offset=48 + (local.get $0) + ) + ) + ) + (i32.const 0) + ) + ) + ) + ) + (func $_wcrtomb (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (block $do-once (result i32) + (if (result i32) + (local.get $0) + (block (result i32) + (if + (i32.lt_u + (local.get $1) + (i32.const 128) + ) + (block + (i32.store8 + (local.get $0) + (local.get $1) + ) + (br $do-once + (i32.const 1) + ) + ) + ) + (if + (i32.lt_u + (local.get $1) + (i32.const 2048) + ) + (block + (i32.store8 + (local.get $0) + (i32.or + (i32.shr_u + (local.get $1) + (i32.const 6) + ) + (i32.const 192) + ) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.or + (i32.and + (local.get $1) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (br $do-once + (i32.const 2) + ) + ) + ) + (if + (i32.or + (i32.lt_u + (local.get $1) + (i32.const 55296) + ) + (i32.eq + (i32.and + (local.get $1) + (i32.const -8192) + ) + (i32.const 57344) + ) + ) + (block + (i32.store8 + (local.get $0) + (i32.or + (i32.shr_u + (local.get $1) + (i32.const 12) + ) + (i32.const 224) + ) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.or + (i32.and + (i32.shr_u + (local.get $1) + (i32.const 6) + ) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.or + (i32.and + (local.get $1) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (br $do-once + (i32.const 3) + ) + ) + ) + (if (result i32) + (i32.lt_u + (i32.add + (local.get $1) + (i32.const -65536) + ) + (i32.const 1048576) + ) + (block (result i32) + (i32.store8 + (local.get $0) + (i32.or + (i32.shr_u + (local.get $1) + (i32.const 18) + ) + (i32.const 240) + ) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.or + (i32.and + (i32.shr_u + (local.get $1) + (i32.const 12) + ) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.or + (i32.and + (i32.shr_u + (local.get $1) + (i32.const 6) + ) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.store8 offset=3 + (local.get $0) + (i32.or + (i32.and + (local.get $1) + (i32.const 63) + ) + (i32.const 128) + ) + ) + (i32.const 4) + ) + (block (result i32) + (i32.store + (call $___errno_location) + (i32.const 84) + ) + (i32.const -1) + ) + ) + ) + (i32.const 1) + ) + ) + ) + (func $_wctomb (param $0 i32) (param $1 i32) (result i32) + (if (result i32) + (local.get $0) + (call $_wcrtomb + (local.get $0) + (local.get $1) + (i32.const 0) + ) + (i32.const 0) + ) + ) + (func $_memchr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $5 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + (block $label$break$L8 + (block $__rjti$2 + (if + (i32.and + (local.tee $4 + (i32.ne + (local.get $2) + (i32.const 0) + ) + ) + (i32.ne + (i32.and + (local.get $0) + (i32.const 3) + ) + (i32.const 0) + ) + ) + (block + (local.set $4 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + (local.set $3 + (local.get $2) + ) + (local.set $2 + (local.get $0) + ) + (loop $while-in + (br_if $__rjti$2 + (i32.eq + (i32.load8_u + (local.get $2) + ) + (i32.and + (local.get $4) + (i32.const 255) + ) + ) + ) + (br_if $while-in + (i32.and + (local.tee $0 + (i32.ne + (local.tee $3 + (i32.add + (local.get $3) + (i32.const -1) + ) + ) + (i32.const 0) + ) + ) + (i32.ne + (i32.and + (local.tee $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (i32.const 3) + ) + (i32.const 0) + ) + ) + ) + ) + ) + (block + (local.set $3 + (local.get $2) + ) + (local.set $2 + (local.get $0) + ) + (local.set $0 + (local.get $4) + ) + ) + ) + (br_if $__rjti$2 + (local.get $0) + ) + (local.set $0 + (i32.const 0) + ) + (br $label$break$L8) + ) + (local.set $0 + (local.get $3) + ) + (if + (i32.ne + (i32.load8_u + (local.get $2) + ) + (local.tee $1 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (block + (local.set $3 + (i32.mul + (local.get $5) + (i32.const 16843009) + ) + ) + (block $__rjto$0 + (block $__rjti$0 + (br_if $__rjti$0 + (i32.le_u + (local.get $0) + (i32.const 3) + ) + ) + (loop $while-in3 + (if + (i32.eqz + (i32.and + (i32.xor + (i32.and + (local.tee $4 + (i32.xor + (i32.load + (local.get $2) + ) + (local.get $3) + ) + ) + (i32.const -2139062144) + ) + (i32.const -2139062144) + ) + (i32.add + (local.get $4) + (i32.const -16843009) + ) + ) + ) + (block + (local.set $2 + (i32.add + (local.get $2) + (i32.const 4) + ) + ) + (br_if $while-in3 + (i32.gt_u + (local.tee $0 + (i32.add + (local.get $0) + (i32.const -4) + ) + ) + (i32.const 3) + ) + ) + (br $__rjti$0) + ) + ) + ) + (br $__rjto$0) + ) + (if + (i32.eqz + (local.get $0) + ) + (block + (local.set $0 + (i32.const 0) + ) + (br $label$break$L8) + ) + ) + ) + (loop $while-in5 + (br_if $label$break$L8 + (i32.eq + (i32.load8_u + (local.get $2) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (br_if $while-in5 + (local.tee $0 + (i32.add + (local.get $0) + (i32.const -1) + ) + ) + ) + (local.set $0 + (i32.const 0) + ) + ) + ) + ) + ) + (select + (local.get $2) + (i32.const 0) + (local.get $0) + ) + ) + (func $___syscall_ret (param $0 i32) (result i32) + (if (result i32) + (i32.gt_u + (local.get $0) + (i32.const -4096) + ) + (block (result i32) + (i32.store + (call $___errno_location) + (i32.sub + (i32.const 0) + (local.get $0) + ) + ) + (i32.const -1) + ) + (local.get $0) + ) + ) + (func $___fflush_unlocked (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local.tee $0 + (block $__rjto$0 (result i32) + (block $__rjti$0 + (br_if $__rjti$0 + (i32.le_u + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + ) + (i32.load + (local.tee $2 + (i32.add + (local.get $0) + (i32.const 28) + ) + ) + ) + ) + ) + (drop + (call_indirect (type $FUNCSIG$iiii) + (local.get $0) + (i32.const 0) + (i32.const 0) + (i32.add + (i32.and + (i32.load offset=36 + (local.get $0) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (br_if $__rjti$0 + (i32.load + (local.get $1) + ) + ) + (br $__rjto$0 + (i32.const -1) + ) + ) + (if + (i32.lt_u + (local.tee $4 + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + ) + ) + (local.tee $6 + (i32.load + (local.tee $5 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + ) + (drop + (call_indirect (type $FUNCSIG$iiii) + (local.get $0) + (i32.sub + (local.get $4) + (local.get $6) + ) + (i32.const 1) + (i32.add + (i32.and + (i32.load offset=40 + (local.get $0) + ) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.store offset=16 + (local.get $0) + (i32.const 0) + ) + (i32.store + (local.get $2) + (i32.const 0) + ) + (i32.store + (local.get $1) + (i32.const 0) + ) + (i32.store + (local.get $5) + (i32.const 0) + ) + (i32.store + (local.get $3) + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (func $_cleanup (param $0 i32) + (if + (i32.eqz + (i32.load offset=68 + (local.get $0) + ) + ) + (call $___unlockfile + (local.get $0) + ) + ) + ) + (func $f64-to-int (param $0 f64) (result i32) + (if (result i32) + (f64.ne + (local.get $0) + (local.get $0) + ) + (i32.const -2147483648) + (if (result i32) + (f64.ge + (local.get $0) + (f64.const 2147483648) + ) + (i32.const -2147483648) + (if (result i32) + (f64.le + (local.get $0) + (f64.const -2147483649) + ) + (i32.const -2147483648) + (i32.trunc_f64_s + (local.get $0) + ) + ) + ) + ) + ) + (func $i32s-div (param $0 i32) (param $1 i32) (result i32) + (if (result i32) + (local.get $1) + (if (result i32) + (i32.and + (i32.eq + (local.get $0) + (i32.const -2147483648) + ) + (i32.eq + (local.get $1) + (i32.const -1) + ) + ) + (i32.const 0) + (i32.div_s + (local.get $0) + (local.get $1) + ) + ) + (i32.const 0) + ) + ) + (func $i32u-rem (param $0 i32) (param $1 i32) (result i32) + (if (result i32) + (local.get $1) + (i32.rem_u + (local.get $0) + (local.get $1) + ) + (i32.const 0) + ) + ) + (func $i32u-div (param $0 i32) (param $1 i32) (result i32) + (if (result i32) + (local.get $1) + (i32.div_u + (local.get $0) + (local.get $1) + ) + (i32.const 0) + ) + ) + (func $_printf_core (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (result i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 f64) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 f64) + (local $24 i32) + (local $25 i32) + (local $26 i32) + (local $27 i32) + (local $28 i32) + (local $29 i32) + (local $30 i32) + (local $31 i32) + (local $32 i32) + (local $33 i32) + (local $34 i32) + (local $35 i32) + (local $36 i32) + (local $37 i32) + (local $38 i32) + (local $39 i32) + (local $40 i32) + (local $41 i32) + (local $42 i32) + (local $43 i32) + (local $44 i32) + (local $45 i32) + (local $46 i32) + (local $47 i32) + (local $48 i32) + (local $49 i32) + (local $50 i32) + (local $51 i32) + (local.set $25 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 624) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $20 + (i32.add + (local.get $25) + (i32.const 16) + ) + ) + (local.set $19 + (local.get $25) + ) + (local.set $36 + (i32.add + (local.get $25) + (i32.const 528) + ) + ) + (local.set $29 + (i32.ne + (local.get $0) + (i32.const 0) + ) + ) + (local.set $39 + (local.tee $26 + (i32.add + (local.tee $5 + (i32.add + (local.get $25) + (i32.const 536) + ) + ) + (i32.const 40) + ) + ) + ) + (local.set $40 + (i32.add + (local.get $5) + (i32.const 39) + ) + ) + (local.set $44 + (i32.add + (local.tee $41 + (i32.add + (local.get $25) + (i32.const 8) + ) + ) + (i32.const 4) + ) + ) + (local.set $34 + (i32.add + (local.tee $5 + (i32.add + (local.get $25) + (i32.const 576) + ) + ) + (i32.const 12) + ) + ) + (local.set $42 + (i32.add + (local.get $5) + (i32.const 11) + ) + ) + (local.set $45 + (i32.sub + (local.tee $28 + (local.get $34) + ) + (local.tee $37 + (local.tee $22 + (i32.add + (local.get $25) + (i32.const 588) + ) + ) + ) + ) + ) + (local.set $46 + (i32.sub + (i32.const -2) + (local.get $37) + ) + ) + (local.set $47 + (i32.add + (local.get $28) + (i32.const 2) + ) + ) + (local.set $49 + (i32.add + (local.tee $48 + (i32.add + (local.get $25) + (i32.const 24) + ) + ) + (i32.const 288) + ) + ) + (local.set $43 + (local.tee $30 + (i32.add + (local.get $22) + (i32.const 9) + ) + ) + ) + (local.set $35 + (i32.add + (local.get $22) + (i32.const 8) + ) + ) + (local.set $16 + (i32.const 0) + ) + (local.set $5 + (local.get $1) + ) + (local.set $10 + (i32.const 0) + ) + (local.set $1 + (i32.const 0) + ) + (block $label$break$L343 + (block $__rjti$9 + (loop $label$continue$L1 + (block $label$break$L1 + (if + (i32.gt_s + (local.get $16) + (i32.const -1) + ) + (local.set $16 + (if (result i32) + (i32.gt_s + (local.get $10) + (i32.sub + (i32.const 2147483647) + (local.get $16) + ) + ) + (block (result i32) + (i32.store + (call $___errno_location) + (i32.const 75) + ) + (i32.const -1) + ) + (i32.add + (local.get $10) + (local.get $16) + ) + ) + ) + ) + (br_if $__rjti$9 + (i32.eqz + (local.tee $7 + (i32.load8_s + (local.get $5) + ) + ) + ) + ) + (local.set $10 + (local.get $5) + ) + (block $label$break$L12 + (block $__rjti$1 + (loop $label$continue$L9 + (block $label$break$L9 + (block $switch-default + (block $switch-case0 + (block $switch-case + (br_table $switch-case0 $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case $switch-default + (i32.shr_s + (i32.shl + (local.get $7) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (local.set $6 + (local.get $10) + ) + (br $__rjti$1) + ) + (local.set $6 + (local.get $10) + ) + (br $label$break$L9) + ) + (local.set $7 + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + ) + (br $label$continue$L9) + ) + ) + (br $label$break$L12) + ) + (loop $while-in + (br_if $label$break$L12 + (i32.ne + (i32.load8_s offset=1 + (local.get $6) + ) + (i32.const 37) + ) + ) + (local.set $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + (br_if $while-in + (i32.eq + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 2) + ) + ) + ) + (i32.const 37) + ) + ) + ) + ) + (local.set $7 + (i32.sub + (local.get $10) + (local.get $5) + ) + ) + (if + (local.get $29) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $5) + (local.get $7) + (local.get $0) + ) + ) + ) + ) + (if + (i32.ne + (local.get $10) + (local.get $5) + ) + (block + (local.set $5 + (local.get $6) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + ) + (local.set $8 + (if (result i32) + (i32.lt_u + (local.tee $8 + (i32.add + (local.tee $11 + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $6) + (i32.const 1) + ) + ) + ) + ) + (i32.const -48) + ) + ) + (i32.const 10) + ) + (block (result i32) + (local.set $6 + (i32.load8_s + (local.tee $10 + (select + (i32.add + (local.get $6) + (i32.const 3) + ) + (local.get $10) + (local.tee $11 + (i32.eq + (i32.load8_s offset=2 + (local.get $6) + ) + (i32.const 36) + ) + ) + ) + ) + ) + ) + (local.set $17 + (select + (local.get $8) + (i32.const -1) + (local.get $11) + ) + ) + (select + (i32.const 1) + (local.get $1) + (local.get $11) + ) + ) + (block (result i32) + (local.set $6 + (local.get $11) + ) + (local.set $17 + (i32.const -1) + ) + (local.get $1) + ) + ) + ) + (block $label$break$L25 + (if + (i32.eq + (i32.and + (local.tee $11 + (i32.shr_s + (i32.shl + (local.get $6) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (i32.const -32) + ) + (i32.const 32) + ) + (block + (local.set $1 + (local.get $6) + ) + (local.set $6 + (local.get $11) + ) + (local.set $11 + (i32.const 0) + ) + (loop $while-in4 + (if + (i32.eqz + (i32.and + (i32.shl + (i32.const 1) + (i32.add + (local.get $6) + (i32.const -32) + ) + ) + (i32.const 75913) + ) + ) + (block + (local.set $6 + (local.get $1) + ) + (local.set $1 + (local.get $11) + ) + (br $label$break$L25) + ) + ) + (local.set $11 + (i32.or + (i32.shl + (i32.const 1) + (i32.add + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const -32) + ) + ) + (local.get $11) + ) + ) + (br_if $while-in4 + (i32.eq + (i32.and + (local.tee $6 + (local.tee $1 + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + ) + ) + (i32.const -32) + ) + (i32.const 32) + ) + ) + (local.set $6 + (local.get $1) + ) + (local.set $1 + (local.get $11) + ) + ) + ) + (local.set $1 + (i32.const 0) + ) + ) + ) + (block $do-once5 + (if + (i32.eq + (i32.and + (local.get $6) + (i32.const 255) + ) + (i32.const 42) + ) + (block + (local.set $10 + (block $__rjto$0 (result i32) + (block $__rjti$0 + (br_if $__rjti$0 + (i32.ge_u + (local.tee $11 + (i32.add + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + (i32.const -48) + ) + ) + (i32.const 10) + ) + ) + (br_if $__rjti$0 + (i32.ne + (i32.load8_s offset=2 + (local.get $10) + ) + (i32.const 36) + ) + ) + (i32.store + (i32.add + (local.get $4) + (i32.shl + (local.get $11) + (i32.const 2) + ) + ) + (i32.const 10) + ) + (drop + (i32.load offset=4 + (local.tee $6 + (i32.add + (local.get $3) + (i32.shl + (i32.add + (i32.load8_s + (local.get $6) + ) + (i32.const -48) + ) + (i32.const 3) + ) + ) + ) + ) + ) + (local.set $8 + (i32.const 1) + ) + (local.set $14 + (i32.load + (local.get $6) + ) + ) + (br $__rjto$0 + (i32.add + (local.get $10) + (i32.const 3) + ) + ) + ) + (if + (local.get $8) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (if + (i32.eqz + (local.get $29) + ) + (block + (local.set $11 + (local.get $1) + ) + (local.set $10 + (local.get $6) + ) + (local.set $1 + (i32.const 0) + ) + (local.set $14 + (i32.const 0) + ) + (br $do-once5) + ) + ) + (local.set $14 + (i32.load + (local.tee $10 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $10) + (i32.const 4) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.get $6) + ) + ) + (local.set $11 + (if (result i32) + (i32.lt_s + (local.get $14) + (i32.const 0) + ) + (block (result i32) + (local.set $14 + (i32.sub + (i32.const 0) + (local.get $14) + ) + ) + (i32.or + (local.get $1) + (i32.const 8192) + ) + ) + (local.get $1) + ) + ) + (local.set $1 + (local.get $8) + ) + ) + (if + (i32.lt_u + (local.tee $6 + (i32.add + (i32.shr_s + (i32.shl + (local.get $6) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const -48) + ) + ) + (i32.const 10) + ) + (block + (local.set $11 + (i32.const 0) + ) + (loop $while-in8 + (local.set $6 + (i32.add + (i32.mul + (local.get $11) + (i32.const 10) + ) + (local.get $6) + ) + ) + (if + (i32.lt_u + (local.tee $9 + (i32.add + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + (i32.const -48) + ) + ) + (i32.const 10) + ) + (block + (local.set $11 + (local.get $6) + ) + (local.set $6 + (local.get $9) + ) + (br $while-in8) + ) + ) + ) + (if + (i32.lt_s + (local.get $6) + (i32.const 0) + ) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + (block + (local.set $11 + (local.get $1) + ) + (local.set $1 + (local.get $8) + ) + (local.set $14 + (local.get $6) + ) + ) + ) + ) + (block + (local.set $11 + (local.get $1) + ) + (local.set $1 + (local.get $8) + ) + (local.set $14 + (i32.const 0) + ) + ) + ) + ) + ) + (local.set $6 + (block $label$break$L46 (result i32) + (if (result i32) + (i32.eq + (i32.load8_s + (local.get $10) + ) + (i32.const 46) + ) + (block (result i32) + (if + (i32.ne + (local.tee $8 + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + ) + (i32.const 42) + ) + (block + (if + (i32.lt_u + (local.tee $9 + (i32.add + (local.get $8) + (i32.const -48) + ) + ) + (i32.const 10) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $6 + (local.get $9) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (br $label$break$L46 + (i32.const 0) + ) + ) + ) + (loop $while-in11 + (drop + (br_if $label$break$L46 + (local.tee $6 + (i32.add + (i32.mul + (local.get $8) + (i32.const 10) + ) + (local.get $6) + ) + ) + (i32.ge_u + (local.tee $9 + (i32.add + (i32.load8_s + (local.tee $10 + (i32.add + (local.get $10) + (i32.const 1) + ) + ) + ) + (i32.const -48) + ) + ) + (i32.const 10) + ) + ) + ) + (local.set $8 + (local.get $6) + ) + (local.set $6 + (local.get $9) + ) + (br $while-in11) + ) + ) + ) + (if + (i32.lt_u + (local.tee $8 + (i32.add + (i32.load8_s + (local.tee $6 + (i32.add + (local.get $10) + (i32.const 2) + ) + ) + ) + (i32.const -48) + ) + ) + (i32.const 10) + ) + (if + (i32.eq + (i32.load8_s offset=3 + (local.get $10) + ) + (i32.const 36) + ) + (block + (i32.store + (i32.add + (local.get $4) + (i32.shl + (local.get $8) + (i32.const 2) + ) + ) + (i32.const 10) + ) + (drop + (i32.load offset=4 + (local.tee $6 + (i32.add + (local.get $3) + (i32.shl + (i32.add + (i32.load8_s + (local.get $6) + ) + (i32.const -48) + ) + (i32.const 3) + ) + ) + ) + ) + ) + (local.set $10 + (i32.add + (local.get $10) + (i32.const 4) + ) + ) + (br $label$break$L46 + (i32.load + (local.get $6) + ) + ) + ) + ) + ) + (if + (local.get $1) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (if (result i32) + (local.get $29) + (block (result i32) + (local.set $8 + (i32.load + (local.tee $10 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $10) + (i32.const 4) + ) + ) + (local.set $10 + (local.get $6) + ) + (local.get $8) + ) + (block (result i32) + (local.set $10 + (local.get $6) + ) + (i32.const 0) + ) + ) + ) + (i32.const -1) + ) + ) + ) + (local.set $8 + (local.get $10) + ) + (local.set $9 + (i32.const 0) + ) + (loop $while-in13 + (if + (i32.gt_u + (local.tee $12 + (i32.add + (i32.load8_s + (local.get $8) + ) + (i32.const -65) + ) + ) + (i32.const 57) + ) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (local.set $10 + (i32.add + (local.get $8) + (i32.const 1) + ) + ) + (if + (i32.lt_u + (i32.add + (local.tee $12 + (i32.and + (local.tee $13 + (i32.load8_s + (i32.add + (i32.add + (i32.mul + (local.get $9) + (i32.const 58) + ) + (i32.const 3611) + ) + (local.get $12) + ) + ) + ) + (i32.const 255) + ) + ) + (i32.const -1) + ) + (i32.const 8) + ) + (block + (local.set $8 + (local.get $10) + ) + (local.set $9 + (local.get $12) + ) + (br $while-in13) + ) + (local.set $18 + (local.get $8) + ) + ) + ) + (if + (i32.eqz + (i32.and + (local.get $13) + (i32.const 255) + ) + ) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (local.set $8 + (i32.gt_s + (local.get $17) + (i32.const -1) + ) + ) + (block $__rjto$2 + (block $__rjti$2 + (if + (i32.eq + (i32.and + (local.get $13) + (i32.const 255) + ) + (i32.const 19) + ) + (if + (local.get $8) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + (br $__rjti$2) + ) + (block + (if + (local.get $8) + (block + (i32.store + (i32.add + (local.get $4) + (i32.shl + (local.get $17) + (i32.const 2) + ) + ) + (local.get $12) + ) + (local.set $13 + (i32.load offset=4 + (local.tee $12 + (i32.add + (local.get $3) + (i32.shl + (local.get $17) + (i32.const 3) + ) + ) + ) + ) + ) + (i32.store + (local.tee $8 + (local.get $19) + ) + (i32.load + (local.get $12) + ) + ) + (i32.store offset=4 + (local.get $8) + (local.get $13) + ) + (br $__rjti$2) + ) + ) + (if + (i32.eqz + (local.get $29) + ) + (block + (local.set $16 + (i32.const 0) + ) + (br $label$break$L1) + ) + ) + (call $_pop_arg_336 + (local.get $19) + (local.get $12) + (local.get $2) + ) + ) + ) + (br $__rjto$2) + ) + (if + (i32.eqz + (local.get $29) + ) + (block + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + ) + ) + (local.set $11 + (select + (local.tee $8 + (i32.and + (local.get $11) + (i32.const -65537) + ) + ) + (local.get $11) + (i32.and + (local.get $11) + (i32.const 8192) + ) + ) + ) + (local.set $5 + (block $__rjto$8 (result i32) + (block $__rjti$8 + (block $__rjti$7 + (block $__rjti$6 + (block $__rjti$5 + (block $__rjti$4 + (block $__rjti$3 + (block $switch-default120 + (block $switch-case42 + (block $switch-case41 + (block $switch-case40 + (block $switch-case39 + (block $switch-case38 + (block $switch-case37 + (block $switch-case36 + (block $switch-case34 + (block $switch-case33 + (block $switch-case29 + (block $switch-case28 + (block $switch-case27 + (br_table $switch-case42 $switch-default120 $switch-case40 $switch-default120 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case41 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case29 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-default120 $switch-case42 $switch-default120 $switch-case37 $switch-case34 $switch-case42 $switch-case42 $switch-case42 $switch-default120 $switch-case34 $switch-default120 $switch-default120 $switch-default120 $switch-case38 $switch-case27 $switch-case33 $switch-case28 $switch-default120 $switch-default120 $switch-case39 $switch-default120 $switch-case36 $switch-default120 $switch-default120 $switch-case29 $switch-default120 + (i32.sub + (local.tee $18 + (select + (i32.and + (local.tee $12 + (i32.load8_s + (local.get $18) + ) + ) + (i32.const -33) + ) + (local.get $12) + (i32.and + (i32.ne + (local.get $9) + (i32.const 0) + ) + (i32.eq + (i32.and + (local.get $12) + (i32.const 15) + ) + (i32.const 3) + ) + ) + ) + ) + (i32.const 65) + ) + ) + ) + (block $switch-default26 + (block $switch-case25 + (block $switch-case24 + (block $switch-case23 + (block $switch-case22 + (block $switch-case21 + (block $switch-case20 + (block $switch-case19 + (br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26 + (local.get $9) + ) + ) + (i32.store + (i32.load + (local.get $19) + ) + (local.get $16) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (i32.load + (local.get $19) + ) + (local.get $16) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (local.tee $5 + (i32.load + (local.get $19) + ) + ) + (local.get $16) + ) + (i32.store offset=4 + (local.get $5) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $16) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store16 + (i32.load + (local.get $19) + ) + (local.get $16) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store8 + (i32.load + (local.get $19) + ) + (local.get $16) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (i32.load + (local.get $19) + ) + (local.get $16) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (i32.store + (local.tee $5 + (i32.load + (local.get $19) + ) + ) + (local.get $16) + ) + (i32.store offset=4 + (local.get $5) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $16) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (local.set $7 + (i32.or + (local.get $11) + (i32.const 8) + ) + ) + (local.set $6 + (select + (local.get $6) + (i32.const 8) + (i32.gt_u + (local.get $6) + (i32.const 8) + ) + ) + ) + (local.set $18 + (i32.const 120) + ) + (br $__rjti$3) + ) + (local.set $7 + (local.get $11) + ) + (br $__rjti$3) + ) + (if + (i32.and + (i32.eqz + (local.tee $7 + (i32.load + (local.tee $5 + (local.get $19) + ) + ) + ) + ) + (i32.eqz + (local.tee $8 + (i32.load offset=4 + (local.get $5) + ) + ) + ) + ) + (local.set $8 + (local.get $26) + ) + (block + (local.set $5 + (local.get $7) + ) + (local.set $7 + (local.get $8) + ) + (local.set $8 + (local.get $26) + ) + (loop $while-in32 + (i32.store8 + (local.tee $8 + (i32.add + (local.get $8) + (i32.const -1) + ) + ) + (i32.or + (i32.and + (local.get $5) + (i32.const 7) + ) + (i32.const 48) + ) + ) + (br_if $while-in32 + (i32.eqz + (i32.and + (i32.eqz + (local.tee $5 + (call $_bitshift64Lshr + (local.get $5) + (local.get $7) + (i32.const 3) + ) + ) + ) + (i32.eqz + (local.tee $7 + (global.get $tempRet0) + ) + ) + ) + ) + ) + ) + ) + ) + (local.set $5 + (if (result i32) + (i32.and + (local.get $11) + (i32.const 8) + ) + (block (result i32) + (local.set $7 + (local.get $11) + ) + (local.set $6 + (select + (local.tee $11 + (i32.add + (i32.sub + (local.get $39) + (local.get $8) + ) + (i32.const 1) + ) + ) + (local.get $6) + (i32.lt_s + (local.get $6) + (local.get $11) + ) + ) + ) + (local.get $8) + ) + (block (result i32) + (local.set $7 + (local.get $11) + ) + (local.get $8) + ) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$8) + ) + (local.set $5 + (i32.load + (local.tee $7 + (local.get $19) + ) + ) + ) + (if + (i32.lt_s + (local.tee $7 + (i32.load offset=4 + (local.get $7) + ) + ) + (i32.const 0) + ) + (block + (i32.store + (local.tee $8 + (local.get $19) + ) + (local.tee $5 + (call $_i64Subtract + (i32.const 0) + (i32.const 0) + (local.get $5) + (local.get $7) + ) + ) + ) + (i32.store offset=4 + (local.get $8) + (local.tee $7 + (global.get $tempRet0) + ) + ) + (local.set $8 + (i32.const 1) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$4) + ) + ) + (local.set $9 + (if (result i32) + (i32.and + (local.get $11) + (i32.const 2048) + ) + (block (result i32) + (local.set $8 + (i32.const 1) + ) + (i32.const 4092) + ) + (block (result i32) + (local.set $8 + (local.tee $9 + (i32.and + (local.get $11) + (i32.const 1) + ) + ) + ) + (select + (i32.const 4093) + (i32.const 4091) + (local.get $9) + ) + ) + ) + ) + (br $__rjti$4) + ) + (local.set $5 + (i32.load + (local.tee $7 + (local.get $19) + ) + ) + ) + (local.set $7 + (i32.load offset=4 + (local.get $7) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$4) + ) + (drop + (i32.load offset=4 + (local.tee $5 + (local.get $19) + ) + ) + ) + (i32.store8 + (local.get $40) + (i32.load + (local.get $5) + ) + ) + (local.set $7 + (local.get $40) + ) + (local.set $11 + (local.get $8) + ) + (local.set $12 + (i32.const 1) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjto$8 + (local.get $26) + ) + ) + (local.set $5 + (call $_strerror + (i32.load + (call $___errno_location) + ) + ) + ) + (br $__rjti$5) + ) + (local.set $5 + (select + (local.tee $5 + (i32.load + (local.get $19) + ) + ) + (i32.const 4101) + (local.get $5) + ) + ) + (br $__rjti$5) + ) + (drop + (i32.load offset=4 + (local.tee $5 + (local.get $19) + ) + ) + ) + (i32.store + (local.get $41) + (i32.load + (local.get $5) + ) + ) + (i32.store + (local.get $44) + (i32.const 0) + ) + (i32.store + (local.get $19) + (local.get $41) + ) + (local.set $8 + (i32.const -1) + ) + (br $__rjti$6) + ) + (if + (local.get $6) + (block + (local.set $8 + (local.get $6) + ) + (br $__rjti$6) + ) + (block + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (i32.const 0) + (local.get $11) + ) + (local.set $7 + (i32.const 0) + ) + (br $__rjti$7) + ) + ) + ) + (local.set $15 + (f64.load + (local.get $19) + ) + ) + (i32.store + (local.get $20) + (i32.const 0) + ) + (f64.store + (global.get $tempDoublePtr) + (local.get $15) + ) + (drop + (i32.load + (global.get $tempDoublePtr) + ) + ) + (local.set $31 + (if (result i32) + (i32.lt_s + (i32.load offset=4 + (global.get $tempDoublePtr) + ) + (i32.const 0) + ) + (block (result i32) + (local.set $27 + (i32.const 1) + ) + (local.set $15 + (f64.neg + (local.get $15) + ) + ) + (i32.const 4108) + ) + (if (result i32) + (i32.and + (local.get $11) + (i32.const 2048) + ) + (block (result i32) + (local.set $27 + (i32.const 1) + ) + (i32.const 4111) + ) + (block (result i32) + (local.set $27 + (local.tee $5 + (i32.and + (local.get $11) + (i32.const 1) + ) + ) + ) + (select + (i32.const 4114) + (i32.const 4109) + (local.get $5) + ) + ) + ) + ) + ) + (f64.store + (global.get $tempDoublePtr) + (local.get $15) + ) + (drop + (i32.load + (global.get $tempDoublePtr) + ) + ) + (local.set $7 + (block $do-once49 (result i32) + (if (result i32) + (i32.or + (i32.lt_u + (local.tee $5 + (i32.and + (i32.load offset=4 + (global.get $tempDoublePtr) + ) + (i32.const 2146435072) + ) + ) + (i32.const 2146435072) + ) + (i32.and + (i32.eq + (local.get $5) + (i32.const 2146435072) + ) + (i32.const 0) + ) + ) + (block (result i32) + (if + (local.tee $5 + (f64.ne + (local.tee $23 + (f64.mul + (call $_frexp + (local.get $15) + (local.tee $5 + (local.get $20) + ) + ) + (f64.const 2) + ) + ) + (f64.const 0) + ) + ) + (i32.store + (local.get $20) + (i32.add + (i32.load + (local.get $20) + ) + (i32.const -1) + ) + ) + ) + (if + (i32.eq + (local.tee $24 + (i32.or + (local.get $18) + (i32.const 32) + ) + ) + (i32.const 97) + ) + (block + (local.set $9 + (select + (i32.add + (local.get $31) + (i32.const 9) + ) + (local.get $31) + (local.tee $13 + (i32.and + (local.get $18) + (i32.const 32) + ) + ) + ) + ) + (local.set $15 + (if (result f64) + (i32.or + (i32.gt_u + (local.get $6) + (i32.const 11) + ) + (i32.eqz + (local.tee $5 + (i32.sub + (i32.const 12) + (local.get $6) + ) + ) + ) + ) + (local.get $23) + (block (result f64) + (local.set $15 + (f64.const 8) + ) + (loop $while-in54 + (local.set $15 + (f64.mul + (local.get $15) + (f64.const 16) + ) + ) + (br_if $while-in54 + (local.tee $5 + (i32.add + (local.get $5) + (i32.const -1) + ) + ) + ) + ) + (if (result f64) + (i32.eq + (i32.load8_s + (local.get $9) + ) + (i32.const 45) + ) + (f64.neg + (f64.add + (local.get $15) + (f64.sub + (f64.neg + (local.get $23) + ) + (local.get $15) + ) + ) + ) + (f64.sub + (f64.add + (local.get $23) + (local.get $15) + ) + (local.get $15) + ) + ) + ) + ) + ) + (if + (i32.eq + (local.tee $5 + (call $_fmt_u + (local.tee $5 + (select + (i32.sub + (i32.const 0) + (local.tee $7 + (i32.load + (local.get $20) + ) + ) + ) + (local.get $7) + (i32.lt_s + (local.get $7) + (i32.const 0) + ) + ) + ) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + (local.get $34) + ) + ) + (local.get $34) + ) + (block + (i32.store8 + (local.get $42) + (i32.const 48) + ) + (local.set $5 + (local.get $42) + ) + ) + ) + (local.set $12 + (i32.or + (local.get $27) + (i32.const 2) + ) + ) + (i32.store8 + (i32.add + (local.get $5) + (i32.const -1) + ) + (i32.add + (i32.and + (i32.shr_s + (local.get $7) + (i32.const 31) + ) + (i32.const 2) + ) + (i32.const 43) + ) + ) + (i32.store8 + (local.tee $8 + (i32.add + (local.get $5) + (i32.const -2) + ) + ) + (i32.add + (local.get $18) + (i32.const 15) + ) + ) + (local.set $18 + (i32.lt_s + (local.get $6) + (i32.const 1) + ) + ) + (local.set $17 + (i32.eqz + (i32.and + (local.get $11) + (i32.const 8) + ) + ) + ) + (local.set $5 + (local.get $22) + ) + (loop $while-in56 + (i32.store8 + (local.get $5) + (i32.or + (i32.load8_u + (i32.add + (local.tee $7 + (call $f64-to-int + (local.get $15) + ) + ) + (i32.const 4075) + ) + ) + (local.get $13) + ) + ) + (local.set $15 + (f64.mul + (f64.sub + (local.get $15) + (f64.convert_i32_s + (local.get $7) + ) + ) + (f64.const 16) + ) + ) + (local.set $5 + (block $do-once57 (result i32) + (if (result i32) + (i32.eq + (i32.sub + (local.tee $7 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (local.get $37) + ) + (i32.const 1) + ) + (block (result i32) + (drop + (br_if $do-once57 + (local.get $7) + (i32.and + (local.get $17) + (i32.and + (local.get $18) + (f64.eq + (local.get $15) + (f64.const 0) + ) + ) + ) + ) + ) + (i32.store8 + (local.get $7) + (i32.const 46) + ) + (i32.add + (local.get $5) + (i32.const 2) + ) + ) + (local.get $7) + ) + ) + ) + (br_if $while-in56 + (f64.ne + (local.get $15) + (f64.const 0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.tee $7 + (i32.add + (local.tee $6 + (select + (i32.sub + (i32.add + (local.get $47) + (local.get $6) + ) + (local.get $8) + ) + (i32.add + (i32.sub + (local.get $45) + (local.get $8) + ) + (local.get $5) + ) + (i32.and + (i32.ne + (local.get $6) + (i32.const 0) + ) + (i32.lt_s + (i32.add + (local.get $46) + (local.get $5) + ) + (local.get $6) + ) + ) + ) + ) + (local.get $12) + ) + ) + (local.get $11) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $9) + (local.get $12) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $14) + (local.get $7) + (i32.xor + (local.get $11) + (i32.const 65536) + ) + ) + (local.set $5 + (i32.sub + (local.get $5) + (local.get $37) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $22) + (local.get $5) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (i32.sub + (local.get $6) + (i32.add + (local.get $5) + (local.tee $5 + (i32.sub + (local.get $28) + (local.get $8) + ) + ) + ) + ) + (i32.const 0) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $8) + (local.get $5) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.get $7) + (i32.xor + (local.get $11) + (i32.const 8192) + ) + ) + (br $do-once49 + (select + (local.get $14) + (local.get $7) + (i32.lt_s + (local.get $7) + (local.get $14) + ) + ) + ) + ) + ) + (local.set $15 + (if (result f64) + (local.get $5) + (block (result f64) + (i32.store + (local.get $20) + (local.tee $5 + (i32.add + (i32.load + (local.get $20) + ) + (i32.const -28) + ) + ) + ) + (f64.mul + (local.get $23) + (f64.const 268435456) + ) + ) + (block (result f64) + (local.set $5 + (i32.load + (local.get $20) + ) + ) + (local.get $23) + ) + ) + ) + (local.set $7 + (local.tee $8 + (select + (local.get $48) + (local.get $49) + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + ) + ) + ) + (loop $while-in60 + (i32.store + (local.get $7) + (local.tee $5 + (call $f64-to-int + (local.get $15) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (br_if $while-in60 + (f64.ne + (local.tee $15 + (f64.mul + (f64.sub + (local.get $15) + (f64.convert_i32_u + (local.get $5) + ) + ) + (f64.const 1e9) + ) + ) + (f64.const 0) + ) + ) + ) + (if + (i32.gt_s + (local.tee $9 + (i32.load + (local.get $20) + ) + ) + (i32.const 0) + ) + (block + (local.set $5 + (local.get $8) + ) + (loop $while-in62 + (local.set $13 + (select + (i32.const 29) + (local.get $9) + (i32.gt_s + (local.get $9) + (i32.const 29) + ) + ) + ) + (block $do-once63 + (if + (i32.ge_u + (local.tee $9 + (i32.add + (local.get $7) + (i32.const -4) + ) + ) + (local.get $5) + ) + (block + (local.set $12 + (i32.const 0) + ) + (loop $while-in66 + (i32.store + (local.get $9) + (call $___uremdi3 + (local.tee $12 + (call $_i64Add + (call $_bitshift64Shl + (i32.load + (local.get $9) + ) + (i32.const 0) + (local.get $13) + ) + (global.get $tempRet0) + (local.get $12) + (i32.const 0) + ) + ) + (local.tee $17 + (global.get $tempRet0) + ) + (i32.const 1000000000) + (i32.const 0) + ) + ) + (local.set $12 + (call $___udivdi3 + (local.get $12) + (local.get $17) + (i32.const 1000000000) + (i32.const 0) + ) + ) + (br_if $while-in66 + (i32.ge_u + (local.tee $9 + (i32.add + (local.get $9) + (i32.const -4) + ) + ) + (local.get $5) + ) + ) + ) + (br_if $do-once63 + (i32.eqz + (local.get $12) + ) + ) + (i32.store + (local.tee $5 + (i32.add + (local.get $5) + (i32.const -4) + ) + ) + (local.get $12) + ) + ) + ) + ) + (loop $while-in68 + (if + (i32.gt_u + (local.get $7) + (local.get $5) + ) + (if + (i32.eqz + (i32.load + (local.tee $9 + (i32.add + (local.get $7) + (i32.const -4) + ) + ) + ) + ) + (block + (local.set $7 + (local.get $9) + ) + (br $while-in68) + ) + ) + ) + ) + (i32.store + (local.get $20) + (local.tee $9 + (i32.sub + (i32.load + (local.get $20) + ) + (local.get $13) + ) + ) + ) + (br_if $while-in62 + (i32.gt_s + (local.get $9) + (i32.const 0) + ) + ) + ) + ) + (local.set $5 + (local.get $8) + ) + ) + (local.set $17 + (select + (i32.const 6) + (local.get $6) + (i32.lt_s + (local.get $6) + (i32.const 0) + ) + ) + ) + (if + (i32.lt_s + (local.get $9) + (i32.const 0) + ) + (block + (local.set $21 + (i32.add + (call $i32s-div + (i32.add + (local.get $17) + (i32.const 25) + ) + (i32.const 9) + ) + (i32.const 1) + ) + ) + (local.set $32 + (i32.eq + (local.get $24) + (i32.const 102) + ) + ) + (local.set $6 + (local.get $5) + ) + (local.set $5 + (local.get $7) + ) + (loop $while-in70 + (local.set $13 + (select + (i32.const 9) + (local.tee $7 + (i32.sub + (i32.const 0) + (local.get $9) + ) + ) + (i32.gt_s + (local.get $7) + (i32.const 9) + ) + ) + ) + (block $do-once71 + (if + (i32.lt_u + (local.get $6) + (local.get $5) + ) + (block + (local.set $12 + (i32.add + (i32.shl + (i32.const 1) + (local.get $13) + ) + (i32.const -1) + ) + ) + (local.set $38 + (i32.shr_u + (i32.const 1000000000) + (local.get $13) + ) + ) + (local.set $9 + (i32.const 0) + ) + (local.set $7 + (local.get $6) + ) + (loop $while-in74 + (i32.store + (local.get $7) + (i32.add + (i32.shr_u + (local.tee $33 + (i32.load + (local.get $7) + ) + ) + (local.get $13) + ) + (local.get $9) + ) + ) + (local.set $9 + (i32.mul + (i32.and + (local.get $33) + (local.get $12) + ) + (local.get $38) + ) + ) + (br_if $while-in74 + (i32.lt_u + (local.tee $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (local.get $5) + ) + ) + ) + (local.set $7 + (select + (local.get $6) + (i32.add + (local.get $6) + (i32.const 4) + ) + (i32.load + (local.get $6) + ) + ) + ) + (br_if $do-once71 + (i32.eqz + (local.get $9) + ) + ) + (i32.store + (local.get $5) + (local.get $9) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 4) + ) + ) + ) + (local.set $7 + (select + (local.get $6) + (i32.add + (local.get $6) + (i32.const 4) + ) + (i32.load + (local.get $6) + ) + ) + ) + ) + ) + (local.set $12 + (select + (i32.add + (local.tee $6 + (select + (local.get $8) + (local.get $7) + (local.get $32) + ) + ) + (i32.shl + (local.get $21) + (i32.const 2) + ) + ) + (local.get $5) + (i32.gt_s + (i32.shr_s + (i32.sub + (local.get $5) + (local.get $6) + ) + (i32.const 2) + ) + (local.get $21) + ) + ) + ) + (i32.store + (local.get $20) + (local.tee $9 + (i32.add + (i32.load + (local.get $20) + ) + (local.get $13) + ) + ) + ) + (if + (i32.lt_s + (local.get $9) + (i32.const 0) + ) + (block + (local.set $6 + (local.get $7) + ) + (local.set $5 + (local.get $12) + ) + (br $while-in70) + ) + (block + (local.set $5 + (local.get $7) + ) + (local.set $9 + (local.get $12) + ) + ) + ) + ) + ) + (local.set $9 + (local.get $7) + ) + ) + (local.set $21 + (local.get $8) + ) + (block $do-once75 + (if + (i32.lt_u + (local.get $5) + (local.get $9) + ) + (block + (local.set $7 + (i32.mul + (i32.shr_s + (i32.sub + (local.get $21) + (local.get $5) + ) + (i32.const 2) + ) + (i32.const 9) + ) + ) + (br_if $do-once75 + (i32.lt_u + (local.tee $12 + (i32.load + (local.get $5) + ) + ) + (i32.const 10) + ) + ) + (local.set $6 + (i32.const 10) + ) + (loop $while-in78 + (local.set $7 + (i32.add + (local.get $7) + (i32.const 1) + ) + ) + (br_if $while-in78 + (i32.ge_u + (local.get $12) + (local.tee $6 + (i32.mul + (local.get $6) + (i32.const 10) + ) + ) + ) + ) + ) + ) + (local.set $7 + (i32.const 0) + ) + ) + ) + (local.set $5 + (if (result i32) + (i32.lt_s + (local.tee $6 + (i32.add + (i32.sub + (local.get $17) + (select + (local.get $7) + (i32.const 0) + (i32.ne + (local.get $24) + (i32.const 102) + ) + ) + ) + (i32.shr_s + (i32.shl + (i32.and + (local.tee $32 + (i32.ne + (local.get $17) + (i32.const 0) + ) + ) + (local.tee $38 + (i32.eq + (local.get $24) + (i32.const 103) + ) + ) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + ) + (i32.add + (i32.mul + (i32.shr_s + (i32.sub + (local.get $9) + (local.get $21) + ) + (i32.const 2) + ) + (i32.const 9) + ) + (i32.const -9) + ) + ) + (block (result i32) + (local.set $13 + (call $i32s-div + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 9216) + ) + ) + (i32.const 9) + ) + ) + (if + (i32.lt_s + (local.tee $6 + (i32.add + (if (result i32) + (local.tee $12 + (i32.const 9) + ) + (i32.rem_s + (local.get $6) + (local.get $12) + ) + (i32.const 0) + ) + (i32.const 1) + ) + ) + (i32.const 9) + ) + (block + (local.set $12 + (i32.const 10) + ) + (loop $while-in80 + (local.set $12 + (i32.mul + (local.get $12) + (i32.const 10) + ) + ) + (br_if $while-in80 + (i32.ne + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 1) + ) + ) + (i32.const 9) + ) + ) + ) + ) + (local.set $12 + (i32.const 10) + ) + ) + (local.set $13 + (call $i32u-rem + (local.tee $24 + (i32.load + (local.tee $6 + (i32.add + (i32.add + (local.get $8) + (i32.shl + (local.get $13) + (i32.const 2) + ) + ) + (i32.const -4092) + ) + ) + ) + ) + (local.get $12) + ) + ) + (block $do-once81 + (if + (i32.eqz + (i32.and + (local.tee $33 + (i32.eq + (i32.add + (local.get $6) + (i32.const 4) + ) + (local.get $9) + ) + ) + (i32.eqz + (local.get $13) + ) + ) + ) + (block + (local.set $50 + (call $i32u-div + (local.get $24) + (local.get $12) + ) + ) + (local.set $15 + (if (result f64) + (i32.lt_u + (local.get $13) + (local.tee $51 + (call $i32s-div + (local.get $12) + (i32.const 2) + ) + ) + ) + (f64.const 0.5) + (select + (f64.const 1) + (f64.const 1.5) + (i32.and + (local.get $33) + (i32.eq + (local.get $13) + (local.get $51) + ) + ) + ) + ) + ) + (local.set $23 + (select + (f64.const 9007199254740994) + (f64.const 9007199254740992) + (i32.and + (local.get $50) + (i32.const 1) + ) + ) + ) + (block $do-once83 + (if + (local.get $27) + (block + (br_if $do-once83 + (i32.ne + (i32.load8_s + (local.get $31) + ) + (i32.const 45) + ) + ) + (local.set $23 + (f64.neg + (local.get $23) + ) + ) + (local.set $15 + (f64.neg + (local.get $15) + ) + ) + ) + ) + ) + (i32.store + (local.get $6) + (local.tee $13 + (i32.sub + (local.get $24) + (local.get $13) + ) + ) + ) + (br_if $do-once81 + (f64.eq + (f64.add + (local.get $23) + (local.get $15) + ) + (local.get $23) + ) + ) + (i32.store + (local.get $6) + (local.tee $7 + (i32.add + (local.get $13) + (local.get $12) + ) + ) + ) + (if + (i32.gt_u + (local.get $7) + (i32.const 999999999) + ) + (loop $while-in86 + (i32.store + (local.get $6) + (i32.const 0) + ) + (if + (i32.lt_u + (local.tee $6 + (i32.add + (local.get $6) + (i32.const -4) + ) + ) + (local.get $5) + ) + (i32.store + (local.tee $5 + (i32.add + (local.get $5) + (i32.const -4) + ) + ) + (i32.const 0) + ) + ) + (i32.store + (local.get $6) + (local.tee $7 + (i32.add + (i32.load + (local.get $6) + ) + (i32.const 1) + ) + ) + ) + (br_if $while-in86 + (i32.gt_u + (local.get $7) + (i32.const 999999999) + ) + ) + ) + ) + (local.set $7 + (i32.mul + (i32.shr_s + (i32.sub + (local.get $21) + (local.get $5) + ) + (i32.const 2) + ) + (i32.const 9) + ) + ) + (br_if $do-once81 + (i32.lt_u + (local.tee $13 + (i32.load + (local.get $5) + ) + ) + (i32.const 10) + ) + ) + (local.set $12 + (i32.const 10) + ) + (loop $while-in88 + (local.set $7 + (i32.add + (local.get $7) + (i32.const 1) + ) + ) + (br_if $while-in88 + (i32.ge_u + (local.get $13) + (local.tee $12 + (i32.mul + (local.get $12) + (i32.const 10) + ) + ) + ) + ) + ) + ) + ) + ) + (local.set $12 + (local.get $5) + ) + (local.set $13 + (local.get $7) + ) + (select + (local.tee $5 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (local.get $9) + (i32.gt_u + (local.get $9) + (local.get $5) + ) + ) + ) + (block (result i32) + (local.set $12 + (local.get $5) + ) + (local.set $13 + (local.get $7) + ) + (local.get $9) + ) + ) + ) + (local.set $33 + (i32.sub + (i32.const 0) + (local.get $13) + ) + ) + (loop $while-in90 + (block $while-out89 + (if + (i32.le_u + (local.get $5) + (local.get $12) + ) + (block + (local.set $24 + (i32.const 0) + ) + (local.set $9 + (local.get $5) + ) + (br $while-out89) + ) + ) + (if + (i32.load + (local.tee $7 + (i32.add + (local.get $5) + (i32.const -4) + ) + ) + ) + (block + (local.set $24 + (i32.const 1) + ) + (local.set $9 + (local.get $5) + ) + ) + (block + (local.set $5 + (local.get $7) + ) + (br $while-in90) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.tee $13 + (i32.add + (i32.add + (i32.add + (i32.add + (local.get $27) + (i32.const 1) + ) + (local.tee $5 + (block $do-once91 (result i32) + (if (result i32) + (local.get $38) + (block (result i32) + (local.set $7 + (if (result i32) + (i32.and + (i32.gt_s + (local.tee $5 + (i32.add + (i32.xor + (local.get $32) + (i32.const 1) + ) + (local.get $17) + ) + ) + (local.get $13) + ) + (i32.gt_s + (local.get $13) + (i32.const -5) + ) + ) + (block (result i32) + (local.set $17 + (i32.sub + (i32.add + (local.get $5) + (i32.const -1) + ) + (local.get $13) + ) + ) + (i32.add + (local.get $18) + (i32.const -1) + ) + ) + (block (result i32) + (local.set $17 + (i32.add + (local.get $5) + (i32.const -1) + ) + ) + (i32.add + (local.get $18) + (i32.const -2) + ) + ) + ) + ) + (if + (local.tee $5 + (i32.and + (local.get $11) + (i32.const 8) + ) + ) + (block + (local.set $21 + (local.get $5) + ) + (br $do-once91 + (local.get $17) + ) + ) + ) + (block $do-once93 + (if + (local.get $24) + (block + (if + (i32.eqz + (local.tee $18 + (i32.load + (i32.add + (local.get $9) + (i32.const -4) + ) + ) + ) + ) + (block + (local.set $5 + (i32.const 9) + ) + (br $do-once93) + ) + ) + (if + (call $i32u-rem + (local.get $18) + (i32.const 10) + ) + (block + (local.set $5 + (i32.const 0) + ) + (br $do-once93) + ) + (block + (local.set $6 + (i32.const 10) + ) + (local.set $5 + (i32.const 0) + ) + ) + ) + (loop $while-in96 + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br_if $while-in96 + (i32.eqz + (call $i32u-rem + (local.get $18) + (local.tee $6 + (i32.mul + (local.get $6) + (i32.const 10) + ) + ) + ) + ) + ) + ) + ) + (local.set $5 + (i32.const 9) + ) + ) + ) + (local.set $6 + (i32.add + (i32.mul + (i32.shr_s + (i32.sub + (local.get $9) + (local.get $21) + ) + (i32.const 2) + ) + (i32.const 9) + ) + (i32.const -9) + ) + ) + (if (result i32) + (i32.eq + (i32.or + (local.get $7) + (i32.const 32) + ) + (i32.const 102) + ) + (block (result i32) + (local.set $21 + (i32.const 0) + ) + (select + (local.get $17) + (local.tee $5 + (select + (i32.const 0) + (local.tee $5 + (i32.sub + (local.get $6) + (local.get $5) + ) + ) + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + ) + ) + (i32.lt_s + (local.get $17) + (local.get $5) + ) + ) + ) + (block (result i32) + (local.set $21 + (i32.const 0) + ) + (select + (local.get $17) + (local.tee $5 + (select + (i32.const 0) + (local.tee $5 + (i32.sub + (i32.add + (local.get $6) + (local.get $13) + ) + (local.get $5) + ) + ) + (i32.lt_s + (local.get $5) + (i32.const 0) + ) + ) + ) + (i32.lt_s + (local.get $17) + (local.get $5) + ) + ) + ) + ) + ) + (block (result i32) + (local.set $21 + (i32.and + (local.get $11) + (i32.const 8) + ) + ) + (local.set $7 + (local.get $18) + ) + (local.get $17) + ) + ) + ) + ) + ) + (i32.ne + (local.tee $32 + (i32.or + (local.get $5) + (local.get $21) + ) + ) + (i32.const 0) + ) + ) + (if (result i32) + (local.tee $17 + (i32.eq + (i32.or + (local.get $7) + (i32.const 32) + ) + (i32.const 102) + ) + ) + (block (result i32) + (local.set $18 + (i32.const 0) + ) + (select + (local.get $13) + (i32.const 0) + (i32.gt_s + (local.get $13) + (i32.const 0) + ) + ) + ) + (block (result i32) + (if + (i32.lt_s + (i32.sub + (local.get $28) + (local.tee $6 + (call $_fmt_u + (local.tee $6 + (select + (local.get $33) + (local.get $13) + (i32.lt_s + (local.get $13) + (i32.const 0) + ) + ) + ) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $6) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + (local.get $34) + ) + ) + ) + (i32.const 2) + ) + (loop $while-in98 + (i32.store8 + (local.tee $6 + (i32.add + (local.get $6) + (i32.const -1) + ) + ) + (i32.const 48) + ) + (br_if $while-in98 + (i32.lt_s + (i32.sub + (local.get $28) + (local.get $6) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.store8 + (i32.add + (local.get $6) + (i32.const -1) + ) + (i32.add + (i32.and + (i32.shr_s + (local.get $13) + (i32.const 31) + ) + (i32.const 2) + ) + (i32.const 43) + ) + ) + (i32.store8 + (local.tee $6 + (i32.add + (local.get $6) + (i32.const -2) + ) + ) + (local.get $7) + ) + (local.set $18 + (local.get $6) + ) + (i32.sub + (local.get $28) + (local.get $6) + ) + ) + ) + ) + ) + (local.get $11) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $31) + (local.get $27) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $14) + (local.get $13) + (i32.xor + (local.get $11) + (i32.const 65536) + ) + ) + (block $do-once99 + (if + (local.get $17) + (block + (local.set $6 + (local.tee $12 + (select + (local.get $8) + (local.get $12) + (i32.gt_u + (local.get $12) + (local.get $8) + ) + ) + ) + ) + (loop $while-in102 + (local.set $7 + (call $_fmt_u + (i32.load + (local.get $6) + ) + (i32.const 0) + (local.get $30) + ) + ) + (block $do-once103 + (if + (i32.eq + (local.get $6) + (local.get $12) + ) + (block + (br_if $do-once103 + (i32.ne + (local.get $7) + (local.get $30) + ) + ) + (i32.store8 + (local.get $35) + (i32.const 48) + ) + (local.set $7 + (local.get $35) + ) + ) + (block + (br_if $do-once103 + (i32.le_u + (local.get $7) + (local.get $22) + ) + ) + (loop $while-in106 + (i32.store8 + (local.tee $7 + (i32.add + (local.get $7) + (i32.const -1) + ) + ) + (i32.const 48) + ) + (br_if $while-in106 + (i32.gt_u + (local.get $7) + (local.get $22) + ) + ) + ) + ) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $7) + (i32.sub + (local.get $43) + (local.get $7) + ) + (local.get $0) + ) + ) + ) + (if + (i32.le_u + (local.tee $7 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (local.get $8) + ) + (block + (local.set $6 + (local.get $7) + ) + (br $while-in102) + ) + ) + ) + (block $do-once107 + (if + (local.get $32) + (block + (br_if $do-once107 + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (i32.const 4143) + (i32.const 1) + (local.get $0) + ) + ) + ) + ) + ) + (if + (i32.and + (i32.gt_s + (local.get $5) + (i32.const 0) + ) + (i32.lt_u + (local.get $7) + (local.get $9) + ) + ) + (loop $while-in110 + (if + (i32.gt_u + (local.tee $6 + (call $_fmt_u + (i32.load + (local.get $7) + ) + (i32.const 0) + (local.get $30) + ) + ) + (local.get $22) + ) + (loop $while-in112 + (i32.store8 + (local.tee $6 + (i32.add + (local.get $6) + (i32.const -1) + ) + ) + (i32.const 48) + ) + (br_if $while-in112 + (i32.gt_u + (local.get $6) + (local.get $22) + ) + ) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $6) + (select + (i32.const 9) + (local.get $5) + (i32.gt_s + (local.get $5) + (i32.const 9) + ) + ) + (local.get $0) + ) + ) + ) + (local.set $6 + (i32.add + (local.get $5) + (i32.const -9) + ) + ) + (if + (i32.and + (i32.gt_s + (local.get $5) + (i32.const 9) + ) + (i32.lt_u + (local.tee $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (local.get $9) + ) + ) + (block + (local.set $5 + (local.get $6) + ) + (br $while-in110) + ) + (local.set $5 + (local.get $6) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (i32.add + (local.get $5) + (i32.const 9) + ) + (i32.const 9) + (i32.const 0) + ) + ) + (block + (local.set $9 + (select + (local.get $9) + (i32.add + (local.get $12) + (i32.const 4) + ) + (local.get $24) + ) + ) + (if + (i32.gt_s + (local.get $5) + (i32.const -1) + ) + (block + (local.set $17 + (i32.eqz + (local.get $21) + ) + ) + (local.set $6 + (local.get $12) + ) + (local.set $7 + (local.get $5) + ) + (loop $while-in114 + (if + (i32.eq + (local.tee $5 + (call $_fmt_u + (i32.load + (local.get $6) + ) + (i32.const 0) + (local.get $30) + ) + ) + (local.get $30) + ) + (block + (i32.store8 + (local.get $35) + (i32.const 48) + ) + (local.set $5 + (local.get $35) + ) + ) + ) + (block $do-once115 + (if + (i32.eq + (local.get $6) + (local.get $12) + ) + (block + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $5) + (i32.const 1) + (local.get $0) + ) + ) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br_if $do-once115 + (i32.and + (local.get $17) + (i32.lt_s + (local.get $7) + (i32.const 1) + ) + ) + ) + (br_if $do-once115 + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (i32.const 4143) + (i32.const 1) + (local.get $0) + ) + ) + ) + (block + (br_if $do-once115 + (i32.le_u + (local.get $5) + (local.get $22) + ) + ) + (loop $while-in118 + (i32.store8 + (local.tee $5 + (i32.add + (local.get $5) + (i32.const -1) + ) + ) + (i32.const 48) + ) + (br_if $while-in118 + (i32.gt_u + (local.get $5) + (local.get $22) + ) + ) + ) + ) + ) + ) + (local.set $8 + (i32.sub + (local.get $43) + (local.get $5) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $5) + (select + (local.get $8) + (local.get $7) + (i32.gt_s + (local.get $7) + (local.get $8) + ) + ) + (local.get $0) + ) + ) + ) + (br_if $while-in114 + (i32.and + (i32.lt_u + (local.tee $6 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (local.get $9) + ) + (i32.gt_s + (local.tee $7 + (i32.sub + (local.get $7) + (local.get $8) + ) + ) + (i32.const -1) + ) + ) + ) + (local.set $5 + (local.get $7) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (i32.add + (local.get $5) + (i32.const 18) + ) + (i32.const 18) + (i32.const 0) + ) + (br_if $do-once99 + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $18) + (i32.sub + (local.get $28) + (local.get $18) + ) + (local.get $0) + ) + ) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.get $13) + (i32.xor + (local.get $11) + (i32.const 8192) + ) + ) + (select + (local.get $14) + (local.get $13) + (i32.lt_s + (local.get $13) + (local.get $14) + ) + ) + ) + (block (result i32) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.tee $7 + (i32.add + (local.tee $9 + (select + (i32.const 0) + (local.get $27) + (local.tee $6 + (i32.or + (f64.ne + (local.get $15) + (local.get $15) + ) + (i32.const 0) + ) + ) + ) + ) + (i32.const 3) + ) + ) + (local.get $8) + ) + (if + (i32.eqz + (i32.and + (local.tee $5 + (i32.load + (local.get $0) + ) + ) + (i32.const 32) + ) + ) + (block + (drop + (call $___fwritex + (local.get $31) + (local.get $9) + (local.get $0) + ) + ) + (local.set $5 + (i32.load + (local.get $0) + ) + ) + ) + ) + (local.set $6 + (select + (select + (i32.const 4135) + (i32.const 4139) + (local.tee $8 + (i32.ne + (i32.and + (local.get $18) + (i32.const 32) + ) + (i32.const 0) + ) + ) + ) + (select + (i32.const 4127) + (i32.const 4131) + (local.get $8) + ) + (local.get $6) + ) + ) + (if + (i32.eqz + (i32.and + (local.get $5) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $6) + (i32.const 3) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.get $7) + (i32.xor + (local.get $11) + (i32.const 8192) + ) + ) + (select + (local.get $14) + (local.get $7) + (i32.lt_s + (local.get $7) + (local.get $14) + ) + ) + ) + ) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $7) + ) + (br $label$continue$L1) + ) + (local.set $7 + (local.get $5) + ) + (local.set $12 + (local.get $6) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjto$8 + (local.get $26) + ) + ) + (local.set $9 + (i32.and + (local.get $18) + (i32.const 32) + ) + ) + (if + (i32.and + (i32.eqz + (local.tee $8 + (i32.load + (local.tee $5 + (local.get $19) + ) + ) + ) + ) + (i32.eqz + (local.tee $11 + (i32.load offset=4 + (local.get $5) + ) + ) + ) + ) + (block + (local.set $5 + (local.get $26) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjti$8) + ) + (block + (local.set $5 + (local.get $8) + ) + (local.set $8 + (local.get $26) + ) + (loop $while-in123 + (i32.store8 + (local.tee $8 + (i32.add + (local.get $8) + (i32.const -1) + ) + ) + (i32.or + (i32.load8_u + (i32.add + (i32.and + (local.get $5) + (i32.const 15) + ) + (i32.const 4075) + ) + ) + (local.get $9) + ) + ) + (br_if $while-in123 + (i32.eqz + (i32.and + (i32.eqz + (local.tee $5 + (call $_bitshift64Lshr + (local.get $5) + (local.get $11) + (i32.const 4) + ) + ) + ) + (i32.eqz + (local.tee $11 + (global.get $tempRet0) + ) + ) + ) + ) + ) + (local.set $5 + (local.get $8) + ) + ) + (local.set $8 + (if (result i32) + (i32.or + (i32.eqz + (i32.and + (local.get $7) + (i32.const 8) + ) + ) + (i32.and + (i32.eqz + (i32.load + (local.tee $11 + (local.get $19) + ) + ) + ) + (i32.eqz + (i32.load offset=4 + (local.get $11) + ) + ) + ) + ) + (block (result i32) + (local.set $9 + (i32.const 4091) + ) + (i32.const 0) + ) + (block (result i32) + (local.set $9 + (i32.add + (i32.shr_s + (local.get $18) + (i32.const 4) + ) + (i32.const 4091) + ) + ) + (i32.const 2) + ) + ) + ) + (br $__rjti$8) + ) + ) + ) + (local.set $5 + (call $_fmt_u + (local.get $5) + (local.get $7) + (local.get $26) + ) + ) + (local.set $7 + (local.get $11) + ) + (br $__rjti$8) + ) + (local.set $18 + (i32.eqz + (local.tee $13 + (call $_memchr + (local.get $5) + (i32.const 0) + (local.get $6) + ) + ) + ) + ) + (local.set $7 + (local.get $5) + ) + (local.set $11 + (local.get $8) + ) + (local.set $12 + (select + (local.get $6) + (i32.sub + (local.get $13) + (local.get $5) + ) + (local.get $18) + ) + ) + (local.set $8 + (i32.const 0) + ) + (local.set $9 + (i32.const 4091) + ) + (br $__rjto$8 + (select + (i32.add + (local.get $5) + (local.get $6) + ) + (local.get $13) + (local.get $18) + ) + ) + ) + (local.set $5 + (i32.const 0) + ) + (local.set $7 + (i32.const 0) + ) + (local.set $6 + (i32.load + (local.get $19) + ) + ) + (loop $while-in125 + (block $while-out124 + (br_if $while-out124 + (i32.eqz + (local.tee $9 + (i32.load + (local.get $6) + ) + ) + ) + ) + (br_if $while-out124 + (i32.or + (i32.lt_s + (local.tee $7 + (call $_wctomb + (local.get $36) + (local.get $9) + ) + ) + (i32.const 0) + ) + (i32.gt_u + (local.get $7) + (i32.sub + (local.get $8) + (local.get $5) + ) + ) + ) + ) + (local.set $6 + (i32.add + (local.get $6) + (i32.const 4) + ) + ) + (br_if $while-in125 + (i32.gt_u + (local.get $8) + (local.tee $5 + (i32.add + (local.get $7) + (local.get $5) + ) + ) + ) + ) + ) + ) + (if + (i32.lt_s + (local.get $7) + (i32.const 0) + ) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L1) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.get $5) + (local.get $11) + ) + (if + (local.get $5) + (block + (local.set $6 + (i32.const 0) + ) + (local.set $7 + (i32.load + (local.get $19) + ) + ) + (loop $while-in127 + (if + (i32.eqz + (local.tee $8 + (i32.load + (local.get $7) + ) + ) + ) + (block + (local.set $7 + (local.get $5) + ) + (br $__rjti$7) + ) + ) + (if + (i32.gt_s + (local.tee $6 + (i32.add + (local.tee $8 + (call $_wctomb + (local.get $36) + (local.get $8) + ) + ) + (local.get $6) + ) + ) + (local.get $5) + ) + (block + (local.set $7 + (local.get $5) + ) + (br $__rjti$7) + ) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $36) + (local.get $8) + (local.get $0) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $7) + (i32.const 4) + ) + ) + (br_if $while-in127 + (i32.lt_u + (local.get $6) + (local.get $5) + ) + ) + (local.set $7 + (local.get $5) + ) + ) + ) + (local.set $7 + (i32.const 0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $14) + (local.get $7) + (i32.xor + (local.get $11) + (i32.const 8192) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (select + (local.get $14) + (local.get $7) + (i32.gt_s + (local.get $14) + (local.get $7) + ) + ) + ) + (br $label$continue$L1) + ) + (local.set $11 + (select + (i32.and + (local.get $7) + (i32.const -65537) + ) + (local.get $7) + (i32.gt_s + (local.get $6) + (i32.const -1) + ) + ) + ) + (local.set $12 + (if (result i32) + (i32.or + (local.get $6) + (local.tee $12 + (i32.or + (i32.ne + (i32.load + (local.tee $7 + (local.get $19) + ) + ) + (i32.const 0) + ) + (i32.ne + (i32.load offset=4 + (local.get $7) + ) + (i32.const 0) + ) + ) + ) + ) + (block (result i32) + (local.set $7 + (local.get $5) + ) + (select + (local.get $6) + (local.tee $5 + (i32.add + (i32.xor + (i32.and + (local.get $12) + (i32.const 1) + ) + (i32.const 1) + ) + (i32.sub + (local.get $39) + (local.get $5) + ) + ) + ) + (i32.gt_s + (local.get $6) + (local.get $5) + ) + ) + ) + (block (result i32) + (local.set $7 + (local.get $26) + ) + (i32.const 0) + ) + ) + ) + (local.get $26) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.tee $6 + (select + (local.tee $5 + (i32.add + (local.get $8) + (local.tee $12 + (select + (local.tee $13 + (i32.sub + (local.get $5) + (local.get $7) + ) + ) + (local.get $12) + (i32.lt_s + (local.get $12) + (local.get $13) + ) + ) + ) + ) + ) + (local.get $14) + (i32.lt_s + (local.get $14) + (local.get $5) + ) + ) + ) + (local.get $5) + (local.get $11) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $9) + (local.get $8) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $6) + (local.get $5) + (i32.xor + (local.get $11) + (i32.const 65536) + ) + ) + (call $_pad + (local.get $0) + (i32.const 48) + (local.get $12) + (local.get $13) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (i32.load + (local.get $0) + ) + (i32.const 32) + ) + ) + (drop + (call $___fwritex + (local.get $7) + (local.get $13) + (local.get $0) + ) + ) + ) + (call $_pad + (local.get $0) + (i32.const 32) + (local.get $6) + (local.get $5) + (i32.xor + (local.get $11) + (i32.const 8192) + ) + ) + (local.set $5 + (local.get $10) + ) + (local.set $10 + (local.get $6) + ) + (br $label$continue$L1) + ) + ) + (br $label$break$L343) + ) + (if + (i32.eqz + (local.get $0) + ) + (if + (local.get $1) + (block + (local.set $0 + (i32.const 1) + ) + (loop $while-in130 + (if + (local.tee $1 + (i32.load + (i32.add + (local.get $4) + (i32.shl + (local.get $0) + (i32.const 2) + ) + ) + ) + ) + (block + (call $_pop_arg_336 + (i32.add + (local.get $3) + (i32.shl + (local.get $0) + (i32.const 3) + ) + ) + (local.get $1) + (local.get $2) + ) + (br_if $while-in130 + (i32.lt_s + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (i32.const 10) + ) + ) + (local.set $16 + (i32.const 1) + ) + (br $label$break$L343) + ) + ) + ) + (if + (i32.lt_s + (local.get $0) + (i32.const 10) + ) + (loop $while-in132 + (if + (i32.load + (i32.add + (local.get $4) + (i32.shl + (local.get $0) + (i32.const 2) + ) + ) + ) + (block + (local.set $16 + (i32.const -1) + ) + (br $label$break$L343) + ) + ) + (br_if $while-in132 + (i32.lt_s + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (i32.const 10) + ) + ) + (local.set $16 + (i32.const 1) + ) + ) + (local.set $16 + (i32.const 1) + ) + ) + ) + (local.set $16 + (i32.const 0) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $25) + ) + (local.get $16) + ) + (func $_pop_arg_336 (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 f64) + (local $5 i32) + (block $label$break$L1 + (if + (i32.le_u + (local.get $1) + (i32.const 20) + ) + (block $switch-default + (block $switch-case9 + (block $switch-case8 + (block $switch-case7 + (block $switch-case6 + (block $switch-case5 + (block $switch-case4 + (block $switch-case3 + (block $switch-case2 + (block $switch-case1 + (block $switch-case + (br_table $switch-case $switch-case1 $switch-case2 $switch-case3 $switch-case4 $switch-case5 $switch-case6 $switch-case7 $switch-case8 $switch-case9 $switch-default + (i32.sub + (local.get $1) + (i32.const 9) + ) + ) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.get $3) + ) + (br $label$break$L1) + ) + (local.set $1 + (i32.load + (local.tee $3 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $3) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.get $1) + ) + (i32.store offset=4 + (local.get $0) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.get $3) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (br $label$break$L1) + ) + (local.set $5 + (i32.load + (local.tee $3 + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + ) + ) + ) + (local.set $3 + (i32.load offset=4 + (local.get $3) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (i32.store + (local.get $0) + (local.get $5) + ) + (i32.store offset=4 + (local.get $0) + (local.get $3) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.tee $1 + (i32.shr_s + (i32.shl + (i32.and + (local.get $3) + (i32.const 65535) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (i32.and + (local.get $3) + (i32.const 65535) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (local.tee $1 + (i32.shr_s + (i32.shl + (i32.and + (local.get $3) + (i32.const 255) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.shr_s + (i32.shl + (i32.lt_s + (local.get $1) + (i32.const 0) + ) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (br $label$break$L1) + ) + (local.set $3 + (i32.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 3) + ) + (i32.const -4) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.store + (local.get $0) + (i32.and + (local.get $3) + (i32.const 255) + ) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (br $label$break$L1) + ) + (local.set $4 + (f64.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (f64.store + (local.get $0) + (local.get $4) + ) + (br $label$break$L1) + ) + (local.set $4 + (f64.load + (local.tee $1 + (i32.and + (i32.add + (i32.load + (local.get $2) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + ) + ) + (i32.store + (local.get $2) + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (f64.store + (local.get $0) + (local.get $4) + ) + ) + ) + ) + ) + (func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (if + (i32.or + (i32.gt_u + (local.get $1) + (i32.const 0) + ) + (i32.and + (i32.eqz + (local.get $1) + ) + (i32.gt_u + (local.get $0) + (i32.const -1) + ) + ) + ) + (loop $while-in + (i32.store8 + (local.tee $2 + (i32.add + (local.get $2) + (i32.const -1) + ) + ) + (i32.or + (local.tee $3 + (call $___uremdi3 + (local.get $0) + (local.get $1) + (i32.const 10) + (i32.const 0) + ) + ) + (i32.const 48) + ) + ) + (local.set $3 + (call $___udivdi3 + (local.get $0) + (local.get $1) + (i32.const 10) + (i32.const 0) + ) + ) + (local.set $4 + (global.get $tempRet0) + ) + (if + (i32.or + (i32.gt_u + (local.get $1) + (i32.const 9) + ) + (i32.and + (i32.eq + (local.get $1) + (i32.const 9) + ) + (i32.gt_u + (local.get $0) + (i32.const -1) + ) + ) + ) + (block + (local.set $0 + (local.get $3) + ) + (local.set $1 + (local.get $4) + ) + (br $while-in) + ) + (local.set $0 + (local.get $3) + ) + ) + ) + ) + (if + (local.get $0) + (loop $while-in1 + (i32.store8 + (local.tee $2 + (i32.add + (local.get $2) + (i32.const -1) + ) + ) + (i32.or + (call $i32u-rem + (local.get $0) + (i32.const 10) + ) + (i32.const 48) + ) + ) + (local.set $1 + (call $i32u-div + (local.get $0) + (i32.const 10) + ) + ) + (if + (i32.ge_u + (local.get $0) + (i32.const 10) + ) + (block + (local.set $0 + (local.get $1) + ) + (br $while-in1) + ) + ) + ) + ) + (local.get $2) + ) + (func $_pad (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $7 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 256) + ) + ) + (if + (i32.ge_s + (global.get $STACKTOP) + (global.get $STACK_MAX) + ) + (call $abort) + ) + (local.set $6 + (local.get $7) + ) + (block $do-once + (if + (i32.and + (i32.gt_s + (local.get $2) + (local.get $3) + ) + (i32.eqz + (i32.and + (local.get $4) + (i32.const 73728) + ) + ) + ) + (block + (drop + (call $_memset + (local.get $6) + (local.get $1) + (select + (i32.const 256) + (local.tee $5 + (i32.sub + (local.get $2) + (local.get $3) + ) + ) + (i32.gt_u + (local.get $5) + (i32.const 256) + ) + ) + ) + ) + (local.set $4 + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (local.get $0) + ) + ) + (i32.const 32) + ) + ) + ) + (if + (i32.gt_u + (local.get $5) + (i32.const 255) + ) + (block + (loop $while-in + (if + (local.get $4) + (block + (drop + (call $___fwritex + (local.get $6) + (i32.const 256) + (local.get $0) + ) + ) + (local.set $1 + (i32.load + (local.get $0) + ) + ) + ) + ) + (local.set $4 + (i32.eqz + (i32.and + (local.get $1) + (i32.const 32) + ) + ) + ) + (br_if $while-in + (i32.gt_u + (local.tee $5 + (i32.add + (local.get $5) + (i32.const -256) + ) + ) + (i32.const 255) + ) + ) + ) + (br_if $do-once + (i32.eqz + (local.get $4) + ) + ) + (local.set $5 + (i32.and + (i32.sub + (local.get $2) + (local.get $3) + ) + (i32.const 255) + ) + ) + ) + (br_if $do-once + (i32.eqz + (local.get $4) + ) + ) + ) + (drop + (call $___fwritex + (local.get $6) + (local.get $5) + (local.get $0) + ) + ) + ) + ) + ) + (global.set $STACKTOP + (local.get $7) + ) + ) + (func $_malloc (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (block $folding-inner0 + (block $do-once + (if + (i32.lt_u + (local.get $0) + (i32.const 245) + ) + (block + (if + (i32.and + (local.tee $5 + (i32.shr_u + (local.tee $11 + (i32.load + (i32.const 176) + ) + ) + (local.tee $13 + (i32.shr_u + (local.tee $4 + (select + (i32.const 16) + (i32.and + (i32.add + (local.get $0) + (i32.const 11) + ) + (i32.const -8) + ) + (i32.lt_u + (local.get $0) + (i32.const 11) + ) + ) + ) + (i32.const 3) + ) + ) + ) + ) + (i32.const 3) + ) + (block + (local.set $10 + (i32.load + (local.tee $1 + (i32.add + (local.tee $7 + (i32.load + (local.tee $3 + (i32.add + (local.tee $2 + (i32.add + (i32.shl + (local.tee $4 + (i32.add + (i32.xor + (i32.and + (local.get $5) + (i32.const 1) + ) + (i32.const 1) + ) + (local.get $13) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.eq + (local.get $2) + (local.get $10) + ) + (i32.store + (i32.const 176) + (i32.and + (local.get $11) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $4) + ) + (i32.const -1) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $10) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $10) + (i32.const 12) + ) + ) + ) + (local.get $7) + ) + (block + (i32.store + (local.get $0) + (local.get $2) + ) + (i32.store + (local.get $3) + (local.get $10) + ) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=4 + (local.get $7) + (i32.or + (local.tee $0 + (i32.shl + (local.get $4) + (i32.const 3) + ) + ) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $7) + (local.get $0) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + (return + (local.get $1) + ) + ) + ) + (if + (i32.gt_u + (local.get $4) + (local.tee $0 + (i32.load + (i32.const 184) + ) + ) + ) + (block + (if + (local.get $5) + (block + (local.set $10 + (i32.and + (i32.shr_u + (local.tee $3 + (i32.add + (i32.and + (local.tee $3 + (i32.and + (i32.shl + (local.get $5) + (local.get $13) + ) + (i32.or + (local.tee $3 + (i32.shl + (i32.const 2) + (local.get $13) + ) + ) + (i32.sub + (i32.const 0) + (local.get $3) + ) + ) + ) + ) + (i32.sub + (i32.const 0) + (local.get $3) + ) + ) + (i32.const -1) + ) + ) + (i32.const 12) + ) + (i32.const 16) + ) + ) + (local.set $9 + (i32.load + (local.tee $7 + (i32.add + (local.tee $12 + (i32.load + (local.tee $3 + (i32.add + (local.tee $10 + (i32.add + (i32.shl + (local.tee $5 + (i32.add + (i32.or + (i32.or + (i32.or + (i32.or + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $3) + (local.get $10) + ) + ) + (i32.const 5) + ) + (i32.const 8) + ) + ) + (local.get $10) + ) + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + (i32.const 2) + ) + (i32.const 4) + ) + ) + ) + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + (i32.const 1) + ) + (i32.const 2) + ) + ) + ) + (local.tee $3 + (i32.and + (i32.shr_u + (local.tee $7 + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + ) + (i32.shr_u + (local.get $7) + (local.get $3) + ) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 8) + ) + ) + ) + ) + (if + (i32.eq + (local.get $10) + (local.get $9) + ) + (block + (i32.store + (i32.const 176) + (i32.and + (local.get $11) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $5) + ) + (i32.const -1) + ) + ) + ) + (local.set $8 + (local.get $0) + ) + ) + (block + (if + (i32.lt_u + (local.get $9) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $9) + (i32.const 12) + ) + ) + ) + (local.get $12) + ) + (block + (i32.store + (local.get $0) + (local.get $10) + ) + (i32.store + (local.get $3) + (local.get $9) + ) + (local.set $8 + (i32.load + (i32.const 184) + ) + ) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.or + (local.get $4) + (i32.const 3) + ) + ) + (i32.store offset=4 + (local.tee $10 + (i32.add + (local.get $12) + (local.get $4) + ) + ) + (i32.or + (local.tee $5 + (i32.sub + (i32.shl + (local.get $5) + (i32.const 3) + ) + (local.get $4) + ) + ) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $10) + (local.get $5) + ) + (local.get $5) + ) + (if + (local.get $8) + (block + (local.set $12 + (i32.load + (i32.const 196) + ) + ) + (local.set $4 + (i32.add + (i32.shl + (local.tee $0 + (i32.shr_u + (local.get $8) + (i32.const 3) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $3 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $3 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (local.set $2 + (local.get $3) + ) + (local.set $1 + (local.get $0) + ) + ) + ) + (block + (i32.store + (i32.const 176) + (i32.or + (local.get $3) + (local.get $0) + ) + ) + (local.set $2 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + (local.set $1 + (local.get $4) + ) + ) + ) + (i32.store + (local.get $2) + (local.get $12) + ) + (i32.store offset=12 + (local.get $1) + (local.get $12) + ) + (i32.store offset=8 + (local.get $12) + (local.get $1) + ) + (i32.store offset=12 + (local.get $12) + (local.get $4) + ) + ) + ) + (i32.store + (i32.const 184) + (local.get $5) + ) + (i32.store + (i32.const 196) + (local.get $10) + ) + (return + (local.get $7) + ) + ) + ) + (if + (local.tee $0 + (i32.load + (i32.const 180) + ) + ) + (block + (local.set $2 + (i32.and + (i32.shr_u + (local.tee $0 + (i32.add + (i32.and + (local.get $0) + (i32.sub + (i32.const 0) + (local.get $0) + ) + ) + (i32.const -1) + ) + ) + (i32.const 12) + ) + (i32.const 16) + ) + ) + (local.set $7 + (i32.sub + (i32.and + (i32.load offset=4 + (local.tee $0 + (i32.load offset=480 + (i32.shl + (i32.add + (i32.or + (i32.or + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $0) + (local.get $2) + ) + ) + (i32.const 5) + ) + (i32.const 8) + ) + ) + (local.get $2) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 2) + ) + (i32.const 4) + ) + ) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 1) + ) + (i32.const 2) + ) + ) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + ) + (i32.shr_u + (local.get $1) + (local.get $0) + ) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.const -8) + ) + (local.get $4) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (local.get $0) + ) + (loop $while-in + (block $while-out + (if + (i32.eqz + (local.tee $0 + (i32.load offset=16 + (local.get $1) + ) + ) + ) + (if + (i32.eqz + (local.tee $0 + (i32.load offset=20 + (local.get $1) + ) + ) + ) + (block + (local.set $10 + (local.get $7) + ) + (local.set $5 + (local.get $2) + ) + (br $while-out) + ) + ) + ) + (local.set $10 + (i32.lt_u + (local.tee $1 + (i32.sub + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $4) + ) + ) + (local.get $7) + ) + ) + (local.set $7 + (select + (local.get $1) + (local.get $7) + (local.get $10) + ) + ) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (select + (local.get $0) + (local.get $2) + (local.get $10) + ) + ) + (br $while-in) + ) + ) + (if + (i32.lt_u + (local.get $5) + (local.tee $12 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (if + (i32.ge_u + (local.get $5) + (local.tee $11 + (i32.add + (local.get $5) + (local.get $4) + ) + ) + ) + (call $_abort) + ) + (local.set $8 + (i32.load offset=24 + (local.get $5) + ) + ) + (block $do-once4 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $5) + ) + ) + (local.get $5) + ) + (block + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $5) + (i32.const 20) + ) + ) + ) + ) + ) + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + ) + ) + ) + (block + (local.set $9 + (i32.const 0) + ) + (br $do-once4) + ) + ) + ) + (loop $while-in7 + (if + (local.tee $2 + (i32.load + (local.tee $7 + (i32.add + (local.get $1) + (i32.const 20) + ) + ) + ) + ) + (block + (local.set $1 + (local.get $2) + ) + (local.set $0 + (local.get $7) + ) + (br $while-in7) + ) + ) + (if + (local.tee $2 + (i32.load + (local.tee $7 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $1 + (local.get $2) + ) + (local.set $0 + (local.get $7) + ) + (br $while-in7) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (local.get $12) + ) + (call $_abort) + (block + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $9 + (local.get $1) + ) + ) + ) + ) + (block + (if + (i32.lt_u + (local.tee $7 + (i32.load offset=8 + (local.get $5) + ) + ) + (local.get $12) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $2 + (i32.add + (local.get $7) + (i32.const 12) + ) + ) + ) + (local.get $5) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $5) + ) + (block + (i32.store + (local.get $2) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $7) + ) + (local.set $9 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (block $do-once8 + (if + (local.get $8) + (block + (if + (i32.eq + (local.get $5) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $1 + (i32.load offset=28 + (local.get $5) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block + (i32.store + (local.get $0) + (local.get $9) + ) + (if + (i32.eqz + (local.get $9) + ) + (block + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $do-once8) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $8) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + ) + (local.get $5) + ) + (i32.store + (local.get $0) + (local.get $9) + ) + (i32.store offset=20 + (local.get $8) + (local.get $9) + ) + ) + (br_if $do-once8 + (i32.eqz + (local.get $9) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $9) + (local.tee $0 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $9) + (local.get $8) + ) + (if + (local.tee $1 + (i32.load offset=16 + (local.get $5) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.get $0) + ) + (call $_abort) + (block + (i32.store offset=16 + (local.get $9) + (local.get $1) + ) + (i32.store offset=24 + (local.get $1) + (local.get $9) + ) + ) + ) + ) + (if + (local.tee $0 + (i32.load offset=20 + (local.get $5) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store offset=20 + (local.get $9) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $9) + ) + ) + ) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $10) + (i32.const 16) + ) + (block + (i32.store offset=4 + (local.get $5) + (i32.or + (local.tee $0 + (i32.add + (local.get $10) + (local.get $4) + ) + ) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $5) + (local.get $0) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + ) + (block + (i32.store offset=4 + (local.get $5) + (i32.or + (local.get $4) + (i32.const 3) + ) + ) + (i32.store offset=4 + (local.get $11) + (i32.or + (local.get $10) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $11) + (local.get $10) + ) + (local.get $10) + ) + (if + (local.tee $0 + (i32.load + (i32.const 184) + ) + ) + (block + (local.set $4 + (i32.load + (i32.const 196) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (local.tee $0 + (i32.shr_u + (local.get $0) + (i32.const 3) + ) + ) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $1 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (local.set $6 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + (block + (i32.store + (i32.const 176) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (local.set $6 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (local.set $3 + (local.get $2) + ) + ) + ) + (i32.store + (local.get $6) + (local.get $4) + ) + (i32.store offset=12 + (local.get $3) + (local.get $4) + ) + (i32.store offset=8 + (local.get $4) + (local.get $3) + ) + (i32.store offset=12 + (local.get $4) + (local.get $2) + ) + ) + ) + (i32.store + (i32.const 184) + (local.get $10) + ) + (i32.store + (i32.const 196) + (local.get $11) + ) + ) + ) + (return + (i32.add + (local.get $5) + (i32.const 8) + ) + ) + ) + (local.set $0 + (local.get $4) + ) + ) + ) + (local.set $0 + (local.get $4) + ) + ) + ) + (if + (i32.gt_u + (local.get $0) + (i32.const -65) + ) + (local.set $0 + (i32.const -1) + ) + (block + (local.set $2 + (i32.and + (local.tee $0 + (i32.add + (local.get $0) + (i32.const 11) + ) + ) + (i32.const -8) + ) + ) + (if + (local.tee $18 + (i32.load + (i32.const 180) + ) + ) + (block + (local.set $14 + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $0) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $2) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $2) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $3 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $3) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (local.set $3 + (i32.sub + (i32.const 0) + (local.get $2) + ) + ) + (block $__rjto$3 + (block $__rjti$3 + (if + (local.tee $0 + (i32.load offset=480 + (i32.shl + (local.get $14) + (i32.const 2) + ) + ) + ) + (block + (local.set $6 + (i32.const 0) + ) + (local.set $8 + (i32.shl + (local.get $2) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $14) + (i32.const 1) + ) + ) + (i32.eq + (local.get $14) + (i32.const 31) + ) + ) + ) + ) + (local.set $1 + (i32.const 0) + ) + (loop $while-in14 + (if + (i32.lt_u + (local.tee $4 + (i32.sub + (local.tee $9 + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + ) + (local.get $2) + ) + ) + (local.get $3) + ) + (if + (i32.eq + (local.get $9) + (local.get $2) + ) + (block + (local.set $1 + (local.get $4) + ) + (local.set $3 + (local.get $0) + ) + (br $__rjti$3) + ) + (block + (local.set $3 + (local.get $4) + ) + (local.set $1 + (local.get $0) + ) + ) + ) + ) + (local.set $0 + (select + (local.get $6) + (local.tee $4 + (i32.load offset=20 + (local.get $0) + ) + ) + (i32.or + (i32.eqz + (local.get $4) + ) + (i32.eq + (local.get $4) + (local.tee $9 + (i32.load + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $8) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + ) + ) + ) + (local.set $4 + (i32.shl + (local.get $8) + (i32.xor + (local.tee $6 + (i32.eqz + (local.get $9) + ) + ) + (i32.const 1) + ) + ) + ) + (if + (local.get $6) + (block + (local.set $4 + (local.get $0) + ) + (local.set $0 + (local.get $1) + ) + ) + (block + (local.set $6 + (local.get $0) + ) + (local.set $8 + (local.get $4) + ) + (local.set $0 + (local.get $9) + ) + (br $while-in14) + ) + ) + ) + ) + (block + (local.set $4 + (i32.const 0) + ) + (local.set $0 + (i32.const 0) + ) + ) + ) + (if + (i32.and + (i32.eqz + (local.get $4) + ) + (i32.eqz + (local.get $0) + ) + ) + (block + (if + (i32.eqz + (local.tee $1 + (i32.and + (local.get $18) + (i32.or + (local.tee $1 + (i32.shl + (i32.const 2) + (local.get $14) + ) + ) + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + ) + ) + ) + (block + (local.set $0 + (local.get $2) + ) + (br $do-once) + ) + ) + (local.set $9 + (i32.and + (i32.shr_u + (local.tee $1 + (i32.add + (i32.and + (local.get $1) + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + (i32.const -1) + ) + ) + (i32.const 12) + ) + (i32.const 16) + ) + ) + (local.set $4 + (i32.load offset=480 + (i32.shl + (i32.add + (i32.or + (i32.or + (i32.or + (i32.or + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $1) + (local.get $9) + ) + ) + (i32.const 5) + ) + (i32.const 8) + ) + ) + (local.get $9) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 2) + ) + (i32.const 4) + ) + ) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 1) + ) + (i32.const 2) + ) + ) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (local.tee $4 + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 1) + ) + (i32.const 1) + ) + ) + ) + (i32.shr_u + (local.get $4) + (local.get $1) + ) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (if + (local.get $4) + (block + (local.set $1 + (local.get $3) + ) + (local.set $3 + (local.get $4) + ) + (br $__rjti$3) + ) + (local.set $4 + (local.get $0) + ) + ) + (br $__rjto$3) + ) + (loop $while-in16 + (local.set $9 + (i32.lt_u + (local.tee $4 + (i32.sub + (i32.and + (i32.load offset=4 + (local.get $3) + ) + (i32.const -8) + ) + (local.get $2) + ) + ) + (local.get $1) + ) + ) + (local.set $1 + (select + (local.get $4) + (local.get $1) + (local.get $9) + ) + ) + (local.set $0 + (select + (local.get $3) + (local.get $0) + (local.get $9) + ) + ) + (if + (local.tee $4 + (i32.load offset=16 + (local.get $3) + ) + ) + (block + (local.set $3 + (local.get $4) + ) + (br $while-in16) + ) + ) + (br_if $while-in16 + (local.tee $3 + (i32.load offset=20 + (local.get $3) + ) + ) + ) + (local.set $3 + (local.get $1) + ) + (local.set $4 + (local.get $0) + ) + ) + ) + (if + (local.get $4) + (if + (i32.lt_u + (local.get $3) + (i32.sub + (i32.load + (i32.const 184) + ) + (local.get $2) + ) + ) + (block + (if + (i32.lt_u + (local.get $4) + (local.tee $12 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (if + (i32.ge_u + (local.get $4) + (local.tee $6 + (i32.add + (local.get $4) + (local.get $2) + ) + ) + ) + (call $_abort) + ) + (local.set $9 + (i32.load offset=24 + (local.get $4) + ) + ) + (block $do-once17 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $4) + ) + ) + (local.get $4) + ) + (block + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 20) + ) + ) + ) + ) + ) + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 16) + ) + ) + ) + ) + ) + (block + (local.set $11 + (i32.const 0) + ) + (br $do-once17) + ) + ) + ) + (loop $while-in20 + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $1) + (i32.const 20) + ) + ) + ) + ) + (block + (local.set $1 + (local.get $7) + ) + (local.set $0 + (local.get $10) + ) + (br $while-in20) + ) + ) + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $1 + (local.get $7) + ) + (local.set $0 + (local.get $10) + ) + (br $while-in20) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (local.get $12) + ) + (call $_abort) + (block + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $11 + (local.get $1) + ) + ) + ) + ) + (block + (if + (i32.lt_u + (local.tee $10 + (i32.load offset=8 + (local.get $4) + ) + ) + (local.get $12) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $7 + (i32.add + (local.get $10) + (i32.const 12) + ) + ) + ) + (local.get $4) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $4) + ) + (block + (i32.store + (local.get $7) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $10) + ) + (local.set $11 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (block $do-once21 + (if + (local.get $9) + (block + (if + (i32.eq + (local.get $4) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $1 + (i32.load offset=28 + (local.get $4) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block + (i32.store + (local.get $0) + (local.get $11) + ) + (if + (i32.eqz + (local.get $11) + ) + (block + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $do-once21) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $9) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $9) + (i32.const 16) + ) + ) + ) + (local.get $4) + ) + (i32.store + (local.get $0) + (local.get $11) + ) + (i32.store offset=20 + (local.get $9) + (local.get $11) + ) + ) + (br_if $do-once21 + (i32.eqz + (local.get $11) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $11) + (local.tee $0 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $11) + (local.get $9) + ) + (if + (local.tee $1 + (i32.load offset=16 + (local.get $4) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.get $0) + ) + (call $_abort) + (block + (i32.store offset=16 + (local.get $11) + (local.get $1) + ) + (i32.store offset=24 + (local.get $1) + (local.get $11) + ) + ) + ) + ) + (if + (local.tee $0 + (i32.load offset=20 + (local.get $4) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store offset=20 + (local.get $11) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $11) + ) + ) + ) + ) + ) + ) + ) + (block $do-once25 + (if + (i32.lt_u + (local.get $3) + (i32.const 16) + ) + (block + (i32.store offset=4 + (local.get $4) + (i32.or + (local.tee $0 + (i32.add + (local.get $3) + (local.get $2) + ) + ) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $4) + (local.get $0) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + ) + (block + (i32.store offset=4 + (local.get $4) + (i32.or + (local.get $2) + (i32.const 3) + ) + ) + (i32.store offset=4 + (local.get $6) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $6) + (local.get $3) + ) + (local.get $3) + ) + (local.set $0 + (i32.shr_u + (local.get $3) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $3) + (i32.const 256) + ) + (block + (local.set $3 + (i32.add + (i32.shl + (local.get $0) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $1 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (local.set $13 + (local.get $1) + ) + (local.set $5 + (local.get $0) + ) + ) + ) + (block + (i32.store + (i32.const 176) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (local.set $13 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + (local.set $5 + (local.get $3) + ) + ) + ) + (i32.store + (local.get $13) + (local.get $6) + ) + (i32.store offset=12 + (local.get $5) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $5) + ) + (i32.store offset=12 + (local.get $6) + (local.get $3) + ) + (br $do-once25) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (local.tee $7 + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $3) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $3) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $2 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $2) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $6) + (local.get $7) + ) + (i32.store offset=4 + (local.tee $0 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + (i32.const 0) + ) + (i32.store + (local.get $0) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (i32.const 180) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $7) + ) + ) + ) + ) + (block + (i32.store + (i32.const 180) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (i32.store + (local.get $2) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $2) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once25) + ) + ) + (local.set $7 + (i32.shl + (local.get $3) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $7) + (i32.const 1) + ) + ) + (i32.eq + (local.get $7) + (i32.const 31) + ) + ) + ) + ) + (local.set $0 + (i32.load + (local.get $2) + ) + ) + (block $__rjto$1 + (block $__rjti$1 + (loop $while-in28 + (br_if $__rjti$1 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $3) + ) + ) + (local.set $2 + (i32.shl + (local.get $7) + (i32.const 1) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $7 + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $7) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block + (local.set $7 + (local.get $2) + ) + (local.set $0 + (local.get $1) + ) + (br $while-in28) + ) + ) + ) + (if + (i32.lt_u + (local.get $7) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store + (local.get $7) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $0) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once25) + ) + ) + (br $__rjto$1) + ) + (if + (i32.and + (i32.ge_u + (local.tee $2 + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + (local.tee $1 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $0) + (local.get $1) + ) + ) + (block + (i32.store offset=12 + (local.get $2) + (local.get $6) + ) + (i32.store + (local.get $3) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $2) + ) + (i32.store offset=12 + (local.get $6) + (local.get $0) + ) + (i32.store offset=24 + (local.get $6) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + ) + ) + (return + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + (local.set $0 + (local.get $2) + ) + ) + (local.set $0 + (local.get $2) + ) + ) + ) + (local.set $0 + (local.get $2) + ) + ) + ) + ) + ) + ) + (if + (i32.ge_u + (local.tee $1 + (i32.load + (i32.const 184) + ) + ) + (local.get $0) + ) + (block + (local.set $2 + (i32.load + (i32.const 196) + ) + ) + (if + (i32.gt_u + (local.tee $3 + (i32.sub + (local.get $1) + (local.get $0) + ) + ) + (i32.const 15) + ) + (block + (i32.store + (i32.const 196) + (local.tee $1 + (i32.add + (local.get $2) + (local.get $0) + ) + ) + ) + (i32.store + (i32.const 184) + (local.get $3) + ) + (i32.store offset=4 + (local.get $1) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $1) + (local.get $3) + ) + (local.get $3) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 3) + ) + ) + ) + (block + (i32.store + (i32.const 184) + (i32.const 0) + ) + (i32.store + (i32.const 196) + (i32.const 0) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $1) + (i32.const 3) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (i32.add + (local.get $2) + (local.get $1) + ) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 1) + ) + ) + ) + ) + (return + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + ) + (br_if $folding-inner0 + (i32.gt_u + (local.tee $1 + (i32.load + (i32.const 188) + ) + ) + (local.get $0) + ) + ) + (if + (i32.eqz + (i32.load + (i32.const 648) + ) + ) + (if + (i32.and + (i32.add + (local.tee $1 + (call $_sysconf + (i32.const 30) + ) + ) + (i32.const -1) + ) + (local.get $1) + ) + (call $_abort) + (block + (i32.store + (i32.const 656) + (local.get $1) + ) + (i32.store + (i32.const 652) + (local.get $1) + ) + (i32.store + (i32.const 660) + (i32.const -1) + ) + (i32.store + (i32.const 664) + (i32.const -1) + ) + (i32.store + (i32.const 668) + (i32.const 0) + ) + (i32.store + (i32.const 620) + (i32.const 0) + ) + (i32.store + (i32.const 648) + (i32.xor + (i32.and + (call $_time + (i32.const 0) + ) + (i32.const -16) + ) + (i32.const 1431655768) + ) + ) + ) + ) + ) + (if + (i32.le_u + (local.tee $5 + (i32.and + (local.tee $6 + (i32.add + (local.tee $1 + (i32.load + (i32.const 656) + ) + ) + (local.tee $8 + (i32.add + (local.get $0) + (i32.const 47) + ) + ) + ) + ) + (local.tee $9 + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + ) + ) + (local.get $0) + ) + (return + (i32.const 0) + ) + ) + (if + (local.tee $2 + (i32.load + (i32.const 616) + ) + ) + (if + (i32.or + (i32.le_u + (local.tee $1 + (i32.add + (local.tee $3 + (i32.load + (i32.const 608) + ) + ) + (local.get $5) + ) + ) + (local.get $3) + ) + (i32.gt_u + (local.get $1) + (local.get $2) + ) + ) + (return + (i32.const 0) + ) + ) + ) + (local.set $11 + (i32.add + (local.get $0) + (i32.const 48) + ) + ) + (block $__rjto$13 + (block $__rjti$13 + (if + (i32.eqz + (i32.and + (i32.load + (i32.const 620) + ) + (i32.const 4) + ) + ) + (block + (block $label$break$L279 + (block $__rjti$5 + (block $__rjti$4 + (br_if $__rjti$4 + (i32.eqz + (local.tee $4 + (i32.load + (i32.const 200) + ) + ) + ) + ) + (local.set $1 + (i32.const 624) + ) + (loop $while-in34 + (block $while-out33 + (if + (i32.le_u + (local.tee $3 + (i32.load + (local.get $1) + ) + ) + (local.get $4) + ) + (if + (i32.gt_u + (i32.add + (local.get $3) + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + ) + ) + (local.get $4) + ) + (block + (local.set $4 + (local.get $1) + ) + (br $while-out33) + ) + ) + ) + (br_if $while-in34 + (local.tee $1 + (i32.load offset=8 + (local.get $1) + ) + ) + ) + (br $__rjti$4) + ) + ) + (if + (i32.lt_u + (local.tee $3 + (i32.and + (i32.sub + (local.get $6) + (i32.load + (i32.const 188) + ) + ) + (local.get $9) + ) + ) + (i32.const 2147483647) + ) + (if + (i32.eq + (local.tee $1 + (call $_sbrk + (local.get $3) + ) + ) + (i32.add + (i32.load + (local.get $4) + ) + (i32.load + (local.get $2) + ) + ) + ) + (br_if $__rjti$13 + (i32.ne + (local.get $1) + (i32.const -1) + ) + ) + (block + (local.set $2 + (local.get $1) + ) + (br $__rjti$5) + ) + ) + ) + (br $label$break$L279) + ) + (if + (i32.ne + (local.tee $1 + (call $_sbrk + (i32.const 0) + ) + ) + (i32.const -1) + ) + (block + (local.set $3 + (if (result i32) + (i32.and + (local.tee $2 + (i32.add + (local.tee $4 + (i32.load + (i32.const 652) + ) + ) + (i32.const -1) + ) + ) + (local.tee $3 + (local.get $1) + ) + ) + (i32.add + (i32.sub + (local.get $5) + (local.get $3) + ) + (i32.and + (i32.add + (local.get $2) + (local.get $3) + ) + (i32.sub + (i32.const 0) + (local.get $4) + ) + ) + ) + (local.get $5) + ) + ) + (local.set $9 + (i32.add + (local.tee $4 + (i32.load + (i32.const 608) + ) + ) + (local.get $3) + ) + ) + (if + (i32.and + (i32.gt_u + (local.get $3) + (local.get $0) + ) + (i32.lt_u + (local.get $3) + (i32.const 2147483647) + ) + ) + (block + (if + (local.tee $2 + (i32.load + (i32.const 616) + ) + ) + (br_if $label$break$L279 + (i32.or + (i32.le_u + (local.get $9) + (local.get $4) + ) + (i32.gt_u + (local.get $9) + (local.get $2) + ) + ) + ) + ) + (br_if $__rjti$13 + (i32.eq + (local.tee $2 + (call $_sbrk + (local.get $3) + ) + ) + (local.get $1) + ) + ) + (br $__rjti$5) + ) + ) + ) + ) + (br $label$break$L279) + ) + (local.set $1 + (local.get $3) + ) + (local.set $4 + (i32.sub + (i32.const 0) + (local.get $1) + ) + ) + (if + (i32.and + (i32.gt_u + (local.get $11) + (local.get $1) + ) + (i32.and + (i32.lt_u + (local.get $1) + (i32.const 2147483647) + ) + (i32.ne + (local.get $2) + (i32.const -1) + ) + ) + ) + (if + (i32.lt_u + (local.tee $3 + (i32.and + (i32.add + (i32.sub + (local.get $8) + (local.get $1) + ) + (local.tee $3 + (i32.load + (i32.const 656) + ) + ) + ) + (i32.sub + (i32.const 0) + (local.get $3) + ) + ) + ) + (i32.const 2147483647) + ) + (if + (i32.eq + (call $_sbrk + (local.get $3) + ) + (i32.const -1) + ) + (block + (drop + (call $_sbrk + (local.get $4) + ) + ) + (br $label$break$L279) + ) + (local.set $3 + (i32.add + (local.get $3) + (local.get $1) + ) + ) + ) + (local.set $3 + (local.get $1) + ) + ) + (local.set $3 + (local.get $1) + ) + ) + (if + (i32.ne + (local.get $2) + (i32.const -1) + ) + (block + (local.set $1 + (local.get $2) + ) + (br $__rjti$13) + ) + ) + ) + (i32.store + (i32.const 620) + (i32.or + (i32.load + (i32.const 620) + ) + (i32.const 4) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $5) + (i32.const 2147483647) + ) + (if + (i32.and + (i32.lt_u + (local.tee $1 + (call $_sbrk + (local.get $5) + ) + ) + (local.tee $3 + (call $_sbrk + (i32.const 0) + ) + ) + ) + (i32.and + (i32.ne + (local.get $1) + (i32.const -1) + ) + (i32.ne + (local.get $3) + (i32.const -1) + ) + ) + ) + (br_if $__rjti$13 + (i32.gt_u + (local.tee $3 + (i32.sub + (local.get $3) + (local.get $1) + ) + ) + (i32.add + (local.get $0) + (i32.const 40) + ) + ) + ) + ) + ) + (br $__rjto$13) + ) + (i32.store + (i32.const 608) + (local.tee $2 + (i32.add + (i32.load + (i32.const 608) + ) + (local.get $3) + ) + ) + ) + (if + (i32.gt_u + (local.get $2) + (i32.load + (i32.const 612) + ) + ) + (i32.store + (i32.const 612) + (local.get $2) + ) + ) + (block $do-once40 + (if + (local.tee $6 + (i32.load + (i32.const 200) + ) + ) + (block + (local.set $2 + (i32.const 624) + ) + (block $__rjto$10 + (block $__rjti$10 + (loop $while-in45 + (br_if $__rjti$10 + (i32.eq + (local.get $1) + (i32.add + (local.tee $11 + (i32.load + (local.get $2) + ) + ) + (local.tee $5 + (i32.load + (local.tee $4 + (i32.add + (local.get $2) + (i32.const 4) + ) + ) + ) + ) + ) + ) + ) + (br_if $while-in45 + (local.tee $2 + (i32.load offset=8 + (local.get $2) + ) + ) + ) + ) + (br $__rjto$10) + ) + (if + (i32.eqz + (i32.and + (i32.load offset=12 + (local.get $2) + ) + (i32.const 8) + ) + ) + (if + (i32.and + (i32.lt_u + (local.get $6) + (local.get $1) + ) + (i32.ge_u + (local.get $6) + (local.get $11) + ) + ) + (block + (i32.store + (local.get $4) + (i32.add + (local.get $5) + (local.get $3) + ) + ) + (local.set $2 + (i32.add + (local.get $6) + (local.tee $1 + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $6) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + ) + (local.set $1 + (i32.add + (i32.sub + (local.get $3) + (local.get $1) + ) + (i32.load + (i32.const 188) + ) + ) + ) + (i32.store + (i32.const 200) + (local.get $2) + ) + (i32.store + (i32.const 188) + (local.get $1) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $1) + (i32.const 1) + ) + ) + (i32.store offset=4 + (i32.add + (local.get $2) + (local.get $1) + ) + (i32.const 40) + ) + (i32.store + (i32.const 204) + (i32.load + (i32.const 664) + ) + ) + (br $do-once40) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.tee $4 + (i32.load + (i32.const 192) + ) + ) + ) + (block + (i32.store + (i32.const 192) + (local.get $1) + ) + (local.set $4 + (local.get $1) + ) + ) + ) + (local.set $11 + (i32.add + (local.get $1) + (local.get $3) + ) + ) + (local.set $2 + (i32.const 624) + ) + (block $__rjto$11 + (block $__rjti$11 + (loop $while-in47 + (if + (i32.eq + (i32.load + (local.get $2) + ) + (local.get $11) + ) + (block + (local.set $5 + (local.get $2) + ) + (br $__rjti$11) + ) + ) + (br_if $while-in47 + (local.tee $2 + (i32.load offset=8 + (local.get $2) + ) + ) + ) + (local.set $4 + (i32.const 624) + ) + ) + (br $__rjto$11) + ) + (if + (i32.and + (i32.load offset=12 + (local.get $2) + ) + (i32.const 8) + ) + (local.set $4 + (i32.const 624) + ) + (block + (i32.store + (local.get $5) + (local.get $1) + ) + (i32.store + (local.tee $2 + (i32.add + (local.get $2) + (i32.const 4) + ) + ) + (i32.add + (i32.load + (local.get $2) + ) + (local.get $3) + ) + ) + (local.set $8 + (i32.add + (local.tee $9 + (i32.add + (local.get $1) + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + (local.get $0) + ) + ) + (local.set $7 + (i32.sub + (i32.sub + (local.tee $5 + (i32.add + (local.get $11) + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $11) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + (local.get $9) + ) + (local.get $0) + ) + ) + (i32.store offset=4 + (local.get $9) + (i32.or + (local.get $0) + (i32.const 3) + ) + ) + (block $do-once48 + (if + (i32.eq + (local.get $5) + (local.get $6) + ) + (block + (i32.store + (i32.const 188) + (local.tee $0 + (i32.add + (i32.load + (i32.const 188) + ) + (local.get $7) + ) + ) + ) + (i32.store + (i32.const 200) + (local.get $8) + ) + (i32.store offset=4 + (local.get $8) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + ) + (block + (if + (i32.eq + (local.get $5) + (i32.load + (i32.const 196) + ) + ) + (block + (i32.store + (i32.const 184) + (local.tee $0 + (i32.add + (i32.load + (i32.const 184) + ) + (local.get $7) + ) + ) + ) + (i32.store + (i32.const 196) + (local.get $8) + ) + (i32.store offset=4 + (local.get $8) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $8) + (local.get $0) + ) + (local.get $0) + ) + (br $do-once48) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (local.tee $0 + (if (result i32) + (i32.eq + (i32.and + (local.tee $0 + (i32.load offset=4 + (local.get $5) + ) + ) + (i32.const 3) + ) + (i32.const 1) + ) + (block (result i32) + (local.set $11 + (i32.and + (local.get $0) + (i32.const -8) + ) + ) + (local.set $1 + (i32.shr_u + (local.get $0) + (i32.const 3) + ) + ) + (block $label$break$L331 + (if + (i32.lt_u + (local.get $0) + (i32.const 256) + ) + (block + (local.set $2 + (i32.load offset=12 + (local.get $5) + ) + ) + (block $do-once51 + (if + (i32.ne + (local.tee $3 + (i32.load offset=8 + (local.get $5) + ) + ) + (local.tee $0 + (i32.add + (i32.shl + (local.get $1) + (i32.const 3) + ) + (i32.const 216) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $3) + (local.get $4) + ) + (call $_abort) + ) + (br_if $do-once51 + (i32.eq + (i32.load offset=12 + (local.get $3) + ) + (local.get $5) + ) + ) + (call $_abort) + ) + ) + ) + (if + (i32.eq + (local.get $2) + (local.get $3) + ) + (block + (i32.store + (i32.const 176) + (i32.and + (i32.load + (i32.const 176) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $label$break$L331) + ) + ) + (block $do-once53 + (if + (i32.eq + (local.get $2) + (local.get $0) + ) + (local.set $15 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (block + (if + (i32.lt_u + (local.get $2) + (local.get $4) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + (local.get $5) + ) + (block + (local.set $15 + (local.get $0) + ) + (br $do-once53) + ) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=12 + (local.get $3) + (local.get $2) + ) + (i32.store + (local.get $15) + (local.get $3) + ) + ) + (block + (local.set $6 + (i32.load offset=24 + (local.get $5) + ) + ) + (block $do-once55 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $5) + ) + ) + (local.get $5) + ) + (block + (if + (i32.eqz + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.tee $3 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (if + (local.tee $1 + (i32.load + (local.get $3) + ) + ) + (local.set $0 + (local.get $3) + ) + (block + (local.set $12 + (i32.const 0) + ) + (br $do-once55) + ) + ) + ) + (loop $while-in58 + (if + (local.tee $3 + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 20) + ) + ) + ) + ) + (block + (local.set $1 + (local.get $3) + ) + (local.set $0 + (local.get $2) + ) + (br $while-in58) + ) + ) + (if + (local.tee $3 + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $1 + (local.get $3) + ) + (local.set $0 + (local.get $2) + ) + (br $while-in58) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (local.get $4) + ) + (call $_abort) + (block + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $12 + (local.get $1) + ) + ) + ) + ) + (block + (if + (i32.lt_u + (local.tee $2 + (i32.load offset=8 + (local.get $5) + ) + ) + (local.get $4) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $3 + (i32.add + (local.get $2) + (i32.const 12) + ) + ) + ) + (local.get $5) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $5) + ) + (block + (i32.store + (local.get $3) + (local.get $0) + ) + (i32.store + (local.get $1) + (local.get $2) + ) + (local.set $12 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (br_if $label$break$L331 + (i32.eqz + (local.get $6) + ) + ) + (block $do-once59 + (if + (i32.eq + (local.get $5) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $1 + (i32.load offset=28 + (local.get $5) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block + (i32.store + (local.get $0) + (local.get $12) + ) + (br_if $do-once59 + (local.get $12) + ) + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $1) + ) + (i32.const -1) + ) + ) + ) + (br $label$break$L331) + ) + (block + (if + (i32.lt_u + (local.get $6) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + ) + (local.get $5) + ) + (i32.store + (local.get $0) + (local.get $12) + ) + (i32.store offset=20 + (local.get $6) + (local.get $12) + ) + ) + (br_if $label$break$L331 + (i32.eqz + (local.get $12) + ) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $12) + (local.tee $1 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $12) + (local.get $6) + ) + (if + (local.tee $3 + (i32.load + (local.tee $0 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $3) + (local.get $1) + ) + (call $_abort) + (block + (i32.store offset=16 + (local.get $12) + (local.get $3) + ) + (i32.store offset=24 + (local.get $3) + (local.get $12) + ) + ) + ) + ) + (br_if $label$break$L331 + (i32.eqz + (local.tee $0 + (i32.load offset=4 + (local.get $0) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store offset=20 + (local.get $12) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $12) + ) + ) + ) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $11) + (local.get $7) + ) + ) + (i32.add + (local.get $5) + (local.get $11) + ) + ) + (local.get $5) + ) + ) + (i32.const 4) + ) + ) + (i32.and + (i32.load + (local.get $0) + ) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $8) + (i32.or + (local.get $7) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $8) + (local.get $7) + ) + (local.get $7) + ) + (local.set $0 + (i32.shr_u + (local.get $7) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $7) + (i32.const 256) + ) + (block + (local.set $3 + (i32.add + (i32.shl + (local.get $0) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (block $do-once63 + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (block + (if + (i32.ge_u + (local.tee $0 + (i32.load + (local.tee $1 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (block + (local.set $16 + (local.get $1) + ) + (local.set $10 + (local.get $0) + ) + (br $do-once63) + ) + ) + (call $_abort) + ) + (block + (i32.store + (i32.const 176) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (local.set $16 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + (local.set $10 + (local.get $3) + ) + ) + ) + ) + (i32.store + (local.get $16) + (local.get $8) + ) + (i32.store offset=12 + (local.get $10) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $10) + ) + (i32.store offset=12 + (local.get $8) + (local.get $3) + ) + (br $do-once48) + ) + ) + (local.set $3 + (i32.add + (i32.shl + (local.tee $2 + (block $do-once65 (result i32) + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $7) + (i32.const 8) + ) + ) + (block (result i32) + (drop + (br_if $do-once65 + (i32.const 31) + (i32.gt_u + (local.get $7) + (i32.const 16777215) + ) + ) + ) + (i32.or + (i32.and + (i32.shr_u + (local.get $7) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $3 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $3) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $8) + (local.get $2) + ) + (i32.store offset=4 + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + (i32.const 0) + ) + (i32.store + (local.get $0) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (i32.const 180) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $2) + ) + ) + ) + ) + (block + (i32.store + (i32.const 180) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (i32.store + (local.get $3) + (local.get $8) + ) + (i32.store offset=24 + (local.get $8) + (local.get $3) + ) + (i32.store offset=12 + (local.get $8) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $8) + ) + (br $do-once48) + ) + ) + (local.set $2 + (i32.shl + (local.get $7) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $2) + (i32.const 1) + ) + ) + (i32.eq + (local.get $2) + (i32.const 31) + ) + ) + ) + ) + (local.set $0 + (i32.load + (local.get $3) + ) + ) + (block $__rjto$7 + (block $__rjti$7 + (loop $while-in68 + (br_if $__rjti$7 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $7) + ) + ) + (local.set $3 + (i32.shl + (local.get $2) + (i32.const 1) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $2 + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $2) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block + (local.set $2 + (local.get $3) + ) + (local.set $0 + (local.get $1) + ) + (br $while-in68) + ) + ) + ) + (if + (i32.lt_u + (local.get $2) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store + (local.get $2) + (local.get $8) + ) + (i32.store offset=24 + (local.get $8) + (local.get $0) + ) + (i32.store offset=12 + (local.get $8) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $8) + ) + (br $do-once48) + ) + ) + (br $__rjto$7) + ) + (if + (i32.and + (i32.ge_u + (local.tee $2 + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + (local.tee $1 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $0) + (local.get $1) + ) + ) + (block + (i32.store offset=12 + (local.get $2) + (local.get $8) + ) + (i32.store + (local.get $3) + (local.get $8) + ) + (i32.store offset=8 + (local.get $8) + (local.get $2) + ) + (i32.store offset=12 + (local.get $8) + (local.get $0) + ) + (i32.store offset=24 + (local.get $8) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + ) + ) + (return + (i32.add + (local.get $9) + (i32.const 8) + ) + ) + ) + ) + ) + (loop $while-in70 + (block $while-out69 + (if + (i32.le_u + (local.tee $2 + (i32.load + (local.get $4) + ) + ) + (local.get $6) + ) + (br_if $while-out69 + (i32.gt_u + (local.tee $2 + (i32.add + (local.get $2) + (i32.load offset=4 + (local.get $4) + ) + ) + ) + (local.get $6) + ) + ) + ) + (local.set $4 + (i32.load offset=8 + (local.get $4) + ) + ) + (br $while-in70) + ) + ) + (local.set $10 + (i32.add + (local.tee $4 + (i32.add + (local.get $2) + (i32.const -47) + ) + ) + (i32.const 8) + ) + ) + (local.set $12 + (i32.add + (local.tee $11 + (select + (local.get $6) + (local.tee $4 + (i32.add + (local.get $4) + (select + (i32.and + (i32.sub + (i32.const 0) + (local.get $10) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $10) + (i32.const 7) + ) + ) + ) + ) + (i32.lt_u + (local.get $4) + (local.tee $10 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + ) + ) + ) + (i32.const 8) + ) + ) + (i32.store + (i32.const 200) + (local.tee $5 + (i32.add + (local.get $1) + (local.tee $4 + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $4 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $4) + (i32.const 7) + ) + ) + ) + ) + ) + ) + (i32.store + (i32.const 188) + (local.tee $4 + (i32.sub + (i32.add + (local.get $3) + (i32.const -40) + ) + (local.get $4) + ) + ) + ) + (i32.store offset=4 + (local.get $5) + (i32.or + (local.get $4) + (i32.const 1) + ) + ) + (i32.store offset=4 + (i32.add + (local.get $5) + (local.get $4) + ) + (i32.const 40) + ) + (i32.store + (i32.const 204) + (i32.load + (i32.const 664) + ) + ) + (i32.store + (local.tee $4 + (i32.add + (local.get $11) + (i32.const 4) + ) + ) + (i32.const 27) + ) + (i32.store + (local.get $12) + (i32.load + (i32.const 624) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.load + (i32.const 628) + ) + ) + (i32.store offset=8 + (local.get $12) + (i32.load + (i32.const 632) + ) + ) + (i32.store offset=12 + (local.get $12) + (i32.load + (i32.const 636) + ) + ) + (i32.store + (i32.const 624) + (local.get $1) + ) + (i32.store + (i32.const 628) + (local.get $3) + ) + (i32.store + (i32.const 636) + (i32.const 0) + ) + (i32.store + (i32.const 632) + (local.get $12) + ) + (local.set $1 + (i32.add + (local.get $11) + (i32.const 24) + ) + ) + (loop $while-in72 + (i32.store + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.const 7) + ) + (br_if $while-in72 + (i32.lt_u + (i32.add + (local.get $1) + (i32.const 4) + ) + (local.get $2) + ) + ) + ) + (if + (i32.ne + (local.get $11) + (local.get $6) + ) + (block + (i32.store + (local.get $4) + (i32.and + (i32.load + (local.get $4) + ) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $6) + (i32.or + (local.tee $5 + (i32.sub + (local.get $11) + (local.get $6) + ) + ) + (i32.const 1) + ) + ) + (i32.store + (local.get $11) + (local.get $5) + ) + (local.set $1 + (i32.shr_u + (local.get $5) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $5) + (i32.const 256) + ) + (block + (local.set $2 + (i32.add + (i32.shl + (local.get $1) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $3 + (i32.load + (i32.const 176) + ) + ) + (local.tee $1 + (i32.shl + (i32.const 1) + (local.get $1) + ) + ) + ) + (if + (i32.lt_u + (local.tee $1 + (i32.load + (local.tee $3 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (local.set $17 + (local.get $3) + ) + (local.set $7 + (local.get $1) + ) + ) + ) + (block + (i32.store + (i32.const 176) + (i32.or + (local.get $3) + (local.get $1) + ) + ) + (local.set $17 + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (local.set $7 + (local.get $2) + ) + ) + ) + (i32.store + (local.get $17) + (local.get $6) + ) + (i32.store offset=12 + (local.get $7) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $7) + ) + (i32.store offset=12 + (local.get $6) + (local.get $2) + ) + (br $do-once40) + ) + ) + (local.set $2 + (i32.add + (i32.shl + (local.tee $4 + (if (result i32) + (local.tee $1 + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $5) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $5) + (i32.add + (local.tee $1 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $1 + (i32.and + (i32.shr_u + (i32.add + (local.tee $3 + (i32.shl + (local.get $1) + (local.tee $2 + (i32.and + (i32.shr_u + (i32.add + (local.get $1) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $2) + ) + (local.tee $1 + (i32.and + (i32.shr_u + (i32.add + (local.tee $3 + (i32.shl + (local.get $3) + (local.get $1) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $3) + (local.get $1) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $1) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $6) + (local.get $4) + ) + (i32.store offset=20 + (local.get $6) + (i32.const 0) + ) + (i32.store + (local.get $10) + (i32.const 0) + ) + (if + (i32.eqz + (i32.and + (local.tee $3 + (i32.load + (i32.const 180) + ) + ) + (local.tee $1 + (i32.shl + (i32.const 1) + (local.get $4) + ) + ) + ) + ) + (block + (i32.store + (i32.const 180) + (i32.or + (local.get $3) + (local.get $1) + ) + ) + (i32.store + (local.get $2) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $2) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once40) + ) + ) + (local.set $4 + (i32.shl + (local.get $5) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $4) + (i32.const 1) + ) + ) + (i32.eq + (local.get $4) + (i32.const 31) + ) + ) + ) + ) + (local.set $1 + (i32.load + (local.get $2) + ) + ) + (block $__rjto$9 + (block $__rjti$9 + (loop $while-in74 + (br_if $__rjti$9 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $1) + ) + (i32.const -8) + ) + (local.get $5) + ) + ) + (local.set $2 + (i32.shl + (local.get $4) + (i32.const 1) + ) + ) + (if + (local.tee $3 + (i32.load + (local.tee $4 + (i32.add + (i32.add + (local.get $1) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $4) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block + (local.set $4 + (local.get $2) + ) + (local.set $1 + (local.get $3) + ) + (br $while-in74) + ) + ) + ) + (if + (i32.lt_u + (local.get $4) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store + (local.get $4) + (local.get $6) + ) + (i32.store offset=24 + (local.get $6) + (local.get $1) + ) + (i32.store offset=12 + (local.get $6) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $6) + ) + (br $do-once40) + ) + ) + (br $__rjto$9) + ) + (if + (i32.and + (i32.ge_u + (local.tee $4 + (i32.load + (local.tee $2 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + ) + (local.tee $3 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $1) + (local.get $3) + ) + ) + (block + (i32.store offset=12 + (local.get $4) + (local.get $6) + ) + (i32.store + (local.get $2) + (local.get $6) + ) + (i32.store offset=8 + (local.get $6) + (local.get $4) + ) + (i32.store offset=12 + (local.get $6) + (local.get $1) + ) + (i32.store offset=24 + (local.get $6) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + ) + ) + (block + (if + (i32.or + (i32.eqz + (local.tee $2 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.lt_u + (local.get $1) + (local.get $2) + ) + ) + (i32.store + (i32.const 192) + (local.get $1) + ) + ) + (i32.store + (i32.const 624) + (local.get $1) + ) + (i32.store + (i32.const 628) + (local.get $3) + ) + (i32.store + (i32.const 636) + (i32.const 0) + ) + (i32.store + (i32.const 212) + (i32.load + (i32.const 648) + ) + ) + (i32.store + (i32.const 208) + (i32.const -1) + ) + (local.set $2 + (i32.const 0) + ) + (loop $while-in43 + (i32.store offset=12 + (local.tee $4 + (i32.add + (i32.shl + (local.get $2) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (local.get $4) + ) + (i32.store offset=8 + (local.get $4) + (local.get $4) + ) + (br_if $while-in43 + (i32.ne + (local.tee $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (i32.const 32) + ) + ) + ) + (i32.store + (i32.const 200) + (local.tee $2 + (i32.add + (local.get $1) + (local.tee $1 + (select + (i32.and + (i32.sub + (i32.const 0) + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + (i32.const 7) + ) + (i32.const 0) + (i32.and + (local.get $1) + (i32.const 7) + ) + ) + ) + ) + ) + ) + (i32.store + (i32.const 188) + (local.tee $1 + (i32.sub + (i32.add + (local.get $3) + (i32.const -40) + ) + (local.get $1) + ) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $1) + (i32.const 1) + ) + ) + (i32.store offset=4 + (i32.add + (local.get $2) + (local.get $1) + ) + (i32.const 40) + ) + (i32.store + (i32.const 204) + (i32.load + (i32.const 664) + ) + ) + ) + ) + ) + (br_if $folding-inner0 + (i32.gt_u + (local.tee $1 + (i32.load + (i32.const 188) + ) + ) + (local.get $0) + ) + ) + ) + (i32.store + (call $___errno_location) + (i32.const 12) + ) + (return + (i32.const 0) + ) + ) + (i32.store + (i32.const 188) + (local.tee $3 + (i32.sub + (local.get $1) + (local.get $0) + ) + ) + ) + (i32.store + (i32.const 200) + (local.tee $1 + (i32.add + (local.tee $2 + (i32.load + (i32.const 200) + ) + ) + (local.get $0) + ) + ) + ) + (i32.store offset=4 + (local.get $1) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 3) + ) + ) + (i32.add + (local.get $2) + (i32.const 8) + ) + ) + (func $_free (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (local $14 i32) + (local $15 i32) + (if + (i32.eqz + (local.get $0) + ) + (return) + ) + (if + (i32.lt_u + (local.tee $1 + (i32.add + (local.get $0) + (i32.const -8) + ) + ) + (local.tee $11 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (local.tee $5 + (i32.and + (local.tee $7 + (i32.load + (i32.add + (local.get $0) + (i32.const -4) + ) + ) + ) + (i32.const 3) + ) + ) + (i32.const 1) + ) + (call $_abort) + ) + (local.set $8 + (i32.add + (local.get $1) + (local.tee $0 + (i32.and + (local.get $7) + (i32.const -8) + ) + ) + ) + ) + (block $do-once + (if + (i32.and + (local.get $7) + (i32.const 1) + ) + (block + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + (block + (local.set $7 + (i32.load + (local.get $1) + ) + ) + (if + (i32.eqz + (local.get $5) + ) + (return) + ) + (if + (i32.lt_u + (local.tee $1 + (i32.add + (local.get $1) + (i32.sub + (i32.const 0) + (local.get $7) + ) + ) + ) + (local.get $11) + ) + (call $_abort) + ) + (local.set $0 + (i32.add + (local.get $7) + (local.get $0) + ) + ) + (if + (i32.eq + (local.get $1) + (i32.load + (i32.const 196) + ) + ) + (block + (if + (i32.ne + (i32.and + (local.tee $3 + (i32.load + (local.tee $2 + (i32.add + (local.get $8) + (i32.const 4) + ) + ) + ) + ) + (i32.const 3) + ) + (i32.const 3) + ) + (block + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + (i32.store + (i32.const 184) + (local.get $0) + ) + (i32.store + (local.get $2) + (i32.and + (local.get $3) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $1) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $1) + (local.get $0) + ) + (local.get $0) + ) + (return) + ) + ) + (local.set $5 + (i32.shr_u + (local.get $7) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $7) + (i32.const 256) + ) + (block + (local.set $6 + (i32.load offset=12 + (local.get $1) + ) + ) + (if + (i32.ne + (local.tee $2 + (i32.load offset=8 + (local.get $1) + ) + ) + (local.tee $3 + (i32.add + (i32.shl + (local.get $5) + (i32.const 3) + ) + (i32.const 216) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $2) + (local.get $11) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load offset=12 + (local.get $2) + ) + (local.get $1) + ) + (call $_abort) + ) + ) + ) + (if + (i32.eq + (local.get $6) + (local.get $2) + ) + (block + (i32.store + (i32.const 176) + (i32.and + (i32.load + (i32.const 176) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $5) + ) + (i32.const -1) + ) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + (if + (i32.eq + (local.get $6) + (local.get $3) + ) + (local.set $4 + (i32.add + (local.get $6) + (i32.const 8) + ) + ) + (block + (if + (i32.lt_u + (local.get $6) + (local.get $11) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $3 + (i32.add + (local.get $6) + (i32.const 8) + ) + ) + ) + (local.get $1) + ) + (local.set $4 + (local.get $3) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=12 + (local.get $2) + (local.get $6) + ) + (i32.store + (local.get $4) + (local.get $2) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + (local.set $12 + (i32.load offset=24 + (local.get $1) + ) + ) + (block $do-once0 + (if + (i32.eq + (local.tee $4 + (i32.load offset=12 + (local.get $1) + ) + ) + (local.get $1) + ) + (block + (if + (i32.eqz + (local.tee $5 + (i32.load + (local.tee $4 + (i32.add + (local.tee $7 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (if + (local.tee $5 + (i32.load + (local.get $7) + ) + ) + (local.set $4 + (local.get $7) + ) + (block + (local.set $6 + (i32.const 0) + ) + (br $do-once0) + ) + ) + ) + (loop $while-in + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $5) + (i32.const 20) + ) + ) + ) + ) + (block + (local.set $5 + (local.get $7) + ) + (local.set $4 + (local.get $10) + ) + (br $while-in) + ) + ) + (if + (local.tee $7 + (i32.load + (local.tee $10 + (i32.add + (local.get $5) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $5 + (local.get $7) + ) + (local.set $4 + (local.get $10) + ) + (br $while-in) + ) + ) + ) + (if + (i32.lt_u + (local.get $4) + (local.get $11) + ) + (call $_abort) + (block + (i32.store + (local.get $4) + (i32.const 0) + ) + (local.set $6 + (local.get $5) + ) + ) + ) + ) + (block + (if + (i32.lt_u + (local.tee $10 + (i32.load offset=8 + (local.get $1) + ) + ) + (local.get $11) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $7 + (i32.add + (local.get $10) + (i32.const 12) + ) + ) + ) + (local.get $1) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $5 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + (local.get $1) + ) + (block + (i32.store + (local.get $7) + (local.get $4) + ) + (i32.store + (local.get $5) + (local.get $10) + ) + (local.set $6 + (local.get $4) + ) + ) + (call $_abort) + ) + ) + ) + ) + (if + (local.get $12) + (block + (if + (i32.eq + (local.get $1) + (i32.load + (local.tee $4 + (i32.add + (i32.shl + (local.tee $5 + (i32.load offset=28 + (local.get $1) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block + (i32.store + (local.get $4) + (local.get $6) + ) + (if + (i32.eqz + (local.get $6) + ) + (block + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $5) + ) + (i32.const -1) + ) + ) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $12) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $4 + (i32.add + (local.get $12) + (i32.const 16) + ) + ) + ) + (local.get $1) + ) + (i32.store + (local.get $4) + (local.get $6) + ) + (i32.store offset=20 + (local.get $12) + (local.get $6) + ) + ) + (if + (i32.eqz + (local.get $6) + ) + (block + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (br $do-once) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $6) + (local.tee $5 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $6) + (local.get $12) + ) + (if + (local.tee $7 + (i32.load + (local.tee $4 + (i32.add + (local.get $1) + (i32.const 16) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $7) + (local.get $5) + ) + (call $_abort) + (block + (i32.store offset=16 + (local.get $6) + (local.get $7) + ) + (i32.store offset=24 + (local.get $7) + (local.get $6) + ) + ) + ) + ) + (if + (local.tee $4 + (i32.load offset=4 + (local.get $4) + ) + ) + (if + (i32.lt_u + (local.get $4) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store offset=20 + (local.get $6) + (local.get $4) + ) + (i32.store offset=24 + (local.get $4) + (local.get $6) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + (block + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + ) + (block + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ) + ) + ) + ) + ) + (if + (i32.ge_u + (local.get $2) + (local.get $8) + ) + (call $_abort) + ) + (if + (i32.eqz + (i32.and + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 4) + ) + ) + ) + ) + (i32.const 1) + ) + ) + (call $_abort) + ) + (if + (i32.and + (local.get $1) + (i32.const 2) + ) + (block + (i32.store + (local.get $0) + (i32.and + (local.get $1) + (i32.const -2) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $3) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $2) + (local.get $3) + ) + (local.get $3) + ) + ) + (block + (if + (i32.eq + (local.get $8) + (i32.load + (i32.const 200) + ) + ) + (block + (i32.store + (i32.const 188) + (local.tee $0 + (i32.add + (i32.load + (i32.const 188) + ) + (local.get $3) + ) + ) + ) + (i32.store + (i32.const 200) + (local.get $2) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (if + (i32.ne + (local.get $2) + (i32.load + (i32.const 196) + ) + ) + (return) + ) + (i32.store + (i32.const 196) + (i32.const 0) + ) + (i32.store + (i32.const 184) + (i32.const 0) + ) + (return) + ) + ) + (if + (i32.eq + (local.get $8) + (i32.load + (i32.const 196) + ) + ) + (block + (i32.store + (i32.const 184) + (local.tee $0 + (i32.add + (i32.load + (i32.const 184) + ) + (local.get $3) + ) + ) + ) + (i32.store + (i32.const 196) + (local.get $2) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $0) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $2) + (local.get $0) + ) + (local.get $0) + ) + (return) + ) + ) + (local.set $5 + (i32.add + (i32.and + (local.get $1) + (i32.const -8) + ) + (local.get $3) + ) + ) + (local.set $3 + (i32.shr_u + (local.get $1) + (i32.const 3) + ) + ) + (block $do-once4 + (if + (i32.lt_u + (local.get $1) + (i32.const 256) + ) + (block + (local.set $4 + (i32.load offset=12 + (local.get $8) + ) + ) + (if + (i32.ne + (local.tee $1 + (i32.load offset=8 + (local.get $8) + ) + ) + (local.tee $0 + (i32.add + (i32.shl + (local.get $3) + (i32.const 3) + ) + (i32.const 216) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $1) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load offset=12 + (local.get $1) + ) + (local.get $8) + ) + (call $_abort) + ) + ) + ) + (if + (i32.eq + (local.get $4) + (local.get $1) + ) + (block + (i32.store + (i32.const 176) + (i32.and + (i32.load + (i32.const 176) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $3) + ) + (i32.const -1) + ) + ) + ) + (br $do-once4) + ) + ) + (if + (i32.eq + (local.get $4) + (local.get $0) + ) + (local.set $14 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + (block + (if + (i32.lt_u + (local.get $4) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $4) + (i32.const 8) + ) + ) + ) + (local.get $8) + ) + (local.set $14 + (local.get $0) + ) + (call $_abort) + ) + ) + ) + (i32.store offset=12 + (local.get $1) + (local.get $4) + ) + (i32.store + (local.get $14) + (local.get $1) + ) + ) + (block + (local.set $6 + (i32.load offset=24 + (local.get $8) + ) + ) + (block $do-once6 + (if + (i32.eq + (local.tee $0 + (i32.load offset=12 + (local.get $8) + ) + ) + (local.get $8) + ) + (block + (if + (i32.eqz + (local.tee $3 + (i32.load + (local.tee $0 + (i32.add + (local.tee $1 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + (i32.const 4) + ) + ) + ) + ) + ) + (if + (local.tee $3 + (i32.load + (local.get $1) + ) + ) + (local.set $0 + (local.get $1) + ) + (block + (local.set $9 + (i32.const 0) + ) + (br $do-once6) + ) + ) + ) + (loop $while-in9 + (if + (local.tee $1 + (i32.load + (local.tee $4 + (i32.add + (local.get $3) + (i32.const 20) + ) + ) + ) + ) + (block + (local.set $3 + (local.get $1) + ) + (local.set $0 + (local.get $4) + ) + (br $while-in9) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $4 + (i32.add + (local.get $3) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $3 + (local.get $1) + ) + (local.set $0 + (local.get $4) + ) + (br $while-in9) + ) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store + (local.get $0) + (i32.const 0) + ) + (local.set $9 + (local.get $3) + ) + ) + ) + ) + (block + (if + (i32.lt_u + (local.tee $4 + (i32.load offset=8 + (local.get $8) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.ne + (i32.load + (local.tee $1 + (i32.add + (local.get $4) + (i32.const 12) + ) + ) + ) + (local.get $8) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $3 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + (local.get $8) + ) + (block + (i32.store + (local.get $1) + (local.get $0) + ) + (i32.store + (local.get $3) + (local.get $4) + ) + (local.set $9 + (local.get $0) + ) + ) + (call $_abort) + ) + ) + ) + ) + (if + (local.get $6) + (block + (if + (i32.eq + (local.get $8) + (i32.load + (local.tee $0 + (i32.add + (i32.shl + (local.tee $3 + (i32.load offset=28 + (local.get $8) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + ) + ) + (block + (i32.store + (local.get $0) + (local.get $9) + ) + (if + (i32.eqz + (local.get $9) + ) + (block + (i32.store + (i32.const 180) + (i32.and + (i32.load + (i32.const 180) + ) + (i32.xor + (i32.shl + (i32.const 1) + (local.get $3) + ) + (i32.const -1) + ) + ) + ) + (br $do-once4) + ) + ) + ) + (block + (if + (i32.lt_u + (local.get $6) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + ) + (if + (i32.eq + (i32.load + (local.tee $0 + (i32.add + (local.get $6) + (i32.const 16) + ) + ) + ) + (local.get $8) + ) + (i32.store + (local.get $0) + (local.get $9) + ) + (i32.store offset=20 + (local.get $6) + (local.get $9) + ) + ) + (br_if $do-once4 + (i32.eqz + (local.get $9) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $9) + (local.tee $3 + (i32.load + (i32.const 192) + ) + ) + ) + (call $_abort) + ) + (i32.store offset=24 + (local.get $9) + (local.get $6) + ) + (if + (local.tee $1 + (i32.load + (local.tee $0 + (i32.add + (local.get $8) + (i32.const 16) + ) + ) + ) + ) + (if + (i32.lt_u + (local.get $1) + (local.get $3) + ) + (call $_abort) + (block + (i32.store offset=16 + (local.get $9) + (local.get $1) + ) + (i32.store offset=24 + (local.get $1) + (local.get $9) + ) + ) + ) + ) + (if + (local.tee $0 + (i32.load offset=4 + (local.get $0) + ) + ) + (if + (i32.lt_u + (local.get $0) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store offset=20 + (local.get $9) + (local.get $0) + ) + (i32.store offset=24 + (local.get $0) + (local.get $9) + ) + ) + ) + ) + ) + ) + ) + ) + ) + (i32.store offset=4 + (local.get $2) + (i32.or + (local.get $5) + (i32.const 1) + ) + ) + (i32.store + (i32.add + (local.get $2) + (local.get $5) + ) + (local.get $5) + ) + (if + (i32.eq + (local.get $2) + (i32.load + (i32.const 196) + ) + ) + (block + (i32.store + (i32.const 184) + (local.get $5) + ) + (return) + ) + (local.set $3 + (local.get $5) + ) + ) + ) + ) + (local.set $0 + (i32.shr_u + (local.get $3) + (i32.const 3) + ) + ) + (if + (i32.lt_u + (local.get $3) + (i32.const 256) + ) + (block + (local.set $1 + (i32.add + (i32.shl + (local.get $0) + (i32.const 3) + ) + (i32.const 216) + ) + ) + (if + (i32.and + (local.tee $3 + (i32.load + (i32.const 176) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $0) + ) + ) + ) + (if + (i32.lt_u + (local.tee $0 + (i32.load + (local.tee $3 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + ) + ) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (local.set $15 + (local.get $3) + ) + (local.set $13 + (local.get $0) + ) + ) + ) + (block + (i32.store + (i32.const 176) + (i32.or + (local.get $3) + (local.get $0) + ) + ) + (local.set $15 + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (local.set $13 + (local.get $1) + ) + ) + ) + (i32.store + (local.get $15) + (local.get $2) + ) + (i32.store offset=12 + (local.get $13) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $13) + ) + (i32.store offset=12 + (local.get $2) + (local.get $1) + ) + (return) + ) + ) + (local.set $4 + (i32.add + (i32.shl + (local.tee $5 + (if (result i32) + (local.tee $0 + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (if (result i32) + (i32.gt_u + (local.get $3) + (i32.const 16777215) + ) + (i32.const 31) + (i32.or + (i32.and + (i32.shr_u + (local.get $3) + (i32.add + (local.tee $0 + (i32.add + (i32.sub + (i32.const 14) + (i32.or + (i32.or + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $0) + (local.tee $4 + (i32.and + (i32.shr_u + (i32.add + (local.get $0) + (i32.const 1048320) + ) + (i32.const 16) + ) + (i32.const 8) + ) + ) + ) + ) + (i32.const 520192) + ) + (i32.const 16) + ) + (i32.const 4) + ) + ) + (local.get $4) + ) + (local.tee $0 + (i32.and + (i32.shr_u + (i32.add + (local.tee $1 + (i32.shl + (local.get $1) + (local.get $0) + ) + ) + (i32.const 245760) + ) + (i32.const 16) + ) + (i32.const 2) + ) + ) + ) + ) + (i32.shr_u + (i32.shl + (local.get $1) + (local.get $0) + ) + (i32.const 15) + ) + ) + ) + (i32.const 7) + ) + ) + (i32.const 1) + ) + (i32.shl + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 0) + ) + ) + (i32.const 2) + ) + (i32.const 480) + ) + ) + (i32.store offset=28 + (local.get $2) + (local.get $5) + ) + (i32.store offset=20 + (local.get $2) + (i32.const 0) + ) + (i32.store offset=16 + (local.get $2) + (i32.const 0) + ) + (block $do-once12 + (if + (i32.and + (local.tee $1 + (i32.load + (i32.const 180) + ) + ) + (local.tee $0 + (i32.shl + (i32.const 1) + (local.get $5) + ) + ) + ) + (block + (local.set $5 + (i32.shl + (local.get $3) + (select + (i32.const 0) + (i32.sub + (i32.const 25) + (i32.shr_u + (local.get $5) + (i32.const 1) + ) + ) + (i32.eq + (local.get $5) + (i32.const 31) + ) + ) + ) + ) + (local.set $0 + (i32.load + (local.get $4) + ) + ) + (block $__rjto$1 + (block $__rjti$1 + (loop $while-in15 + (br_if $__rjti$1 + (i32.eq + (i32.and + (i32.load offset=4 + (local.get $0) + ) + (i32.const -8) + ) + (local.get $3) + ) + ) + (local.set $4 + (i32.shl + (local.get $5) + (i32.const 1) + ) + ) + (if + (local.tee $1 + (i32.load + (local.tee $5 + (i32.add + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.shl + (i32.shr_u + (local.get $5) + (i32.const 31) + ) + (i32.const 2) + ) + ) + ) + ) + ) + (block + (local.set $5 + (local.get $4) + ) + (local.set $0 + (local.get $1) + ) + (br $while-in15) + ) + ) + ) + (if + (i32.lt_u + (local.get $5) + (i32.load + (i32.const 192) + ) + ) + (call $_abort) + (block + (i32.store + (local.get $5) + (local.get $2) + ) + (i32.store offset=24 + (local.get $2) + (local.get $0) + ) + (i32.store offset=12 + (local.get $2) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $2) + ) + (br $do-once12) + ) + ) + (br $__rjto$1) + ) + (if + (i32.and + (i32.ge_u + (local.tee $4 + (i32.load + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 8) + ) + ) + ) + ) + (local.tee $3 + (i32.load + (i32.const 192) + ) + ) + ) + (i32.ge_u + (local.get $0) + (local.get $3) + ) + ) + (block + (i32.store offset=12 + (local.get $4) + (local.get $2) + ) + (i32.store + (local.get $1) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $4) + ) + (i32.store offset=12 + (local.get $2) + (local.get $0) + ) + (i32.store offset=24 + (local.get $2) + (i32.const 0) + ) + ) + (call $_abort) + ) + ) + ) + (block + (i32.store + (i32.const 180) + (i32.or + (local.get $1) + (local.get $0) + ) + ) + (i32.store + (local.get $4) + (local.get $2) + ) + (i32.store offset=24 + (local.get $2) + (local.get $4) + ) + (i32.store offset=12 + (local.get $2) + (local.get $2) + ) + (i32.store offset=8 + (local.get $2) + (local.get $2) + ) + ) + ) + ) + (i32.store + (i32.const 208) + (local.tee $0 + (i32.add + (i32.load + (i32.const 208) + ) + (i32.const -1) + ) + ) + ) + (if + (local.get $0) + (return) + (local.set $0 + (i32.const 632) + ) + ) + (loop $while-in17 + (local.set $0 + (i32.add + (local.tee $3 + (i32.load + (local.get $0) + ) + ) + (i32.const 8) + ) + ) + (br_if $while-in17 + (local.get $3) + ) + ) + (i32.store + (i32.const 208) + (i32.const -1) + ) + ) + (func $runPostSets + (nop) + ) + (func $_i64Subtract (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (global.set $tempRet0 + (i32.sub + (i32.sub + (local.get $1) + (local.get $3) + ) + (i32.gt_u + (local.get $2) + (local.get $0) + ) + ) + ) + (i32.sub + (local.get $0) + (local.get $2) + ) + ) + (func $_i64Add (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local $4 i32) + (global.set $tempRet0 + (i32.add + (i32.add + (local.get $1) + (local.get $3) + ) + (i32.lt_u + (local.tee $4 + (i32.add + (local.get $0) + (local.get $2) + ) + ) + (local.get $0) + ) + ) + ) + (local.get $4) + ) + (func $_memset (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $4 + (i32.add + (local.get $0) + (local.get $2) + ) + ) + (if + (i32.ge_s + (local.get $2) + (i32.const 20) + ) + (block + (local.set $1 + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + (if + (local.tee $3 + (i32.and + (local.get $0) + (i32.const 3) + ) + ) + (block + (local.set $3 + (i32.sub + (i32.add + (local.get $0) + (i32.const 4) + ) + (local.get $3) + ) + ) + (loop $while-in + (if + (i32.lt_s + (local.get $0) + (local.get $3) + ) + (block + (i32.store8 + (local.get $0) + (local.get $1) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (br $while-in) + ) + ) + ) + ) + ) + (local.set $3 + (i32.or + (i32.or + (i32.or + (local.get $1) + (i32.shl + (local.get $1) + (i32.const 8) + ) + ) + (i32.shl + (local.get $1) + (i32.const 16) + ) + ) + (i32.shl + (local.get $1) + (i32.const 24) + ) + ) + ) + (local.set $5 + (i32.and + (local.get $4) + (i32.const -4) + ) + ) + (loop $while-in1 + (if + (i32.lt_s + (local.get $0) + (local.get $5) + ) + (block + (i32.store + (local.get $0) + (local.get $3) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (br $while-in1) + ) + ) + ) + ) + ) + (loop $while-in3 + (if + (i32.lt_s + (local.get $0) + (local.get $4) + ) + (block + (i32.store8 + (local.get $0) + (local.get $1) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (br $while-in3) + ) + ) + ) + (i32.sub + (local.get $0) + (local.get $2) + ) + ) + (func $_bitshift64Lshr (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (if + (i32.lt_s + (local.get $2) + (i32.const 32) + ) + (block + (global.set $tempRet0 + (i32.shr_u + (local.get $1) + (local.get $2) + ) + ) + (return + (i32.or + (i32.shr_u + (local.get $0) + (local.get $2) + ) + (i32.shl + (i32.and + (local.get $1) + (i32.sub + (i32.shl + (i32.const 1) + (local.get $2) + ) + (i32.const 1) + ) + ) + (i32.sub + (i32.const 32) + (local.get $2) + ) + ) + ) + ) + ) + ) + (global.set $tempRet0 + (i32.const 0) + ) + (i32.shr_u + (local.get $1) + (i32.sub + (local.get $2) + (i32.const 32) + ) + ) + ) + (func $_bitshift64Shl (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (if + (i32.lt_s + (local.get $2) + (i32.const 32) + ) + (block + (global.set $tempRet0 + (i32.or + (i32.shl + (local.get $1) + (local.get $2) + ) + (i32.shr_u + (i32.and + (local.get $0) + (i32.shl + (i32.sub + (i32.shl + (i32.const 1) + (local.get $2) + ) + (i32.const 1) + ) + (i32.sub + (i32.const 32) + (local.get $2) + ) + ) + ) + (i32.sub + (i32.const 32) + (local.get $2) + ) + ) + ) + ) + (return + (i32.shl + (local.get $0) + (local.get $2) + ) + ) + ) + ) + (global.set $tempRet0 + (i32.shl + (local.get $0) + (i32.sub + (local.get $2) + (i32.const 32) + ) + ) + ) + (i32.const 0) + ) + (func $_memcpy (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (local $3 i32) + (if + (i32.ge_s + (local.get $2) + (i32.const 4096) + ) + (return + (call $_emscripten_memcpy_big + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + ) + (local.set $3 + (local.get $0) + ) + (if + (i32.eq + (i32.and + (local.get $0) + (i32.const 3) + ) + (i32.and + (local.get $1) + (i32.const 3) + ) + ) + (block + (loop $while-in + (if + (i32.and + (local.get $0) + (i32.const 3) + ) + (block + (if + (i32.eqz + (local.get $2) + ) + (return + (local.get $3) + ) + ) + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (br $while-in) + ) + ) + ) + (loop $while-in1 + (if + (i32.ge_s + (local.get $2) + (i32.const 4) + ) + (block + (i32.store + (local.get $0) + (i32.load + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 4) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 4) + ) + ) + (br $while-in1) + ) + ) + ) + ) + ) + (loop $while-in3 + (if + (i32.gt_s + (local.get $2) + (i32.const 0) + ) + (block + (i32.store8 + (local.get $0) + (i32.load8_s + (local.get $1) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 1) + ) + ) + (br $while-in3) + ) + ) + ) + (local.get $3) + ) + (func $___udivdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (call $___udivmoddi4 + (local.get $0) + (local.get $1) + (local.get $2) + (local.get $3) + (i32.const 0) + ) + ) + (func $___uremdi3 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (local $4 i32) + (local.set $4 + (global.get $STACKTOP) + ) + (global.set $STACKTOP + (i32.add + (global.get $STACKTOP) + (i32.const 16) + ) + ) + (drop + (call $___udivmoddi4 + (local.get $0) + (local.get $1) + (local.get $2) + (local.get $3) + (local.tee $0 + (local.get $4) + ) + ) + ) + (global.set $STACKTOP + (local.get $4) + ) + (global.set $tempRet0 + (i32.load offset=4 + (local.get $0) + ) + ) + (i32.load + (local.get $0) + ) + ) + (func $___udivmoddi4 (param $xl i32) (param $xh i32) (param $yl i32) (param $yh i32) (param $r i32) (result i32) + (local $x64 i64) + (local $y64 i64) + (local.set $x64 + (i64.or + (i64.extend_i32_u + (local.get $xl) + ) + (i64.shl + (i64.extend_i32_u + (local.get $xh) + ) + (i64.const 32) + ) + ) + ) + (local.set $y64 + (i64.or + (i64.extend_i32_u + (local.get $yl) + ) + (i64.shl + (i64.extend_i32_u + (local.get $yh) + ) + (i64.const 32) + ) + ) + ) + (if + (local.get $r) + (i64.store + (local.get $r) + (i64.rem_u + (local.get $x64) + (local.get $y64) + ) + ) + ) + (local.set $x64 + (i64.div_u + (local.get $x64) + (local.get $y64) + ) + ) + (global.set $tempRet0 + (i32.wrap_i64 + (i64.shr_u + (local.get $x64) + (i64.const 32) + ) + ) + ) + (i32.wrap_i64 + (local.get $x64) + ) + ) + (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) + (call_indirect (type $FUNCSIG$ii) + (local.get $1) + (i32.and + (local.get $0) + (i32.const 1) + ) + ) + ) + (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (call_indirect (type $FUNCSIG$iiii) + (local.get $1) + (local.get $2) + (local.get $3) + (i32.add + (i32.and + (local.get $0) + (i32.const 7) + ) + (i32.const 2) + ) + ) + ) + (func $dynCall_vi (param $0 i32) (param $1 i32) + (call_indirect (type $FUNCSIG$vi) + (local.get $1) + (i32.add + (i32.and + (local.get $0) + (i32.const 7) + ) + (i32.const 10) + ) + ) + ) + (func $b0 (param $0 i32) (result i32) + (call $nullFunc_ii + (i32.const 0) + ) + (i32.const 0) + ) + (func $b1 (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (call $nullFunc_iiii + (i32.const 1) + ) + (i32.const 0) + ) + (func $b2 (param $0 i32) + (call $nullFunc_vi + (i32.const 2) + ) + ) +) diff -Nru binaryen-108/test/passes/instrument-locals_all-features_disable-typed-function-references.txt binaryen-99/test/passes/instrument-locals_all-features_disable-typed-function-references.txt --- binaryen-108/test/passes/instrument-locals_all-features_disable-typed-function-references.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-locals_all-features_disable-typed-function-references.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,286 @@ +(module + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_i32_i64_=>_i64 (func (param i32 i32 i64) (result i64))) + (type $i32_i32_f32_=>_f32 (func (param i32 i32 f32) (result f32))) + (type $i32_i32_f64_=>_f64 (func (param i32 i32 f64) (result f64))) + (type $i32_i32_v128_=>_v128 (func (param i32 i32 v128) (result v128))) + (type $i32_i32_funcref_=>_funcref (func (param i32 i32 funcref) (result funcref))) + (type $i32_i32_externref_=>_externref (func (param i32 i32 externref) (result externref))) + (type $i32_i32_exnref_=>_exnref (func (param i32 i32 exnref) (result exnref))) + (type $i32_i32_anyref_=>_anyref (func (param i32 i32 anyref) (result anyref))) + (type $i32_i32_eqref_=>_eqref (func (param i32 i32 eqref) (result eqref))) + (type $i32_i32_i31ref_=>_i31ref (func (param i32 i32 i31ref) (result i31ref))) + (type $none_=>_none (func)) + (import "env" "get_i32" (func $get_i32 (param i32 i32 i32) (result i32))) + (import "env" "get_i64" (func $get_i64 (param i32 i32 i64) (result i64))) + (import "env" "get_f32" (func $get_f32 (param i32 i32 f32) (result f32))) + (import "env" "get_f64" (func $get_f64 (param i32 i32 f64) (result f64))) + (import "env" "set_i32" (func $set_i32 (param i32 i32 i32) (result i32))) + (import "env" "set_i64" (func $set_i64 (param i32 i32 i64) (result i64))) + (import "env" "set_f32" (func $set_f32 (param i32 i32 f32) (result f32))) + (import "env" "set_f64" (func $set_f64 (param i32 i32 f64) (result f64))) + (import "env" "get_funcref" (func $get_funcref (param i32 i32 funcref) (result funcref))) + (import "env" "set_funcref" (func $set_funcref (param i32 i32 funcref) (result funcref))) + (import "env" "get_externref" (func $get_externref (param i32 i32 externref) (result externref))) + (import "env" "set_externref" (func $set_externref (param i32 i32 externref) (result externref))) + (import "env" "get_exnref" (func $get_exnref (param i32 i32 exnref) (result exnref))) + (import "env" "set_exnref" (func $set_exnref (param i32 i32 exnref) (result exnref))) + (import "env" "get_anyref" (func $get_anyref (param i32 i32 anyref) (result anyref))) + (import "env" "set_anyref" (func $set_anyref (param i32 i32 anyref) (result anyref))) + (import "env" "get_eqref" (func $get_eqref (param i32 i32 eqref) (result eqref))) + (import "env" "set_eqref" (func $set_eqref (param i32 i32 eqref) (result eqref))) + (import "env" "get_i31ref" (func $get_i31ref (param i32 i32 i31ref) (result i31ref))) + (import "env" "set_i31ref" (func $set_i31ref (param i32 i32 i31ref) (result i31ref))) + (import "env" "get_v128" (func $get_v128 (param i32 i32 v128) (result v128))) + (import "env" "set_v128" (func $set_v128 (param i32 i32 v128) (result v128))) + (func $test + (local $x i32) + (local $y i64) + (local $z f32) + (local $w f64) + (local $F funcref) + (local $X externref) + (local $E exnref) + (local $S v128) + (drop + (call $get_i32 + (i32.const 0) + (i32.const 0) + (local.get $x) + ) + ) + (drop + (local.get $y) + ) + (drop + (call $get_f32 + (i32.const 1) + (i32.const 2) + (local.get $z) + ) + ) + (drop + (call $get_f64 + (i32.const 2) + (i32.const 3) + (local.get $w) + ) + ) + (drop + (call $get_funcref + (i32.const 3) + (i32.const 4) + (local.get $F) + ) + ) + (drop + (call $get_externref + (i32.const 4) + (i32.const 5) + (local.get $X) + ) + ) + (drop + (call $get_exnref + (i32.const 5) + (i32.const 6) + (local.get $E) + ) + ) + (drop + (call $get_i32 + (i32.const 6) + (i32.const 0) + (local.get $x) + ) + ) + (drop + (local.get $y) + ) + (drop + (call $get_f32 + (i32.const 7) + (i32.const 2) + (local.get $z) + ) + ) + (drop + (call $get_f64 + (i32.const 8) + (i32.const 3) + (local.get $w) + ) + ) + (drop + (call $get_funcref + (i32.const 9) + (i32.const 4) + (local.get $F) + ) + ) + (drop + (call $get_externref + (i32.const 10) + (i32.const 5) + (local.get $X) + ) + ) + (drop + (call $get_exnref + (i32.const 11) + (i32.const 6) + (local.get $E) + ) + ) + (local.set $x + (call $set_i32 + (i32.const 12) + (i32.const 0) + (i32.const 1) + ) + ) + (local.set $y + (i64.const 2) + ) + (local.set $z + (call $set_f32 + (i32.const 13) + (i32.const 2) + (f32.const 3.2100000381469727) + ) + ) + (local.set $w + (call $set_f64 + (i32.const 14) + (i32.const 3) + (f64.const 4.321) + ) + ) + (local.set $F + (ref.func $test) + ) + (local.set $X + (call $set_externref + (i32.const 16) + (i32.const 5) + (call $get_externref + (i32.const 15) + (i32.const 5) + (local.get $X) + ) + ) + ) + (local.set $E + (call $set_exnref + (i32.const 18) + (i32.const 6) + (call $get_exnref + (i32.const 17) + (i32.const 6) + (local.get $E) + ) + ) + ) + (local.set $x + (call $set_i32 + (i32.const 19) + (i32.const 0) + (i32.const 11) + ) + ) + (local.set $y + (i64.const 22) + ) + (local.set $z + (call $set_f32 + (i32.const 20) + (i32.const 2) + (f32.const 33.209999084472656) + ) + ) + (local.set $w + (call $set_f64 + (i32.const 21) + (i32.const 3) + (f64.const 44.321) + ) + ) + (local.set $F + (call $set_funcref + (i32.const 23) + (i32.const 4) + (call $get_funcref + (i32.const 22) + (i32.const 4) + (local.get $F) + ) + ) + ) + (local.set $X + (call $set_externref + (i32.const 25) + (i32.const 5) + (call $get_externref + (i32.const 24) + (i32.const 5) + (local.get $X) + ) + ) + ) + (local.set $E + (call $set_exnref + (i32.const 27) + (i32.const 6) + (call $get_exnref + (i32.const 26) + (i32.const 6) + (local.get $E) + ) + ) + ) + (try + (do + (nop) + ) + (catch + (local.set $F + (pop funcref) + ) + ) + ) + (try + (do + (nop) + ) + (catch + (local.set $X + (pop externref) + ) + ) + ) + (try + (do + (nop) + ) + (catch + (local.set $E + (pop exnref) + ) + ) + ) + (drop + (call $get_v128 + (i32.const 28) + (i32.const 7) + (local.get $S) + ) + ) + (local.set $S + (call $set_v128 + (i32.const 29) + (i32.const 7) + (v128.const i32x4 0x00000000 0x00000001 0x00000002 0x00000003) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/instrument-locals_all-features_disable-typed-function-references.wast binaryen-99/test/passes/instrument-locals_all-features_disable-typed-function-references.wast --- binaryen-108/test/passes/instrument-locals_all-features_disable-typed-function-references.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-locals_all-features_disable-typed-function-references.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,69 @@ +(module + (func $test + (local $x i32) + (local $y i64) + (local $z f32) + (local $w f64) + (local $F funcref) + (local $X externref) + (local $E exnref) + (local $S v128) + + (drop (local.get $x)) + (drop (local.get $y)) + (drop (local.get $z)) + (drop (local.get $w)) + (drop (local.get $F)) + (drop (local.get $X)) + (drop (local.get $E)) + + (drop (local.get $x)) + (drop (local.get $y)) + (drop (local.get $z)) + (drop (local.get $w)) + (drop (local.get $F)) + (drop (local.get $X)) + (drop (local.get $E)) + + (local.set $x (i32.const 1)) + (local.set $y (i64.const 2)) + (local.set $z (f32.const 3.21)) + (local.set $w (f64.const 4.321)) + (local.set $F (ref.func $test)) + (local.set $X (local.get $X)) + (local.set $E (local.get $E)) + + (local.set $x (i32.const 11)) + (local.set $y (i64.const 22)) + (local.set $z (f32.const 33.21)) + (local.set $w (f64.const 44.321)) + (local.set $F (local.get $F)) + (local.set $X (local.get $X)) + (local.set $E (local.get $E)) + + ;; Pop instructions should not be instrumented + (try + (do) + (catch + (local.set $F (pop funcref)) + ) + ) + (try + (do) + (catch + (local.set $X (pop externref)) + ) + ) + (try + (do) + (catch + (local.set $E (pop exnref)) + ) + ) + + ;; Add new instructions here so expected output doesn't change too much, it + ;; depends on order of instructions in this file. + (drop (local.get $S)) + (local.set $S (v128.const i32x4 0x00000000 0x00000001 0x00000002 0x00000003)) + ) +) diff -Nru binaryen-108/test/passes/instrument-memory64.passes binaryen-99/test/passes/instrument-memory64.passes --- binaryen-108/test/passes/instrument-memory64.passes 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-memory64.passes 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +instrument-memory_enable-memory64 diff -Nru binaryen-108/test/passes/instrument-memory64.txt binaryen-99/test/passes/instrument-memory64.txt --- binaryen-108/test/passes/instrument-memory64.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-memory64.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,603 @@ +(module + (type $none_=>_none (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i64_i64_=>_i64 (func (param i32 i32 i64 i64) (result i64))) + (type $i32_i64_=>_i64 (func (param i32 i64) (result i64))) + (type $i32_f32_=>_f32 (func (param i32 f32) (result f32))) + (type $i32_f64_=>_f64 (func (param i32 f64) (result f64))) + (import "env" "load_ptr" (func $load_ptr (param i32 i32 i64 i64) (result i64))) + (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) + (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) + (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) + (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) + (import "env" "store_ptr" (func $store_ptr (param i32 i32 i64 i64) (result i64))) + (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) + (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) + (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) + (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) + (memory $0 i64 256 256) + (func $A + (drop + (call $load_val_i32 + (i32.const 1) + (i32.load8_s + (call $load_ptr + (i32.const 1) + (i32.const 1) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 2) + (i32.load8_u + (call $load_ptr + (i32.const 2) + (i32.const 1) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 3) + (i32.load16_s + (call $load_ptr + (i32.const 3) + (i32.const 2) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 4) + (i32.load16_u + (call $load_ptr + (i32.const 4) + (i32.const 2) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 5) + (i32.load + (call $load_ptr + (i32.const 5) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 6) + (i64.load8_s + (call $load_ptr + (i32.const 6) + (i32.const 1) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 7) + (i64.load8_u + (call $load_ptr + (i32.const 7) + (i32.const 1) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 8) + (i64.load16_s + (call $load_ptr + (i32.const 8) + (i32.const 2) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 9) + (i64.load16_u + (call $load_ptr + (i32.const 9) + (i32.const 2) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 10) + (i64.load32_s + (call $load_ptr + (i32.const 10) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 11) + (i64.load32_u + (call $load_ptr + (i32.const 11) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 12) + (i64.load + (call $load_ptr + (i32.const 12) + (i32.const 8) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f32 + (i32.const 13) + (f32.load + (call $load_ptr + (i32.const 13) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f64 + (i32.const 14) + (f64.load + (call $load_ptr + (i32.const 14) + (i32.const 8) + (i64.const 0) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 15) + (i32.load8_s offset=1 + (call $load_ptr + (i32.const 15) + (i32.const 1) + (i64.const 1) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 16) + (i32.load8_u offset=2 + (call $load_ptr + (i32.const 16) + (i32.const 1) + (i64.const 2) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 17) + (i32.load16_s offset=3 align=1 + (call $load_ptr + (i32.const 17) + (i32.const 2) + (i64.const 3) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 18) + (i32.load16_u offset=4 align=1 + (call $load_ptr + (i32.const 18) + (i32.const 2) + (i64.const 4) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 19) + (i32.load offset=5 align=2 + (call $load_ptr + (i32.const 19) + (i32.const 4) + (i64.const 5) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 20) + (i64.load8_s offset=6 + (call $load_ptr + (i32.const 20) + (i32.const 1) + (i64.const 6) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 21) + (i64.load8_u offset=7 + (call $load_ptr + (i32.const 21) + (i32.const 1) + (i64.const 7) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 22) + (i64.load16_s offset=8 align=1 + (call $load_ptr + (i32.const 22) + (i32.const 2) + (i64.const 8) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 23) + (i64.load16_u offset=9 align=1 + (call $load_ptr + (i32.const 23) + (i32.const 2) + (i64.const 9) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 24) + (i64.load32_s offset=10 align=2 + (call $load_ptr + (i32.const 24) + (i32.const 4) + (i64.const 10) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 25) + (i64.load32_u offset=11 align=2 + (call $load_ptr + (i32.const 25) + (i32.const 4) + (i64.const 11) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 26) + (i64.load offset=12 align=2 + (call $load_ptr + (i32.const 26) + (i32.const 8) + (i64.const 12) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f32 + (i32.const 27) + (f32.load offset=13 align=2 + (call $load_ptr + (i32.const 27) + (i32.const 4) + (i64.const 13) + (i64.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f64 + (i32.const 28) + (f64.load offset=14 align=2 + (call $load_ptr + (i32.const 28) + (i32.const 8) + (i64.const 14) + (i64.const 0) + ) + ) + ) + ) + ) + (func $B + (i32.store8 + (call $store_ptr + (i32.const 29) + (i32.const 1) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i32 + (i32.const 29) + (i32.const 1) + ) + ) + (i32.store16 + (call $store_ptr + (i32.const 30) + (i32.const 2) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i32 + (i32.const 30) + (i32.const 2) + ) + ) + (i32.store + (call $store_ptr + (i32.const 31) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i32 + (i32.const 31) + (i32.const 3) + ) + ) + (i64.store8 + (call $store_ptr + (i32.const 32) + (i32.const 1) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 32) + (i64.const 4) + ) + ) + (i64.store16 + (call $store_ptr + (i32.const 33) + (i32.const 2) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 33) + (i64.const 5) + ) + ) + (i64.store32 + (call $store_ptr + (i32.const 34) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 34) + (i64.const 6) + ) + ) + (i64.store + (call $store_ptr + (i32.const 35) + (i32.const 8) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 35) + (i64.const 7) + ) + ) + (f32.store + (call $store_ptr + (i32.const 36) + (i32.const 4) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_f32 + (i32.const 36) + (f32.const 8) + ) + ) + (f64.store + (call $store_ptr + (i32.const 37) + (i32.const 8) + (i64.const 0) + (i64.const 0) + ) + (call $store_val_f64 + (i32.const 37) + (f64.const 9) + ) + ) + (i32.store8 offset=1 + (call $store_ptr + (i32.const 38) + (i32.const 1) + (i64.const 1) + (i64.const 0) + ) + (call $store_val_i32 + (i32.const 38) + (i32.const 1) + ) + ) + (i32.store16 offset=2 align=1 + (call $store_ptr + (i32.const 39) + (i32.const 2) + (i64.const 2) + (i64.const 0) + ) + (call $store_val_i32 + (i32.const 39) + (i32.const 2) + ) + ) + (i32.store offset=3 align=2 + (call $store_ptr + (i32.const 40) + (i32.const 4) + (i64.const 3) + (i64.const 0) + ) + (call $store_val_i32 + (i32.const 40) + (i32.const 3) + ) + ) + (i64.store8 offset=4 + (call $store_ptr + (i32.const 41) + (i32.const 1) + (i64.const 4) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 41) + (i64.const 4) + ) + ) + (i64.store16 offset=5 + (call $store_ptr + (i32.const 42) + (i32.const 2) + (i64.const 5) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 42) + (i64.const 5) + ) + ) + (i64.store32 offset=6 align=2 + (call $store_ptr + (i32.const 43) + (i32.const 4) + (i64.const 6) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 43) + (i64.const 6) + ) + ) + (i64.store offset=7 align=2 + (call $store_ptr + (i32.const 44) + (i32.const 8) + (i64.const 7) + (i64.const 0) + ) + (call $store_val_i64 + (i32.const 44) + (i64.const 7) + ) + ) + (f32.store offset=8 align=2 + (call $store_ptr + (i32.const 45) + (i32.const 4) + (i64.const 8) + (i64.const 0) + ) + (call $store_val_f32 + (i32.const 45) + (f32.const 8) + ) + ) + (f64.store offset=9 align=2 + (call $store_ptr + (i32.const 46) + (i32.const 8) + (i64.const 9) + (i64.const 0) + ) + (call $store_val_f64 + (i32.const 46) + (f64.const 9) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/instrument-memory64.wast binaryen-99/test/passes/instrument-memory64.wast --- binaryen-108/test/passes/instrument-memory64.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-memory64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,57 @@ +(module + (memory i64 256 256) + (type $1 (func)) + (func $A (type $1) + (drop (i32.load8_s (i64.const 0))) + (drop (i32.load8_u (i64.const 0))) + (drop (i32.load16_s (i64.const 0))) + (drop (i32.load16_u (i64.const 0))) + (drop (i32.load (i64.const 0))) + (drop (i64.load8_s (i64.const 0))) + (drop (i64.load8_u (i64.const 0))) + (drop (i64.load16_s (i64.const 0))) + (drop (i64.load16_u (i64.const 0))) + (drop (i64.load32_s (i64.const 0))) + (drop (i64.load32_u (i64.const 0))) + (drop (i64.load (i64.const 0))) + (drop (f32.load (i64.const 0))) + (drop (f64.load (i64.const 0))) + + (drop (i32.load8_s align=1 offset=1 (i64.const 0))) + (drop (i32.load8_u align=1 offset=2 (i64.const 0))) + (drop (i32.load16_s align=1 offset=3 (i64.const 0))) + (drop (i32.load16_u align=1 offset=4 (i64.const 0))) + (drop (i32.load align=2 offset=5 (i64.const 0))) + (drop (i64.load8_s align=1 offset=6 (i64.const 0))) + (drop (i64.load8_u align=1 offset=7 (i64.const 0))) + (drop (i64.load16_s align=1 offset=8 (i64.const 0))) + (drop (i64.load16_u align=1 offset=9 (i64.const 0))) + (drop (i64.load32_s align=2 offset=10 (i64.const 0))) + (drop (i64.load32_u align=2 offset=11 (i64.const 0))) + (drop (i64.load align=2 offset=12 (i64.const 0))) + (drop (f32.load align=2 offset=13 (i64.const 0))) + (drop (f64.load align=2 offset=14 (i64.const 0))) + ) + + (func $B (type $1) + (i32.store8 (i64.const 0) (i32.const 1)) + (i32.store16 (i64.const 0) (i32.const 2)) + (i32.store (i64.const 0) (i32.const 3)) + (i64.store8 (i64.const 0) (i64.const 4)) + (i64.store16 (i64.const 0) (i64.const 5)) + (i64.store32 (i64.const 0) (i64.const 6)) + (i64.store (i64.const 0) (i64.const 7)) + (f32.store (i64.const 0) (f32.const 8)) + (f64.store (i64.const 0) (f64.const 9)) + + (i32.store8 align=1 offset=1 (i64.const 0) (i32.const 1)) + (i32.store16 align=1 offset=2 (i64.const 0) (i32.const 2)) + (i32.store align=2 offset=3 (i64.const 0) (i32.const 3)) + (i64.store8 align=1 offset=4 (i64.const 0) (i64.const 4)) + (i64.store16 align=2 offset=5 (i64.const 0) (i64.const 5)) + (i64.store32 align=2 offset=6 (i64.const 0) (i64.const 6)) + (i64.store align=2 offset=7 (i64.const 0) (i64.const 7)) + (f32.store align=2 offset=8 (i64.const 0) (f32.const 8)) + (f64.store align=2 offset=9 (i64.const 0) (f64.const 9)) + ) +) diff -Nru binaryen-108/test/passes/instrument-memory.txt binaryen-99/test/passes/instrument-memory.txt --- binaryen-108/test/passes/instrument-memory.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-memory.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,603 @@ +(module + (type $none_=>_none (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (type $i32_i64_=>_i64 (func (param i32 i64) (result i64))) + (type $i32_f32_=>_f32 (func (param i32 f32) (result f32))) + (type $i32_f64_=>_f64 (func (param i32 f64) (result f64))) + (import "env" "load_ptr" (func $load_ptr (param i32 i32 i32 i32) (result i32))) + (import "env" "load_val_i32" (func $load_val_i32 (param i32 i32) (result i32))) + (import "env" "load_val_i64" (func $load_val_i64 (param i32 i64) (result i64))) + (import "env" "load_val_f32" (func $load_val_f32 (param i32 f32) (result f32))) + (import "env" "load_val_f64" (func $load_val_f64 (param i32 f64) (result f64))) + (import "env" "store_ptr" (func $store_ptr (param i32 i32 i32 i32) (result i32))) + (import "env" "store_val_i32" (func $store_val_i32 (param i32 i32) (result i32))) + (import "env" "store_val_i64" (func $store_val_i64 (param i32 i64) (result i64))) + (import "env" "store_val_f32" (func $store_val_f32 (param i32 f32) (result f32))) + (import "env" "store_val_f64" (func $store_val_f64 (param i32 f64) (result f64))) + (memory $0 256 256) + (func $A + (drop + (call $load_val_i32 + (i32.const 1) + (i32.load8_s + (call $load_ptr + (i32.const 1) + (i32.const 1) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 2) + (i32.load8_u + (call $load_ptr + (i32.const 2) + (i32.const 1) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 3) + (i32.load16_s + (call $load_ptr + (i32.const 3) + (i32.const 2) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 4) + (i32.load16_u + (call $load_ptr + (i32.const 4) + (i32.const 2) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 5) + (i32.load + (call $load_ptr + (i32.const 5) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 6) + (i64.load8_s + (call $load_ptr + (i32.const 6) + (i32.const 1) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 7) + (i64.load8_u + (call $load_ptr + (i32.const 7) + (i32.const 1) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 8) + (i64.load16_s + (call $load_ptr + (i32.const 8) + (i32.const 2) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 9) + (i64.load16_u + (call $load_ptr + (i32.const 9) + (i32.const 2) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 10) + (i64.load32_s + (call $load_ptr + (i32.const 10) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 11) + (i64.load32_u + (call $load_ptr + (i32.const 11) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 12) + (i64.load + (call $load_ptr + (i32.const 12) + (i32.const 8) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f32 + (i32.const 13) + (f32.load + (call $load_ptr + (i32.const 13) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f64 + (i32.const 14) + (f64.load + (call $load_ptr + (i32.const 14) + (i32.const 8) + (i32.const 0) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 15) + (i32.load8_s offset=1 + (call $load_ptr + (i32.const 15) + (i32.const 1) + (i32.const 1) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 16) + (i32.load8_u offset=2 + (call $load_ptr + (i32.const 16) + (i32.const 1) + (i32.const 2) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 17) + (i32.load16_s offset=3 align=1 + (call $load_ptr + (i32.const 17) + (i32.const 2) + (i32.const 3) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 18) + (i32.load16_u offset=4 align=1 + (call $load_ptr + (i32.const 18) + (i32.const 2) + (i32.const 4) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i32 + (i32.const 19) + (i32.load offset=5 align=2 + (call $load_ptr + (i32.const 19) + (i32.const 4) + (i32.const 5) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 20) + (i64.load8_s offset=6 + (call $load_ptr + (i32.const 20) + (i32.const 1) + (i32.const 6) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 21) + (i64.load8_u offset=7 + (call $load_ptr + (i32.const 21) + (i32.const 1) + (i32.const 7) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 22) + (i64.load16_s offset=8 align=1 + (call $load_ptr + (i32.const 22) + (i32.const 2) + (i32.const 8) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 23) + (i64.load16_u offset=9 align=1 + (call $load_ptr + (i32.const 23) + (i32.const 2) + (i32.const 9) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 24) + (i64.load32_s offset=10 align=2 + (call $load_ptr + (i32.const 24) + (i32.const 4) + (i32.const 10) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 25) + (i64.load32_u offset=11 align=2 + (call $load_ptr + (i32.const 25) + (i32.const 4) + (i32.const 11) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_i64 + (i32.const 26) + (i64.load offset=12 align=2 + (call $load_ptr + (i32.const 26) + (i32.const 8) + (i32.const 12) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f32 + (i32.const 27) + (f32.load offset=13 align=2 + (call $load_ptr + (i32.const 27) + (i32.const 4) + (i32.const 13) + (i32.const 0) + ) + ) + ) + ) + (drop + (call $load_val_f64 + (i32.const 28) + (f64.load offset=14 align=2 + (call $load_ptr + (i32.const 28) + (i32.const 8) + (i32.const 14) + (i32.const 0) + ) + ) + ) + ) + ) + (func $B + (i32.store8 + (call $store_ptr + (i32.const 29) + (i32.const 1) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i32 + (i32.const 29) + (i32.const 1) + ) + ) + (i32.store16 + (call $store_ptr + (i32.const 30) + (i32.const 2) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i32 + (i32.const 30) + (i32.const 2) + ) + ) + (i32.store + (call $store_ptr + (i32.const 31) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i32 + (i32.const 31) + (i32.const 3) + ) + ) + (i64.store8 + (call $store_ptr + (i32.const 32) + (i32.const 1) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 32) + (i64.const 4) + ) + ) + (i64.store16 + (call $store_ptr + (i32.const 33) + (i32.const 2) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 33) + (i64.const 5) + ) + ) + (i64.store32 + (call $store_ptr + (i32.const 34) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 34) + (i64.const 6) + ) + ) + (i64.store + (call $store_ptr + (i32.const 35) + (i32.const 8) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 35) + (i64.const 7) + ) + ) + (f32.store + (call $store_ptr + (i32.const 36) + (i32.const 4) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_f32 + (i32.const 36) + (f32.const 8) + ) + ) + (f64.store + (call $store_ptr + (i32.const 37) + (i32.const 8) + (i32.const 0) + (i32.const 0) + ) + (call $store_val_f64 + (i32.const 37) + (f64.const 9) + ) + ) + (i32.store8 offset=1 + (call $store_ptr + (i32.const 38) + (i32.const 1) + (i32.const 1) + (i32.const 0) + ) + (call $store_val_i32 + (i32.const 38) + (i32.const 1) + ) + ) + (i32.store16 offset=2 align=1 + (call $store_ptr + (i32.const 39) + (i32.const 2) + (i32.const 2) + (i32.const 0) + ) + (call $store_val_i32 + (i32.const 39) + (i32.const 2) + ) + ) + (i32.store offset=3 align=2 + (call $store_ptr + (i32.const 40) + (i32.const 4) + (i32.const 3) + (i32.const 0) + ) + (call $store_val_i32 + (i32.const 40) + (i32.const 3) + ) + ) + (i64.store8 offset=4 + (call $store_ptr + (i32.const 41) + (i32.const 1) + (i32.const 4) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 41) + (i64.const 4) + ) + ) + (i64.store16 offset=5 + (call $store_ptr + (i32.const 42) + (i32.const 2) + (i32.const 5) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 42) + (i64.const 5) + ) + ) + (i64.store32 offset=6 align=2 + (call $store_ptr + (i32.const 43) + (i32.const 4) + (i32.const 6) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 43) + (i64.const 6) + ) + ) + (i64.store offset=7 align=2 + (call $store_ptr + (i32.const 44) + (i32.const 8) + (i32.const 7) + (i32.const 0) + ) + (call $store_val_i64 + (i32.const 44) + (i64.const 7) + ) + ) + (f32.store offset=8 align=2 + (call $store_ptr + (i32.const 45) + (i32.const 4) + (i32.const 8) + (i32.const 0) + ) + (call $store_val_f32 + (i32.const 45) + (f32.const 8) + ) + ) + (f64.store offset=9 align=2 + (call $store_ptr + (i32.const 46) + (i32.const 8) + (i32.const 9) + (i32.const 0) + ) + (call $store_val_f64 + (i32.const 46) + (f64.const 9) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/instrument-memory.wast binaryen-99/test/passes/instrument-memory.wast --- binaryen-108/test/passes/instrument-memory.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/instrument-memory.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,57 @@ +(module + (memory 256 256) + (type $1 (func)) + (func $A (type $1) + (drop (i32.load8_s (i32.const 0))) + (drop (i32.load8_u (i32.const 0))) + (drop (i32.load16_s (i32.const 0))) + (drop (i32.load16_u (i32.const 0))) + (drop (i32.load (i32.const 0))) + (drop (i64.load8_s (i32.const 0))) + (drop (i64.load8_u (i32.const 0))) + (drop (i64.load16_s (i32.const 0))) + (drop (i64.load16_u (i32.const 0))) + (drop (i64.load32_s (i32.const 0))) + (drop (i64.load32_u (i32.const 0))) + (drop (i64.load (i32.const 0))) + (drop (f32.load (i32.const 0))) + (drop (f64.load (i32.const 0))) + + (drop (i32.load8_s align=1 offset=1 (i32.const 0))) + (drop (i32.load8_u align=1 offset=2 (i32.const 0))) + (drop (i32.load16_s align=1 offset=3 (i32.const 0))) + (drop (i32.load16_u align=1 offset=4 (i32.const 0))) + (drop (i32.load align=2 offset=5 (i32.const 0))) + (drop (i64.load8_s align=1 offset=6 (i32.const 0))) + (drop (i64.load8_u align=1 offset=7 (i32.const 0))) + (drop (i64.load16_s align=1 offset=8 (i32.const 0))) + (drop (i64.load16_u align=1 offset=9 (i32.const 0))) + (drop (i64.load32_s align=2 offset=10 (i32.const 0))) + (drop (i64.load32_u align=2 offset=11 (i32.const 0))) + (drop (i64.load align=2 offset=12 (i32.const 0))) + (drop (f32.load align=2 offset=13 (i32.const 0))) + (drop (f64.load align=2 offset=14 (i32.const 0))) + ) + + (func $B (type $1) + (i32.store8 (i32.const 0) (i32.const 1)) + (i32.store16 (i32.const 0) (i32.const 2)) + (i32.store (i32.const 0) (i32.const 3)) + (i64.store8 (i32.const 0) (i64.const 4)) + (i64.store16 (i32.const 0) (i64.const 5)) + (i64.store32 (i32.const 0) (i64.const 6)) + (i64.store (i32.const 0) (i64.const 7)) + (f32.store (i32.const 0) (f32.const 8)) + (f64.store (i32.const 0) (f64.const 9)) + + (i32.store8 align=1 offset=1 (i32.const 0) (i32.const 1)) + (i32.store16 align=1 offset=2 (i32.const 0) (i32.const 2)) + (i32.store align=2 offset=3 (i32.const 0) (i32.const 3)) + (i64.store8 align=1 offset=4 (i32.const 0) (i64.const 4)) + (i64.store16 align=2 offset=5 (i32.const 0) (i64.const 5)) + (i64.store32 align=2 offset=6 (i32.const 0) (i64.const 6)) + (i64.store align=2 offset=7 (i32.const 0) (i64.const 7)) + (f32.store align=2 offset=8 (i32.const 0) (f32.const 8)) + (f64.store align=2 offset=9 (i32.const 0) (f64.const 9)) + ) +) diff -Nru binaryen-108/test/passes/legalize-js-interface_all-features.txt binaryen-99/test/passes/legalize-js-interface_all-features.txt --- binaryen-108/test/passes/legalize-js-interface_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/legalize-js-interface_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -5,12 +5,12 @@ (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (type $i32_i64_i64_=>_none (func (param i32 i64 i64))) + (import "env" "ref-func-arg" (func $ref-func-arg (result i64))) (import "env" "setTempRet0" (func $setTempRet0 (param i32))) (import "env" "getTempRet0" (func $getTempRet0 (result i32))) (import "env" "imported" (func $legalimport$imported (result i32))) (import "env" "other" (func $legalimport$other (param i32 i32 i32 i32 i32))) (import "env" "ref-func-arg" (func $legalimport$ref-func-arg (result i32))) - (elem declare func $legalfunc$ref-func-arg) (export "func" (func $legalstub$func)) (export "ref-func-test" (func $ref-func-test)) (export "imported" (func $legalstub$imported)) @@ -32,7 +32,7 @@ (call $legalfunc$ref-func-arg) ) (drop - (ref.func $legalfunc$ref-func-arg) + (ref.func $ref-func-arg) ) ) (func $legalstub$func (result i32) diff -Nru binaryen-108/test/passes/legalize-js-interface_all-features.wast binaryen-99/test/passes/legalize-js-interface_all-features.wast --- binaryen-108/test/passes/legalize-js-interface_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/legalize-js-interface_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -17,7 +17,8 @@ (unreachable) ) - ;; ref.func must also be updated. + ;; If an import is used in ref.func, even if it is legalized to another + ;; import, the original import should not be removed. (func $ref-func-test (drop (call $ref-func-arg) diff -Nru binaryen-108/test/passes/legalize-js-interface-minimally.txt binaryen-99/test/passes/legalize-js-interface-minimally.txt --- binaryen-108/test/passes/legalize-js-interface-minimally.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/legalize-js-interface-minimally.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $none_=>_i64 (func (result i64))) (type $i32_=>_none (func (param i32))) - (type $none_=>_i32 (func (result i32))) (type $i64_=>_none (func (param i64))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "imported" (func $imported (result i64))) (import "env" "setTempRet0" (func $setTempRet0 (param i32))) (import "env" "invoke_vj" (func $legalimport$invoke_vj (param i32 i32))) diff -Nru binaryen-108/test/passes/legalize-js-interface_pass-arg=legalize-js-interface-export-originals.txt binaryen-99/test/passes/legalize-js-interface_pass-arg=legalize-js-interface-export-originals.txt --- binaryen-108/test/passes/legalize-js-interface_pass-arg=legalize-js-interface-export-originals.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/legalize-js-interface_pass-arg=legalize-js-interface-export-originals.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $none_=>_i64 (func (result i64))) (type $i32_=>_none (func (param i32))) (type $none_=>_i32 (func (result i32))) + (type $none_=>_i64 (func (result i64))) (import "env" "setTempRet0" (func $setTempRet0 (param i32))) (export "func" (func $legalstub$func)) (export "orig$func" (func $func)) diff -Nru binaryen-108/test/passes/licm.txt binaryen-99/test/passes/licm.txt --- binaryen-108/test/passes/licm.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/licm.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,11 @@ (module (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) - (type $none_=>_i64 (func (result i64))) (type $i32_=>_none (func (param i32))) (type $i32_=>_i32 (func (param i32) (result i32))) - (global $glob (mut i32) (i32.const 1)) - (global $glob-imm i32 (i32.const 1)) + (type $none_=>_i64 (func (result i64))) (memory $0 1) + (global $glob (mut i32) (i32.const 1)) (func $loop1 (drop (i32.const 10) @@ -690,38 +689,6 @@ (nop) (br_if $loop (local.get $x) - ) - ) - ) - (func $global-call - (local $x i32) - (loop $loop - (local.set $x - (global.get $glob) - ) - (call $global) - (drop - (local.get $x) - ) - (br_if $loop - (local.get $x) - ) - ) - ) - (func $global-call-immutable - (local $x i32) - (local.set $x - (global.get $glob-imm) - ) - (drop - (local.get $x) - ) - (loop $loop - (nop) - (call $global) - (nop) - (br_if $loop - (local.get $x) ) ) ) diff -Nru binaryen-108/test/passes/licm.wast binaryen-99/test/passes/licm.wast --- binaryen-108/test/passes/licm.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/licm.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,6 @@ (module (memory 1) (global $glob (mut i32) (i32.const 1)) - (global $glob-imm i32 (i32.const 1)) (func $loop1 (loop $loop (drop (i32.const 10)) @@ -394,33 +393,9 @@ (func $global (local $x i32) (loop $loop - ;; Moving this global.get out of the loop is ok. It is mutable, but there - ;; is no possible place where it can be set in the loop. (local.set $x (global.get $glob)) (drop (local.get $x)) (br_if $loop (local.get $x)) ) - ) - (func $global-call - (local $x i32) - (loop $loop - ;; As above, but now the loop does a call, which might in theory change - ;; mutable global state, so we cannot optimize. - (local.set $x (global.get $glob)) - (call $global) - (drop (local.get $x)) - (br_if $loop (local.get $x)) - ) - ) - (func $global-call-immutable - (local $x i32) - (loop $loop - ;; As above, but now the global is immutable, so the call does not - ;; prevent us from optimizing. - (local.set $x (global.get $glob-imm)) - (call $global) - (drop (local.get $x)) - (br_if $loop (local.get $x)) - ) ) ) diff -Nru binaryen-108/test/passes/log-execution.txt binaryen-99/test/passes/log-execution.txt --- binaryen-108/test/passes/log-execution.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/log-execution.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_none (func)) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "func" (func $import)) (import "env" "log_execution" (func $log_execution (param i32))) (func $nopp diff -Nru binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.txt binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.txt --- binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,218 +0,0 @@ -(module - (type $none_=>_none (func)) - (memory $0 1 1) - (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00") - (func $func_1 - (local $0 i64) - (drop - (i32.load - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load align=1 - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load align=2 - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load offset=100 - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load offset=100 align=1 - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load offset=100 align=2 - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load offset=100 - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (drop - (i32.load offset=100 align=1 - (unreachable) - ) - ) - (i32.store - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store align=1 - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store align=2 - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store offset=100 - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store offset=100 align=1 - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store offset=100 align=2 - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store offset=100 - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (i32.store offset=100 align=1 - (unreachable) - (i32.const 8) - ) - (i32.store offset=100 align=1 - (i32.wrap_i64 - (i64.const 4) - ) - (unreachable) - ) - (local.set $0 - (i64.extend_i32_u - (memory.size) - ) - ) - (local.set $0 - (i64.extend_i32_u - (memory.grow - (i32.wrap_i64 - (i64.const 1) - ) - ) - ) - ) - (memory.init 0 - (i32.wrap_i64 - (i64.const 1) - ) - (i32.const 2) - (i32.const 3) - ) - (memory.fill - (i32.wrap_i64 - (i64.const 1) - ) - (i32.const 2) - (i32.wrap_i64 - (i64.const 3) - ) - ) - (memory.copy - (i32.wrap_i64 - (i64.const 1) - ) - (i32.wrap_i64 - (i64.const 2) - ) - (i32.wrap_i64 - (i64.const 3) - ) - ) - (drop - (i32.atomic.load - (i32.wrap_i64 - (i64.const 4) - ) - ) - ) - (i32.atomic.store - (i32.wrap_i64 - (i64.const 4) - ) - (i32.const 8) - ) - (drop - (i32.atomic.rmw8.add_u - (i32.wrap_i64 - (i64.const 1) - ) - (i32.const 2) - ) - ) - (drop - (i32.atomic.rmw8.cmpxchg_u - (i32.wrap_i64 - (i64.const 1) - ) - (i32.const 2) - (i32.const 3) - ) - ) - (drop - (memory.atomic.wait32 - (i32.wrap_i64 - (i64.const 1) - ) - (i32.const 2) - (i64.const 3) - ) - ) - (drop - (memory.atomic.notify - (i32.wrap_i64 - (i64.const 1) - ) - (i32.const 2) - ) - ) - ) -) -(module - (memory $0 1 65536) -) diff -Nru binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.wast binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.wast --- binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory_enable-threads.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -(module - (memory $0 i64 1 1) - (data (i64.const 0) "\00\00\00\00\00\00\00\00\00\00") - (func $func_1 - (local i64) - (drop (i32.load (i64.const 4))) - (drop (i32.load align=1 (i64.const 4))) - (drop (i32.load align=2 (i64.const 4))) - (drop (i32.load align=4 (i64.const 4))) - (drop (i32.load offset=100 (i64.const 4))) - (drop (i32.load offset=100 align=1 (i64.const 4))) - (drop (i32.load offset=100 align=2 (i64.const 4))) - (drop (i32.load offset=100 align=4 (i64.const 4))) - (drop (i32.load offset=100 align=1 (unreachable))) - (i32.store (i64.const 4) (i32.const 8)) - (i32.store align=1 (i64.const 4) (i32.const 8)) - (i32.store align=2 (i64.const 4) (i32.const 8)) - (i32.store align=4 (i64.const 4) (i32.const 8)) - (i32.store offset=100 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=1 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=2 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=4 (i64.const 4) (i32.const 8)) - (i32.store offset=100 align=1 (unreachable) (i32.const 8)) - (i32.store offset=100 align=1 (i64.const 4) (unreachable)) - (local.set 0 (memory.size)) - (local.set 0 (memory.grow (i64.const 1))) - (memory.init 0 (i64.const 1) (i32.const 2) (i32.const 3)) - (memory.fill (i64.const 1) (i32.const 2) (i64.const 3)) - (memory.copy (i64.const 1) (i64.const 2) (i64.const 3)) - (drop (i32.atomic.load (i64.const 4))) - (i32.atomic.store (i64.const 4) (i32.const 8)) - (drop (i32.atomic.rmw8.add_u (i64.const 1) (i32.const 2))) - (drop (i32.atomic.rmw8.cmpxchg_u (i64.const 1) (i32.const 2) (i32.const 3))) - (drop (memory.atomic.wait32 (i64.const 1) (i32.const 2) (i64.const 3))) - (drop (memory.atomic.notify (i64.const 1) (i32.const 2))) - ) -) - -(module - (memory $0 i64 1 65537) -) diff -Nru binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.txt binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.txt --- binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,168 @@ +(module + (type $none_=>_none (func)) + (memory $0 1 1) + (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00") + (func $func_1 + (local $0 i64) + (drop + (i32.load + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load align=1 + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load align=2 + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load offset=100 + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load offset=100 align=1 + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load offset=100 align=2 + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load offset=100 + (i32.wrap_i64 + (i64.const 4) + ) + ) + ) + (drop + (i32.load offset=100 align=1 + (unreachable) + ) + ) + (i32.store + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store align=1 + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store align=2 + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store offset=100 + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store offset=100 align=1 + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store offset=100 align=2 + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store offset=100 + (i32.wrap_i64 + (i64.const 4) + ) + (i32.const 8) + ) + (i32.store offset=100 align=1 + (unreachable) + (i32.const 8) + ) + (i32.store offset=100 align=1 + (i32.wrap_i64 + (i64.const 4) + ) + (unreachable) + ) + (local.set $0 + (i64.extend_i32_u + (memory.size) + ) + ) + (local.set $0 + (i64.extend_i32_u + (memory.grow + (i32.wrap_i64 + (i64.const 1) + ) + ) + ) + ) + (memory.init 0 + (i32.wrap_i64 + (i64.const 1) + ) + (i32.const 2) + (i32.const 3) + ) + (memory.fill + (i32.wrap_i64 + (i64.const 1) + ) + (i32.const 2) + (i32.wrap_i64 + (i64.const 3) + ) + ) + (memory.copy + (i32.wrap_i64 + (i64.const 1) + ) + (i32.wrap_i64 + (i64.const 2) + ) + (i32.wrap_i64 + (i64.const 3) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.wast binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.wast --- binaryen-108/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/memory64-lowering_enable-memory64_enable-bulk-memory.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,31 @@ +(module + (memory $0 i64 1 1) + (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00") + (func $func_1 + (local i64) + (drop (i32.load (i64.const 4))) + (drop (i32.load align=1 (i64.const 4))) + (drop (i32.load align=2 (i64.const 4))) + (drop (i32.load align=4 (i64.const 4))) + (drop (i32.load offset=100 (i64.const 4))) + (drop (i32.load offset=100 align=1 (i64.const 4))) + (drop (i32.load offset=100 align=2 (i64.const 4))) + (drop (i32.load offset=100 align=4 (i64.const 4))) + (drop (i32.load offset=100 align=1 (unreachable))) + (i32.store (i64.const 4) (i32.const 8)) + (i32.store align=1 (i64.const 4) (i32.const 8)) + (i32.store align=2 (i64.const 4) (i32.const 8)) + (i32.store align=4 (i64.const 4) (i32.const 8)) + (i32.store offset=100 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=1 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=2 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=4 (i64.const 4) (i32.const 8)) + (i32.store offset=100 align=1 (unreachable) (i32.const 8)) + (i32.store offset=100 align=1 (i64.const 4) (unreachable)) + (local.set 0 (memory.size)) + (local.set 0 (memory.grow (i64.const 1))) + (memory.init 0 (i64.const 1) (i32.const 2) (i32.const 3)) + (memory.fill (i64.const 1) (i32.const 2) (i64.const 3)) + (memory.copy (i64.const 1) (i64.const 2) (i64.const 3)) + ) +) diff -Nru binaryen-108/test/passes/memory-packing_all-features.txt binaryen-99/test/passes/memory-packing_all-features.txt --- binaryen-108/test/passes/memory-packing_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/memory-packing_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1574 @@ +(module + (import "env" "memoryBase" (global $memoryBase i32)) + (memory $0 2048 2048) +) +(module + (import "env" "memoryBase" (global $memoryBase i32)) + (memory $0 2048 2048) +) +(module + (import "env" "memoryBase" (global $memoryBase i32)) + (memory $0 2048 2048) + (data (global.get $memoryBase) "waka this cannot be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we don\'t know where it will go") +) +(module + (type $none_=>_none (func)) + (memory $0 1 1) + (data (i32.const 1024) "waka this CAN be optimized") + (data (i32.const 1107) "we DO know where it will go") + (data (i32.const 2057) "zeros before") + (data (i32.const 3000) "zeros after") + (data (i32.const 4000) "zeros\00in\00the\00middle") + (data (i32.const 4035) "nice skip here") + (data (i32.const 4066) "another\00but no") + (func $nonzero-size-init-of-active-will-trap + (block + (drop + (i32.const 42) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 13) + ) + (unreachable) + ) + (nop) + ) + (func $nonzero-offset-init-of-active-will-trap + (block + (drop + (i32.const 42) + ) + (drop + (i32.const 13) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + (nop) + ) + (func $zero-offset-size-init-of-active-may-trap + (if + (i32.gt_u + (i32.const 42) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (unreachable) + ) + (nop) + ) +) +(module + (type $none_=>_none (func)) + (memory $0 2048 2048) + (data passive "zeroes at start") + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes at start") + (data passive "\00\00\00few zeroes at start") + (data passive "zeroes at end") + (data passive "zeroes at end\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data passive "few zeroes at end\00\00\00") + (data passive "zeroes") + (data passive "in middle") + (data passive "zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00in middle") + (data passive "few zeroes\00\00\00in middle") + (data passive "multiple") + (data passive "spans") + (data passive "of zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "no zeroes") + (global $__mem_segment_drop_state (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_0 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_1 (mut i32) (i32.const 0)) + (func $zeroes-at-start + (block + (if + (global.get $__mem_segment_drop_state) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + (memory.init 0 + (i32.const 30) + (i32.const 0) + (i32.const 15) + ) + ) + (block + (global.set $__mem_segment_drop_state + (i32.const 1) + ) + (data.drop 0) + ) + ) + (func $zeroes-at-start-not-split + (memory.init 1 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (memory.init 1 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (memory.init 1 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (memory.init 1 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (data.drop 1) + ) + (func $few-zeroes-at-start + (memory.init 2 + (i32.const 0) + (i32.const 0) + (i32.const 22) + ) + (data.drop 2) + ) + (func $zeroes-at-end + (block + (memory.init 3 + (i32.const 0) + (i32.const 0) + (i32.const 13) + ) + (memory.fill + (i32.const 13) + (i32.const 0) + (i32.const 30) + ) + ) + (data.drop 3) + ) + (func $zeroes-at-end-not-split + (memory.init 4 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (memory.init 4 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (memory.init 4 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (memory.init 4 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (data.drop 4) + ) + (func $few-zeroes-at-end + (memory.init 5 + (i32.const 0) + (i32.const 0) + (i32.const 20) + ) + (data.drop 5) + ) + (func $zeroes-in-middle + (block + (memory.init 6 + (i32.const 0) + (i32.const 0) + (i32.const 6) + ) + (memory.fill + (i32.const 6) + (i32.const 0) + (i32.const 30) + ) + (memory.init 7 + (i32.const 36) + (i32.const 0) + (i32.const 9) + ) + ) + (block + (data.drop 6) + (data.drop 7) + ) + ) + (func $zeroes-in-middle-not-split + (memory.init 8 + (i32.const 0) + (i32.const 0) + (i32.const 35) + ) + (memory.init 8 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (data.drop 8) + ) + (func $few-zeroes-in-middle + (memory.init 9 + (i32.const 0) + (i32.const 0) + (i32.const 22) + ) + (data.drop 9) + ) + (func $multiple-spans-of-zeroes + (block + (memory.init 10 + (i32.const 0) + (i32.const 0) + (i32.const 8) + ) + (memory.fill + (i32.const 8) + (i32.const 0) + (i32.const 30) + ) + (memory.init 11 + (i32.const 38) + (i32.const 0) + (i32.const 5) + ) + (memory.fill + (i32.const 43) + (i32.const 0) + (i32.const 30) + ) + (memory.init 12 + (i32.const 73) + (i32.const 0) + (i32.const 9) + ) + ) + (block + (data.drop 10) + (data.drop 11) + (data.drop 12) + ) + ) + (func $even-more-zeroes + (block + (if + (global.get $__mem_segment_drop_state_0) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + (memory.init 13 + (i32.const 30) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 34) + (i32.const 0) + (i32.const 30) + ) + (memory.init 14 + (i32.const 64) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 68) + (i32.const 0) + (i32.const 30) + ) + (memory.init 15 + (i32.const 98) + (i32.const 0) + (i32.const 6) + ) + (memory.fill + (i32.const 104) + (i32.const 0) + (i32.const 30) + ) + ) + (block + (global.set $__mem_segment_drop_state_0 + (i32.const 1) + ) + (data.drop 13) + (data.drop 14) + (data.drop 15) + ) + ) + (func $only-zeroes + (block + (if + (global.get $__mem_segment_drop_state_1) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + ) + (global.set $__mem_segment_drop_state_1 + (i32.const 1) + ) + ) + (func $no-zeroes + (memory.init 16 + (i32.const 0) + (i32.const 0) + (i32.const 9) + ) + (data.drop 16) + ) + (func $empty + (if + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (unreachable) + ) + (nop) + ) + (func $only-dropped + (nop) + (nop) + ) + (func $only-dropped-zeroes + (nop) + (nop) + ) +) +(module + (type $none_=>_none (func)) + (import "env" "param" (global $param i32)) + (memory $0 2048 2048) + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (data passive "even") + (data passive "more") + (data passive "zeroes") + (global $__mem_segment_drop_state (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_0 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_1 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_2 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_3 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_4 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_5 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_6 (mut i32) (i32.const 0)) + (func $nonconst-dest + (local $0 i32) + (block + (local.set $0 + (global.get $param) + ) + (if + (global.get $__mem_segment_drop_state) + (unreachable) + ) + (memory.fill + (local.get $0) + (i32.const 0) + (i32.const 30) + ) + (memory.init 0 + (i32.add + (local.get $0) + (i32.const 30) + ) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.add + (local.get $0) + (i32.const 34) + ) + (i32.const 0) + (i32.const 30) + ) + (memory.init 1 + (i32.add + (local.get $0) + (i32.const 64) + ) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.add + (local.get $0) + (i32.const 68) + ) + (i32.const 0) + (i32.const 30) + ) + (memory.init 2 + (i32.add + (local.get $0) + (i32.const 98) + ) + (i32.const 0) + (i32.const 6) + ) + (memory.fill + (i32.add + (local.get $0) + (i32.const 104) + ) + (i32.const 0) + (i32.const 30) + ) + ) + (block + (global.set $__mem_segment_drop_state + (i32.const 1) + ) + (data.drop 0) + (data.drop 1) + (data.drop 2) + ) + ) + (func $nonconst-offset + (memory.init 3 + (i32.const 0) + (global.get $param) + (i32.const 134) + ) + (data.drop 3) + ) + (func $nonconst-size + (memory.init 4 + (i32.const 0) + (i32.const 0) + (global.get $param) + ) + (data.drop 4) + ) + (func $partial-skip-start + (block + (if + (global.get $__mem_segment_drop_state_0) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 20) + ) + (memory.init 5 + (i32.const 20) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 24) + (i32.const 0) + (i32.const 30) + ) + (memory.init 6 + (i32.const 54) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 58) + (i32.const 0) + (i32.const 30) + ) + (memory.init 7 + (i32.const 88) + (i32.const 0) + (i32.const 6) + ) + (memory.fill + (i32.const 94) + (i32.const 0) + (i32.const 30) + ) + ) + (block + (global.set $__mem_segment_drop_state_0 + (i32.const 1) + ) + (data.drop 5) + (data.drop 6) + (data.drop 7) + ) + ) + (func $full-skip-start + (block + (memory.init 8 + (i32.const 0) + (i32.const 2) + (i32.const 2) + ) + (memory.fill + (i32.const 2) + (i32.const 0) + (i32.const 30) + ) + (memory.init 9 + (i32.const 32) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 36) + (i32.const 0) + (i32.const 30) + ) + (memory.init 10 + (i32.const 66) + (i32.const 0) + (i32.const 6) + ) + (memory.fill + (i32.const 72) + (i32.const 0) + (i32.const 30) + ) + ) + (block + (data.drop 8) + (data.drop 9) + (data.drop 10) + ) + ) + (func $partial-skip-end + (block + (if + (global.get $__mem_segment_drop_state_1) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + (memory.init 11 + (i32.const 30) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 34) + (i32.const 0) + (i32.const 30) + ) + (memory.init 12 + (i32.const 64) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 68) + (i32.const 0) + (i32.const 30) + ) + (memory.init 13 + (i32.const 98) + (i32.const 0) + (i32.const 6) + ) + (memory.fill + (i32.const 104) + (i32.const 0) + (i32.const 20) + ) + ) + (block + (global.set $__mem_segment_drop_state_1 + (i32.const 1) + ) + (data.drop 11) + (data.drop 12) + (data.drop 13) + ) + ) + (func $full-skip-end + (block + (if + (global.get $__mem_segment_drop_state_2) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + (memory.init 14 + (i32.const 30) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 34) + (i32.const 0) + (i32.const 30) + ) + (memory.init 15 + (i32.const 64) + (i32.const 0) + (i32.const 4) + ) + (memory.fill + (i32.const 68) + (i32.const 0) + (i32.const 30) + ) + (memory.init 16 + (i32.const 98) + (i32.const 0) + (i32.const 4) + ) + ) + (block + (global.set $__mem_segment_drop_state_2 + (i32.const 1) + ) + (data.drop 14) + (data.drop 15) + (data.drop 16) + ) + ) + (func $slice-zeroes + (block + (if + (global.get $__mem_segment_drop_state_3) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 10) + ) + ) + (block + (global.set $__mem_segment_drop_state_3 + (i32.const 1) + ) + (data.drop 17) + (data.drop 18) + (data.drop 19) + ) + ) + (func $slice-nonzeroes + (memory.init 20 + (i32.const 0) + (i32.const 1) + (i32.const 2) + ) + (block + (data.drop 20) + (data.drop 21) + (data.drop 22) + ) + ) + (func $zero-size + (if + (i32.or + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state_4) + ) + (unreachable) + ) + (block + (global.set $__mem_segment_drop_state_4 + (i32.const 1) + ) + (data.drop 23) + (data.drop 24) + (data.drop 25) + ) + ) + (func $zero-size-undropped + (if + (i32.or + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state_5) + ) + (unreachable) + ) + ) + (func $out-of-bounds-offset + (block + (drop + (i32.const 0) + ) + (drop + (i32.const 135) + ) + (drop + (i32.const 1) + ) + (unreachable) + ) + (nop) + ) + (func $zero-size-out-of-bounds-offset + (block + (drop + (i32.const 0) + ) + (drop + (i32.const 135) + ) + (drop + (i32.const 0) + ) + (unreachable) + ) + (nop) + ) + (func $out-of-bounds-size + (block + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 135) + ) + (unreachable) + ) + (nop) + ) + (func $zero-size-at-bounds-offset + (if + (i32.or + (i32.gt_u + (i32.const 0) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state_6) + ) + (unreachable) + ) + (block + (global.set $__mem_segment_drop_state_6 + (i32.const 1) + ) + (data.drop 29) + (data.drop 30) + (data.drop 31) + ) + ) +) +(module + (type $none_=>_none (func)) + (memory $0 2048 2048) + (data passive "hi") + (data passive "even") + (data passive "hi") + (data passive "hi") + (data passive "even") + (data passive "hi") + (data passive "even") + (data passive "hi") + (data passive "even") + (data passive "hi") + (global $__mem_segment_drop_state (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_0 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_1 (mut i32) (i32.const 0)) + (global $__mem_segment_drop_state_2 (mut i32) (i32.const 0)) + (func $zero-length-init-zeroes + (if + (i32.or + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state) + ) + (unreachable) + ) + (block + (global.set $__mem_segment_drop_state + (i32.const 1) + ) + (data.drop 0) + (data.drop 1) + (data.drop 2) + ) + ) + (func $zero-length-init-nonzeroes + (if + (i32.or + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state_0) + ) + (unreachable) + ) + (block + (global.set $__mem_segment_drop_state_0 + (i32.const 1) + ) + (data.drop 3) + (data.drop 4) + (data.drop 5) + ) + ) + (func $zero-length-init-zeroes-2 + (if + (i32.or + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state_1) + ) + (unreachable) + ) + (block + (global.set $__mem_segment_drop_state_1 + (i32.const 1) + ) + (data.drop 6) + (data.drop 7) + ) + ) + (func $zero-length-init-nonzeroes-2 + (if + (i32.or + (i32.gt_u + (i32.const 13) + (i32.shl + (memory.size) + (i32.const 16) + ) + ) + (global.get $__mem_segment_drop_state_2) + ) + (unreachable) + ) + (block + (global.set $__mem_segment_drop_state_2 + (i32.const 1) + ) + (data.drop 8) + (data.drop 9) + ) + ) +) +(module + (type $none_=>_none (func)) + (memory $0 2048 2048) + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a") + (data passive "a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a") + (func $init-lots + (block + (memory.init 0 + (i32.const 0) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1) + (i32.const 0) + (i32.const 30) + ) + (memory.init 1 + (i32.const 31) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 32) + (i32.const 0) + (i32.const 30) + ) + (memory.init 2 + (i32.const 62) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 63) + (i32.const 0) + (i32.const 30) + ) + (memory.init 3 + (i32.const 93) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 94) + (i32.const 0) + (i32.const 30) + ) + (memory.init 4 + (i32.const 124) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 125) + (i32.const 0) + (i32.const 30) + ) + (memory.init 5 + (i32.const 155) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 156) + (i32.const 0) + (i32.const 30) + ) + (memory.init 6 + (i32.const 186) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 187) + (i32.const 0) + (i32.const 30) + ) + (memory.init 7 + (i32.const 217) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 218) + (i32.const 0) + (i32.const 30) + ) + (memory.init 8 + (i32.const 248) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 249) + (i32.const 0) + (i32.const 30) + ) + (memory.init 9 + (i32.const 279) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 280) + (i32.const 0) + (i32.const 30) + ) + (memory.init 10 + (i32.const 310) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 311) + (i32.const 0) + (i32.const 30) + ) + (memory.init 11 + (i32.const 341) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 342) + (i32.const 0) + (i32.const 30) + ) + (memory.init 12 + (i32.const 372) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 373) + (i32.const 0) + (i32.const 30) + ) + (memory.init 13 + (i32.const 403) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 404) + (i32.const 0) + (i32.const 30) + ) + (memory.init 14 + (i32.const 434) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 435) + (i32.const 0) + (i32.const 30) + ) + (memory.init 15 + (i32.const 465) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 466) + (i32.const 0) + (i32.const 30) + ) + (memory.init 16 + (i32.const 496) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 497) + (i32.const 0) + (i32.const 30) + ) + (memory.init 17 + (i32.const 527) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 528) + (i32.const 0) + (i32.const 30) + ) + (memory.init 18 + (i32.const 558) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 559) + (i32.const 0) + (i32.const 30) + ) + (memory.init 19 + (i32.const 589) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 590) + (i32.const 0) + (i32.const 30) + ) + (memory.init 20 + (i32.const 620) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 621) + (i32.const 0) + (i32.const 30) + ) + (memory.init 21 + (i32.const 651) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 652) + (i32.const 0) + (i32.const 30) + ) + (memory.init 22 + (i32.const 682) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 683) + (i32.const 0) + (i32.const 30) + ) + (memory.init 23 + (i32.const 713) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 714) + (i32.const 0) + (i32.const 30) + ) + (memory.init 24 + (i32.const 744) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 745) + (i32.const 0) + (i32.const 30) + ) + (memory.init 25 + (i32.const 775) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 776) + (i32.const 0) + (i32.const 30) + ) + (memory.init 26 + (i32.const 806) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 807) + (i32.const 0) + (i32.const 30) + ) + (memory.init 27 + (i32.const 837) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 838) + (i32.const 0) + (i32.const 30) + ) + (memory.init 28 + (i32.const 868) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 869) + (i32.const 0) + (i32.const 30) + ) + (memory.init 29 + (i32.const 899) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 900) + (i32.const 0) + (i32.const 30) + ) + (memory.init 30 + (i32.const 930) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 931) + (i32.const 0) + (i32.const 30) + ) + (memory.init 31 + (i32.const 961) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 962) + (i32.const 0) + (i32.const 30) + ) + (memory.init 32 + (i32.const 992) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 993) + (i32.const 0) + (i32.const 30) + ) + (memory.init 33 + (i32.const 1023) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1024) + (i32.const 0) + (i32.const 30) + ) + (memory.init 34 + (i32.const 1054) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1055) + (i32.const 0) + (i32.const 30) + ) + (memory.init 35 + (i32.const 1085) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1086) + (i32.const 0) + (i32.const 30) + ) + (memory.init 36 + (i32.const 1116) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1117) + (i32.const 0) + (i32.const 30) + ) + (memory.init 37 + (i32.const 1147) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1148) + (i32.const 0) + (i32.const 30) + ) + (memory.init 38 + (i32.const 1178) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1179) + (i32.const 0) + (i32.const 30) + ) + (memory.init 39 + (i32.const 1209) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1210) + (i32.const 0) + (i32.const 30) + ) + (memory.init 40 + (i32.const 1240) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1241) + (i32.const 0) + (i32.const 30) + ) + (memory.init 41 + (i32.const 1271) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1272) + (i32.const 0) + (i32.const 30) + ) + (memory.init 42 + (i32.const 1302) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1303) + (i32.const 0) + (i32.const 30) + ) + (memory.init 43 + (i32.const 1333) + (i32.const 0) + (i32.const 1) + ) + (memory.fill + (i32.const 1334) + (i32.const 0) + (i32.const 11) + ) + ) + (block + (data.drop 0) + (data.drop 1) + (data.drop 2) + (data.drop 3) + (data.drop 4) + (data.drop 5) + (data.drop 6) + (data.drop 7) + (data.drop 8) + (data.drop 9) + (data.drop 10) + (data.drop 11) + (data.drop 12) + (data.drop 13) + (data.drop 14) + (data.drop 15) + (data.drop 16) + (data.drop 17) + (data.drop 18) + (data.drop 19) + (data.drop 20) + (data.drop 21) + (data.drop 22) + (data.drop 23) + (data.drop 24) + (data.drop 25) + (data.drop 26) + (data.drop 27) + (data.drop 28) + (data.drop 29) + (data.drop 30) + (data.drop 31) + (data.drop 32) + (data.drop 33) + (data.drop 34) + (data.drop 35) + (data.drop 36) + (data.drop 37) + (data.drop 38) + (data.drop 39) + (data.drop 40) + (data.drop 41) + (data.drop 42) + (data.drop 43) + (data.drop 44) + (data.drop 45) + (data.drop 46) + (data.drop 47) + (data.drop 48) + (data.drop 49) + (data.drop 50) + (data.drop 51) + (data.drop 52) + (data.drop 53) + (data.drop 54) + (data.drop 55) + (data.drop 56) + (data.drop 57) + (data.drop 58) + (data.drop 59) + (data.drop 60) + (data.drop 61) + (data.drop 62) + ) + ) +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 1024) "\00") +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 1024) "\00") + (data (i32.const 4096) "\00") +) +(module + (import "env" "memoryBase" (global $memoryBase i32)) + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (global.get $memoryBase) "\00") +) +(module + (import "env" "memoryBase" (global $memoryBase i32)) + (memory $0 1 1) + (data (i32.const 1024) "\00") + (data (global.get $memoryBase) "x") +) +(module + (type $none_=>_none (func)) + (memory $0 1 1) + (data passive "skipped") + (data passive "included") + (global $__mem_segment_drop_state (mut i32) (i32.const 0)) + (export "func_54" (func $0)) + (func $0 + (if + (global.get $__mem_segment_drop_state) + (unreachable) + ) + (memory.fill + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + (memory.init 1 + (i32.const 30) + (i32.const 0) + (i32.const 8) + ) + ) +) +(module + (import "env" "memory" (memory $0 1 1)) + (data (i32.const 1024) "x") + (data (i32.const 2048) "\00") +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") +) diff -Nru binaryen-108/test/passes/memory-packing_all-features.wast binaryen-99/test/passes/memory-packing_all-features.wast --- binaryen-108/test/passes/memory-packing_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/memory-packing_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,558 @@ +(module + (memory $0 2048 2048) + (import "env" "memoryBase" (global $memoryBase i32)) + ;; nothing +) + +(module + (memory $0 2048 2048) + (import "env" "memoryBase" (global $memoryBase i32)) + (data (i32.const 4066) "") ;; empty +) + +(module + (memory $0 2048 2048) + (import "env" "memoryBase" (global $memoryBase i32)) + + (data (global.get $memoryBase) "waka this cannot be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we don't know where it will go") +) + +(module + (memory 1 1) + + (data (i32.const 1024) "waka this CAN be optimized\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00we DO know where it will go") + + (data (i32.const 2000) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeros before") + + (data (i32.const 3000) "zeros after\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") + + (data (i32.const 4000) "zeros\00in\00the\00middle\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00nice skip here\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00another\00but no") + + (func $nonzero-size-init-of-active-will-trap + (memory.init 0 + (i32.const 42) + (i32.const 0) + (i32.const 13) + ) + (data.drop 0) + ) + + (func $nonzero-offset-init-of-active-will-trap + (memory.init 0 + (i32.const 42) + (i32.const 13) + (i32.const 0) + ) + (data.drop 0) + ) + + (func $zero-offset-size-init-of-active-may-trap + (memory.init 0 + (i32.const 42) + (i32.const 0) + (i32.const 0) + ) + (data.drop 0) + ) +) + +(module + (memory $0 2048 2048) + + (data passive "not referenced, delete me") ;; 0 + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes at start") ;; 1 + + (func $zeroes-at-start + (memory.init 1 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (data.drop 1) + ) + + ;; the not-split tests have too many memory.init and data.drop instructions for splitting to be worth it + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes at start") ;; 2 + + (func $zeroes-at-start-not-split + (memory.init 2 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (memory.init 2 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (memory.init 2 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (memory.init 2 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (data.drop 2) + ) + + (data passive "\00\00\00few zeroes at start") ;; 3 + + (func $few-zeroes-at-start + (memory.init 3 + (i32.const 0) + (i32.const 0) + (i32.const 22) + ) + (data.drop 3) + ) + + (data passive "zeroes at end\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 4 + + (func $zeroes-at-end + (memory.init 4 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (data.drop 4) + ) + + (data passive "zeroes at end\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 5 + + (func $zeroes-at-end-not-split + (memory.init 5 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (memory.init 5 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (memory.init 5 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (memory.init 5 + (i32.const 0) + (i32.const 0) + (i32.const 43) + ) + (data.drop 5) + ) + + (data passive "few zeroes at end\00\00\00") ;; 6 + + (func $few-zeroes-at-end + (memory.init 6 + (i32.const 0) + (i32.const 0) + (i32.const 20) + ) + (data.drop 6) + ) + + (data passive "zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00in middle") ;; 7 + + (func $zeroes-in-middle + (memory.init 7 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (data.drop 7) + ) + + (data passive "zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00in middle") ;; 8 + + (func $zeroes-in-middle-not-split + (memory.init 8 + (i32.const 0) + (i32.const 0) + (i32.const 35) + ) + (memory.init 8 + (i32.const 0) + (i32.const 0) + (i32.const 45) + ) + (data.drop 8) + ) + + (data passive "few zeroes\00\00\00in middle") ;; 9 + + (func $few-zeroes-in-middle + (memory.init 9 + (i32.const 0) + (i32.const 0) + (i32.const 22) + ) + (data.drop 9) + ) + + (data passive "multiple\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00spans\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00of zeroes") ;; 10 + + (func $multiple-spans-of-zeroes + (memory.init 10 + (i32.const 0) + (i32.const 0) + (i32.const 82) + ) + (data.drop 10) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 11 + + (func $even-more-zeroes + (memory.init 11 + (i32.const 0) + (i32.const 0) + (i32.const 134) + ) + (data.drop 11) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 12 + + (func $only-zeroes + (memory.init 12 + (i32.const 0) + (i32.const 0) + (i32.const 30) + ) + (data.drop 12) + ) + + (data passive "no zeroes") ;; 13 + + (func $no-zeroes + (memory.init 13 + (i32.const 0) + (i32.const 0) + (i32.const 9) + ) + (data.drop 13) + ) + + (data passive "") ;; 14 + + (func $empty + (memory.init 14 + (i32.const 13) + (i32.const 0) + (i32.const 0) + ) + (data.drop 14) + ) + + (data passive "only dropped") ;; 15 + + (func $only-dropped + (data.drop 15) + (data.drop 15) + ) + + (data passive "\00\00\00\00\00") ;; 16 + + (func $only-dropped-zeroes + (data.drop 16) + (data.drop 16) + ) + + (data passive "") ;; not referenced + + (data passive "\00\00\00\00\00") ;; not referenced +) + +(module + (memory $0 2048 2048) + (import "env" "param" (global $param i32)) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 0 + + (func $nonconst-dest + (memory.init 0 + (global.get $param) + (i32.const 0) + (i32.const 134) + ) + (data.drop 0) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 1 + + (func $nonconst-offset + (memory.init 1 + (i32.const 0) + (global.get $param) + (i32.const 134) + ) + (data.drop 1) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 2 + + (func $nonconst-size + (memory.init 2 + (i32.const 0) + (i32.const 0) + (global.get $param) + ) + (data.drop 2) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 3 + + (func $partial-skip-start + (memory.init 3 + (i32.const 0) + (i32.const 10) + (i32.const 124) + ) + (data.drop 3) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 4 + + (func $full-skip-start + (memory.init 4 + (i32.const 0) + (i32.const 32) + (i32.const 102) + ) + (data.drop 4) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 5 + + (func $partial-skip-end + (memory.init 5 + (i32.const 0) + (i32.const 0) + (i32.const 124) + ) + (data.drop 5) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 6 + + (func $full-skip-end + (memory.init 6 + (i32.const 0) + (i32.const 0) + (i32.const 102) + ) + (data.drop 6) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 7 + + (func $slice-zeroes + (memory.init 7 + (i32.const 0) + (i32.const 35) + (i32.const 10) + ) + (data.drop 7) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 8 + + (func $slice-nonzeroes + (memory.init 8 + (i32.const 0) + (i32.const 31) + (i32.const 2) + ) + (data.drop 8) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 9 + + (func $zero-size + (memory.init 9 + (i32.const 13) + (i32.const 40) + (i32.const 0) + ) + (data.drop 9) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 10 + + (func $zero-size-undropped + (memory.init 10 + (i32.const 13) + (i32.const 40) + (i32.const 0) + ) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 11 + + (func $out-of-bounds-offset + (memory.init 11 + (i32.const 0) + (i32.const 135) + (i32.const 1) + ) + (data.drop 11) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 12 + + (func $zero-size-out-of-bounds-offset + (memory.init 12 + (i32.const 0) + (i32.const 135) + (i32.const 0) + ) + (data.drop 12) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 13 + + (func $out-of-bounds-size + (memory.init 13 + (i32.const 0) + (i32.const 0) + (i32.const 135) + ) + (data.drop 13) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00more\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00zeroes\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") ;; 14 + + (func $zero-size-at-bounds-offset + (memory.init 14 + (i32.const 0) + (i32.const 134) + (i32.const 0) + ) + (data.drop 14) + ) +) + +(module + (memory $0 2048 2048) + (data passive "hi\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 0 + + (func $zero-length-init-zeroes + (memory.init 0 + (i32.const 13) + (i32.const 10) + (i32.const 0) + ) + (data.drop 0) + ) + + (data passive "hi\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 1 + + (func $zero-length-init-nonzeroes + (memory.init 1 + (i32.const 13) + (i32.const 33) + (i32.const 0) + ) + (data.drop 1) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 2 + + (func $zero-length-init-zeroes-2 + (memory.init 2 + (i32.const 13) + (i32.const 10) + (i32.const 0) + ) + (data.drop 2) + ) + + (data passive "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00even\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00hi") ;; 3 + + (func $zero-length-init-nonzeroes-2 + (memory.init 3 + (i32.const 13) + (i32.const 31) + (i32.const 0) + ) + (data.drop 3) + ) +) + +(module + (memory $0 2048 2048) + (data passive "a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00a") ;; 64 ranges of zeroes + + (func $init-lots + (memory.init 0 + (i32.const 0) + (i32.const 0) + (i32.const 1345) + ) + (data.drop 0) + ) +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 1024) "\00") ;; this tramples the "x", and so must be kept. +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 1025) "\00") +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 1023) "\00") +) +(module + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 1024) "\00") ;; when we see one bad thing, we give up + (data (i32.const 4096) "\00") +) +(module + (memory $0 1 1) + (import "env" "memoryBase" (global $memoryBase i32)) + (data (i32.const 1024) "x") + (data (global.get $memoryBase) "\00") ;; this could trample, or not +) +(module + (memory $0 1 1) + (import "env" "memoryBase" (global $memoryBase i32)) + (data (i32.const 1024) "\00") ;; this could trample, or not + (data (global.get $memoryBase) "x") +) +(module + (memory $0 1 1) + (data passive "skipped\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00included") + (export "func_54" (func $0)) + (func $0 + (memory.init 0 + (i32.const 0) + (i32.const 7) + (i32.const 38) + ) + ) +) +(module + ;; we can't optimize on an imported memory without zeroFilledMemory being set. + (import "env" "memory" (memory $0 1 1)) + (data (i32.const 1024) "x") + (data (i32.const 2048) "\00") +) +(module + ;; we can when not imported + (memory $0 1 1) + (data (i32.const 1024) "x") + (data (i32.const 2048) "\00") +) diff -Nru binaryen-108/test/passes/memory-packing_all-features_zero-filled-memory.txt binaryen-99/test/passes/memory-packing_all-features_zero-filled-memory.txt --- binaryen-108/test/passes/memory-packing_all-features_zero-filled-memory.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/memory-packing_all-features_zero-filled-memory.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,4 @@ +(module + (import "env" "memory" (memory $0 1 1)) + (data (i32.const 1024) "x") +) diff -Nru binaryen-108/test/passes/memory-packing_all-features_zero-filled-memory.wast binaryen-99/test/passes/memory-packing_all-features_zero-filled-memory.wast --- binaryen-108/test/passes/memory-packing_all-features_zero-filled-memory.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/memory-packing_all-features_zero-filled-memory.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,6 @@ +(module + ;; we can optimize on an imported memory with zeroFilledMemory being set. + (import "env" "memory" (memory $0 1 1)) + (data (i32.const 1024) "x") + (data (i32.const 1023) "\00") +) diff -Nru binaryen-108/test/passes/merge-locals_all-features.txt binaryen-99/test/passes/merge-locals_all-features.txt --- binaryen-108/test/passes/merge-locals_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/merge-locals_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_f32_f32_=>_i64 (func (param i32 f32 f32) (result i64))) - (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_none (func)) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_f32_f32_=>_i64 (func (param i32 f32 f32) (result i64))) (global $global$0 (mut i32) (i32.const 10)) (func $test (param $x i32) (param $y i32) (result i32) (drop diff -Nru binaryen-108/test/passes/metrics_all-features.txt binaryen-99/test/passes/metrics_all-features.txt --- binaryen-108/test/passes/metrics_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/metrics_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,30 +1,28 @@ total + [events] : 2 [exports] : 0 [funcs] : 1 [globals] : 1 [imports] : 0 [memory-data] : 9 [table-data] : 3 - [tables] : 1 - [tags] : 2 - [total] : 30 + [total] : 27 [vars] : 1 - Binary : 1 - Block : 1 - Const : 15 - Drop : 6 - If : 4 - RefFunc : 3 + binary : 1 + block : 1 + const : 15 + drop : 6 + if : 4 (module - (type $0 (func (param i32))) + (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) - (global $glob i32 (i32.const 1337)) (memory $0 256 256) (data (i32.const 0) "\ff\ef\0f\1f 0@P\99") (table $0 256 256 funcref) (elem (i32.const 0) $ifs $ifs $ifs) - (tag $e0 (param i32)) - (tag $e1 (param i32 i32)) + (global $glob i32 (i32.const 1337)) + (event $e0 (attr 0) (param i32)) + (event $e1 (attr 0) (param i32 i32)) (func $ifs (param $x i32) (local $y f32) (block $block0 @@ -66,12 +64,11 @@ ) ) total + [events] : 0 [exports] : 0 [funcs] : 0 [globals] : 0 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 0 [vars] : 0 (module diff -Nru binaryen-108/test/passes/metrics_all-features.wast binaryen-99/test/passes/metrics_all-features.wast --- binaryen-108/test/passes/metrics_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/metrics_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -5,8 +5,8 @@ (data (i32.const 0) "\ff\ef\0f\1f\20\30\40\50\99") (type $0 (func (param i32))) (global $glob i32 (i32.const 1337)) - (tag $e0 (param i32)) - (tag $e1 (param i32 i32)) + (event $e0 (attr 0) (param i32)) + (event $e1 (attr 0) (param i32 i32)) (func $ifs (type $0) (param $x i32) (local $y f32) (block $block0 diff -Nru binaryen-108/test/passes/metrics_strip-debug_metrics.bin.txt binaryen-99/test/passes/metrics_strip-debug_metrics.bin.txt --- binaryen-108/test/passes/metrics_strip-debug_metrics.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/metrics_strip-debug_metrics.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,23 +1,21 @@ total + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 0 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 1 [vars] : 0 - Nop : 1 + nop : 1 total + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 0 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 1 [vars] : 0 - Nop : 1 + nop : 1 (module (type $none_=>_none (func)) (export "a" (func $0)) diff -Nru binaryen-108/test/passes/metrics_strip-producers_metrics.bin.txt binaryen-99/test/passes/metrics_strip-producers_metrics.bin.txt --- binaryen-108/test/passes/metrics_strip-producers_metrics.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/metrics_strip-producers_metrics.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,23 +1,21 @@ total + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 0 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 1 [vars] : 0 - Nop : 1 + nop : 1 total + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 0 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 1 [vars] : 0 - Nop : 1 + nop : 1 (module (type $none_=>_none (func)) (export "a" (func $0)) diff -Nru binaryen-108/test/passes/minify-imports_all-features.txt binaryen-99/test/passes/minify-imports_all-features.txt --- binaryen-108/test/passes/minify-imports_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/minify-imports_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1128,7 +1128,7 @@ longname1490 => LA longname4946 => LAa longname1544 => LB -tagname1 => LBa +eventname1 => LBa longname1598 => LC longname1652 => LD longname1706 => LE @@ -10008,11 +10008,11 @@ (import "env" "JBa" (func $internal4998)) (import "env" "KBa" (func $internal4999)) (import "other" "anything" (func $internalInfinity)) - (import "env" "LBa" (tag $tagname1 (param i32))) - (tag $tag1 (param i32 i32)) + (import "env" "LBa" (event $eventname1 (attr 0) (param i32))) + (event $event1 (attr 0) (param i32 i32)) (export "foo1" (func $foo1)) (export "foo2" (func $foo2)) - (export "tag1" (tag $tag1)) + (export "event1" (event $event1)) (func $foo1 (nop) ) diff -Nru binaryen-108/test/passes/minify-imports_all-features.wast binaryen-99/test/passes/minify-imports_all-features.wast --- binaryen-108/test/passes/minify-imports_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/minify-imports_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -5002,11 +5002,11 @@ (import "env" "__memory_base" (global i32)) (import "env" "__table_base" (global i32)) (import "other" "anything" (func $internalInfinity)) - (import "env" "tagname1" (tag $tagname1 (param i32))) + (import "env" "eventname1" (event $eventname1 (attr 0) (param i32))) (export "foo1" (func $foo1)) (export "foo2" (func $foo2)) - (export "tag1" (tag $tag1)) + (export "event1" (event $event1)) (func $foo1) (func $foo2) - (tag $tag1 (param i32 i32)) + (event $event1 (attr 0) (param i32 i32)) ) diff -Nru binaryen-108/test/passes/minify-imports-and-exports_all-features.txt binaryen-99/test/passes/minify-imports-and-exports_all-features.txt --- binaryen-108/test/passes/minify-imports-and-exports_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/minify-imports-and-exports_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1221,7 +1221,7 @@ longname1491 => MA longname4947 => MAa longname1545 => MB -tagname1 => MBa +eventname1 => MBa longname1599 => MC longname1653 => MD longname1707 => ME @@ -1500,7 +1500,7 @@ longname1494 => PA longname4950 => PAa longname1548 => PB -tag1 => PBa +event1 => PBa longname1602 => PC longname1656 => PD longname1710 => PE @@ -10014,11 +10014,11 @@ (import "other" "anything" (func $internalInfinity)) (import "wasi_unstable" "f" (func $internal3_wasi)) (import "wasi_unstable" "LBa" (func $internal3_wasi_only)) - (import "env" "MBa" (tag $tagname1 (param i32))) - (tag $tag1 (param i32 i32)) + (import "env" "MBa" (event $eventname1 (attr 0) (param i32))) + (event $event1 (attr 0) (param i32 i32)) (export "NBa" (func $foo1)) (export "OBa" (func $foo2)) - (export "PBa" (tag $tag1)) + (export "PBa" (event $event1)) (func $foo1 (nop) ) diff -Nru binaryen-108/test/passes/minify-imports-and-exports_all-features.wast binaryen-99/test/passes/minify-imports-and-exports_all-features.wast --- binaryen-108/test/passes/minify-imports-and-exports_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/minify-imports-and-exports_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -5002,13 +5002,13 @@ (import "env" "__memory_base" (global i32)) (import "env" "__table_base" (global i32)) (import "other" "anything" (func $internalInfinity)) - (import "env" "tagname1" (tag $tagname1 (param i32))) + (import "env" "eventname1" (event $eventname1 (attr 0) (param i32))) (import "wasi_unstable" "longname3" (func $internal3_wasi)) ;; overlapping base (import "wasi_unstable" "longname3-only" (func $internal3_wasi_only)) (export "exp1" (func $foo1)) (export "exp2" (func $foo2)) (func $foo1) (func $foo2) - (export "tag1" (tag $tag1)) - (tag $tag1 (param i32 i32)) + (export "event1" (event $event1)) + (event $event1 (attr 0) (param i32 i32)) ) diff -Nru binaryen-108/test/passes/nm.txt binaryen-99/test/passes/nm.txt --- binaryen-108/test/passes/nm.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/nm.txt 2021-01-07 20:01:06.000000000 +0000 @@ -2,7 +2,7 @@ b : 5 c : 13 (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $a (nop) diff -Nru binaryen-108/test/passes/no-exit-runtime.txt binaryen-99/test/passes/no-exit-runtime.txt --- binaryen-108/test/passes/no-exit-runtime.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/no-exit-runtime.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,166 @@ +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (import "env" "atexit" (func $fimport$0 (param i32 i32) (result i32))) + (import "env" "__cxa_atexit" (func $fimport$1 (param i32 i32) (result i32))) + (import "env" "_atexit" (func $fimport$2 (param i32 i32) (result i32))) + (import "env" "___cxa_atexit" (func $fimport$3 (param i32 i32) (result i32))) + (import "env" "other" (func $fimport$4 (param i32 i32) (result i32))) + (func $caller + (drop + (block (result i32) + (drop + (i32.const 0) + ) + (drop + (i32.const 1) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (i32.const 0) + ) + (drop + (i32.const 1) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (i32.const 0) + ) + (drop + (i32.const 1) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (i32.const 0) + ) + (drop + (i32.const 1) + ) + (i32.const 0) + ) + ) + (drop + (call $fimport$4 + (i32.const 0) + (i32.const 1) + ) + ) + (drop + (block + (drop + (unreachable) + ) + (drop + (i32.const 1) + ) + (unreachable) + ) + ) + ) + (func $side-effects (result i32) + (local $x i32) + (drop + (block (result i32) + (drop + (local.tee $x + (i32.const 1) + ) + ) + (drop + (i32.const 2) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (i32.const 3) + ) + (drop + (local.tee $x + (i32.const 4) + ) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (local.tee $x + (i32.const 5) + ) + ) + (drop + (local.tee $x + (i32.const 6) + ) + ) + (i32.const 0) + ) + ) + (drop + (block + (drop + (unreachable) + ) + (drop + (local.tee $x + (i32.const 7) + ) + ) + (unreachable) + ) + ) + (drop + (block + (drop + (local.tee $x + (i32.const 8) + ) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (drop + (block + (drop + (unreachable) + ) + (drop + (i32.const 9) + ) + (unreachable) + ) + ) + (drop + (block + (drop + (i32.const 10) + ) + (drop + (unreachable) + ) + (unreachable) + ) + ) + (local.get $x) + ) +) diff -Nru binaryen-108/test/passes/no-exit-runtime.wast binaryen-99/test/passes/no-exit-runtime.wast --- binaryen-108/test/passes/no-exit-runtime.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/no-exit-runtime.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,47 @@ +(module + (import "env" "atexit" (func $fimport$0 (param i32 i32) (result i32))) + (import "env" "__cxa_atexit" (func $fimport$1 (param i32 i32) (result i32))) + (import "env" "_atexit" (func $fimport$2 (param i32 i32) (result i32))) + (import "env" "___cxa_atexit" (func $fimport$3 (param i32 i32) (result i32))) + (import "env" "other" (func $fimport$4 (param i32 i32) (result i32))) + (func $caller + (drop (call $fimport$0 (i32.const 0) (i32.const 1))) + (drop (call $fimport$1 (i32.const 0) (i32.const 1))) + (drop (call $fimport$2 (i32.const 0) (i32.const 1))) + (drop (call $fimport$3 (i32.const 0) (i32.const 1))) + (drop (call $fimport$4 (i32.const 0) (i32.const 1))) + (drop (call $fimport$0 (unreachable) (i32.const 1))) + ) + (func $side-effects (result i32) + (local $x i32) + (drop (call $fimport$0 + (local.tee $x (i32.const 1)) + (i32.const 2) + )) + (drop (call $fimport$0 + (i32.const 3) + (local.tee $x (i32.const 4)) + )) + (drop (call $fimport$0 + (local.tee $x (i32.const 5)) + (local.tee $x (i32.const 6)) + )) + (drop (call $fimport$0 + (unreachable) + (local.tee $x (i32.const 7)) + )) + (drop (call $fimport$0 + (local.tee $x (i32.const 8)) + (unreachable) + )) + (drop (call $fimport$0 + (unreachable) + (i32.const 9) + )) + (drop (call $fimport$0 + (i32.const 10) + (unreachable) + )) + (local.get $x) + ) +) diff -Nru binaryen-108/test/passes/O1.txt binaryen-99/test/passes/O1.txt --- binaryen-108/test/passes/O1.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O1.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,13 @@ +(module + (type $none_=>_i32 (func (result i32))) + (memory $0 1 1) + (export "foo" (func $0)) + (func $0 (result i32) + (drop + (i32.const 0) + ) + (i32.load align=1 + (i32.const 4) + ) + ) +) diff -Nru binaryen-108/test/passes/O1.wast binaryen-99/test/passes/O1.wast --- binaryen-108/test/passes/O1.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O1.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,25 @@ +(module + (memory $0 1 1) + (global $global$0 (mut i32) (i32.const 10)) + (func "foo" (result i32) + (i32.load offset=4 align=1 + (i32.and + (block $label$1 (result i32) + (global.set $global$0 + (i32.const 0) + ) + (i32.const -64) + ) + (i32.const 15) + ) + ) + ) + (func $signed-overflow (param $0 f32) (result i32) + (i32.sub + (i32.const 268435456) + (i32.const -2147483648) + ) + ) +) + + diff -Nru binaryen-108/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.txt binaryen-99/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.txt --- binaryen-108/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,95 @@ +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (memory $memory 0) + (export "fib" (func $fib)) + (export "looped" (func $looped)) + (export "t0" (func $looped)) + (export "t1" (func $t1)) + (export "t2" (func $t2)) + (export "t3" (func $t3)) + (export "memory" (memory $memory)) + (func $fib (; has Stack IR ;) (param $0 i32) (result i32) + (if + (i32.le_s + (local.get $0) + (i32.const 2) + ) + (return + (local.get $0) + ) + ) + (i32.add + (call $fib + (i32.sub + (local.get $0) + (i32.const 1) + ) + ) + (call $fib + (i32.sub + (local.get $0) + (i32.const 2) + ) + ) + ) + ) + (func $looped (; has Stack IR ;) (param $0 i32) (result i32) + (loop $L0 + (if + (i32.ge_s + (local.get $0) + (i32.const 0) + ) + (block + (local.set $0 + (i32.sub + (local.get $0) + (i32.const 1) + ) + ) + (br $L0) + ) + ) + ) + (local.get $0) + ) + (func $t1 (; has Stack IR ;) (param $0 i32) (result i32) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (loop $L0 + (if + (i32.ge_s + (local.get $0) + (i32.const 0) + ) + (block + (local.set $0 + (i32.sub + (local.get $0) + (i32.const 1) + ) + ) + (br $L0) + ) + ) + ) + (local.get $0) + ) + (func $t2 (; has Stack IR ;) (param $0 i32) (result i32) + (call $fib + (local.get $0) + ) + ) + (func $t3 (; has Stack IR ;) (param $0 i32) (result i32) + (call $fib + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast binaryen-99/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast --- binaryen-108/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,80 @@ +(module + (type $t0 (func (param i32) (result i32))) + (func $fib (export "fib") (type $t0) (param $p0 i32) (result i32) + (if $I0 + (i32.le_s + (local.get $p0) + (i32.const 2) + ) + (then + (return + (local.get $p0) + ) + ) + ) + (i32.add + (call $fib + (i32.sub + (local.get $p0) + (i32.const 1) + ) + ) + (call $fib + (i32.sub + (local.get $p0) + (i32.const 2) + ) + ) + ) + ) + (func $looped (export "looped") (type $t0) (param $p0 i32) (result i32) + (loop $L0 + (if $I1 + (i32.ge_s + (local.get $p0) + (i32.const 0) + ) + (then + (local.set $p0 + (i32.sub + (local.get $p0) + (i32.const 1) + ) + ) + (br $L0) + ) + ) + ) + (local.get $p0) + ) + + (func $t0 (export "t0") (type $t0) (param $p0 i32) (result i32) + (call $looped + (local.get $p0) + ) + ) + + (func $t1 (export "t1") (type $t0) (param $p0 i32) (result i32) + (call $looped + (i32.add + (local.get $p0) + (i32.const 1) + ) + ) + ) + (func $t2 (export "t2") (type $t0) (param $p0 i32) (result i32) + (call $fib + (local.get $p0) + ) + ) + + (func $t3 (export "t3") (type $t0) (param $p0 i32) (result i32) + (call $fib + (i32.add + (local.get $p0) + (i32.const 1) + ) + ) + ) + (memory $memory (export "memory") 0) +) diff -Nru binaryen-108/test/passes/O3_inlining.txt binaryen-99/test/passes/O3_inlining.txt --- binaryen-108/test/passes/O3_inlining.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O3_inlining.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,23 @@ +(module + (type $i32_=>_none (func (param i32))) + (memory $0 1 1) + (global $global$1 (mut i32) (i32.const 100)) + (export "func_217" (func $1)) + (func $1 (param $0 i32) + (if + (global.get $global$1) + (unreachable) + ) + (global.set $global$1 + (i32.const 0) + ) + (if + (i32.eqz + (i32.load16_u + (i32.const 3) + ) + ) + (unreachable) + ) + ) +) diff -Nru binaryen-108/test/passes/O3_inlining.wast binaryen-99/test/passes/O3_inlining.wast --- binaryen-108/test/passes/O3_inlining.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O3_inlining.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,44 @@ +(module + (global $global$0 (mut f64) (f64.const -32768)) + (global $global$1 (mut i32) (i32.const 100)) + (memory $0 1 1) + (export "func_217" (func $1)) + (func $0 + (if + (global.get $global$1) + (unreachable) + ) + (global.set $global$1 + (i32.const 0) + ) + (block $label$2 + (global.set $global$0 + (block $label$3 (result f64) + (br_if $label$2 + (if (result i32) + (i32.load16_u offset=3 + (i32.const 0) + ) + (i32.const 1) + (i32.const 0) + ) + ) + (unreachable) + ) + ) + ) + ) + (func $1 (param $var$0 i32) + (drop + (call $2 + (f32.const 1) + (i32.const 1) + (i32.const 0) + ) + ) + ) + (func $2 (param $var$0 f32) (param $var$1 i32) (param $var$2 i32) (result i32) + (call $0) + (i32.const 0) + ) +) diff -Nru binaryen-108/test/passes/O3_low-memory-unused_metrics.txt binaryen-99/test/passes/O3_low-memory-unused_metrics.txt --- binaryen-108/test/passes/O3_low-memory-unused_metrics.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/O3_low-memory-unused_metrics.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,35 +1,34 @@ total + [events] : 0 [exports] : 1 [funcs] : 1 [globals] : 0 [imports] : 10 [memory-data] : 0 [table-data] : 0 - [tables] : 0 - [tags] : 0 [total] : 1964 [vars] : 9 - Binary : 240 - Block : 68 - Break : 90 - Call : 22 - CallIndirect : 1 - Const : 175 - Drop : 8 - If : 27 - Load : 313 - LocalGet : 633 - LocalSet : 181 - Loop : 3 - Return : 3 - Select : 11 - Store : 160 - Unary : 29 + binary : 240 + block : 68 + break : 90 + call : 22 + call_indirect : 1 + const : 175 + drop : 8 + if : 27 + load : 313 + local.get : 633 + local.set : 181 + loop : 3 + return : 3 + select : 11 + store : 160 + unary : 29 (module - (type $0 (func (param i32 i32 i32) (result i32))) - (type $2 (func (param i32 i32) (result i32))) - (type $3 (func (param i32 i32 i32 i32))) - (type $10 (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (import "env" "memory" (memory $108 4096 4096)) (import "env" "table" (table $timport$109 10 funcref)) (import "env" "crc32" (func $fimport$14 (param i32 i32 i32) (result i32))) @@ -2445,7 +2444,7 @@ ) ) ) - (call_indirect (type $2) + (call_indirect (type $i32_i32_=>_i32) (local.get $2) (local.get $1) (i32.load @@ -2688,13 +2687,13 @@ (i32.const 1) ) (br_if $label$1 - (i32.le_s + (i32.lt_s (local.tee $4 (i32.load offset=24 (local.get $2) ) ) - (i32.const 0) + (i32.const 1) ) ) (local.set $1 @@ -3106,13 +3105,13 @@ ) ) (if - (i32.gt_s + (i32.ge_s (local.tee $0 (i32.load offset=24 (local.get $2) ) ) - (i32.const 0) + (i32.const 1) ) (i32.store offset=24 (local.get $2) diff -Nru binaryen-108/test/passes/O4_disable-bulk-memory.txt binaryen-99/test/passes/O4_disable-bulk-memory.txt --- binaryen-108/test/passes/O4_disable-bulk-memory.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O4_disable-bulk-memory.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1282 @@ +(module + (type $none_=>_none (func)) + (export "func_59_invoker" (func $0)) + (func $0 (; has Stack IR ;) + (unreachable) + ) +) +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $f64_f64_f64_f64_f64_f64_f64_=>_i32 (func (param f64 f64 f64 f64 f64 f64 f64) (result i32))) + (type $none_=>_f64 (func (result f64))) + (type $i32_=>_f64 (func (param i32) (result f64))) + (import "env" "memory" (memory $1 1)) + (data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00") + (data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00") + (table $0 1 funcref) + (elem (i32.const 0) $null) + (global $global$0 (mut i32) (i32.const 0)) + (global $global$1 (mut i32) (i32.const 0)) + (global $global$5 (mut i32) (i32.const 0)) + (export "memory" (memory $0)) + (export "table" (table $0)) + (export "init" (func $assembly/index/init)) + (export "step" (func $assembly/index/step)) + (export "bench" (func $assembly/index/bench)) + (export "getBody" (func $assembly/index/getBody)) + (start $start) + (func $~lib/allocator/arena/__memory_allocate (; has Stack IR ;) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (if + (i32.gt_u + (local.get $0) + (i32.const 1073741824) + ) + (unreachable) + ) + (if + (i32.gt_u + (local.tee $0 + (i32.and + (i32.add + (i32.add + (local.tee $1 + (global.get $global$1) + ) + (select + (local.get $0) + (i32.const 1) + (i32.gt_u + (local.get $0) + (i32.const 1) + ) + ) + ) + (i32.const 7) + ) + (i32.const -8) + ) + ) + (i32.shl + (local.tee $2 + (memory.size) + ) + (i32.const 16) + ) + ) + (if + (i32.lt_s + (memory.grow + (select + (local.get $2) + (local.tee $3 + (i32.shr_u + (i32.and + (i32.add + (i32.sub + (local.get $0) + (local.get $1) + ) + (i32.const 65535) + ) + (i32.const -65536) + ) + (i32.const 16) + ) + ) + (i32.gt_s + (local.get $2) + (local.get $3) + ) + ) + ) + (i32.const 0) + ) + (if + (i32.lt_s + (memory.grow + (local.get $3) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + (global.set $global$1 + (local.get $0) + ) + (local.get $1) + ) + (func $assembly/index/NBodySystem#constructor (; has Stack IR ;) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 f64) + (local $4 f64) + (local $5 f64) + (local $6 f64) + (local $7 i32) + (local.set $7 + (i32.load offset=4 + (local.get $0) + ) + ) + (loop $label$3 + (if + (i32.lt_s + (local.get $1) + (local.get $7) + ) + (block + (local.set $3 + (f64.load offset=48 + (local.tee $2 + (i32.load offset=8 + (i32.add + (i32.load + (local.get $0) + ) + (i32.shl + (local.get $1) + (i32.const 2) + ) + ) + ) + ) + ) + ) + (local.set $4 + (f64.add + (local.get $4) + (f64.mul + (f64.load offset=24 + (local.get $2) + ) + (local.get $3) + ) + ) + ) + (local.set $5 + (f64.add + (local.get $5) + (f64.mul + (f64.load offset=32 + (local.get $2) + ) + (local.get $3) + ) + ) + ) + (local.set $6 + (f64.add + (local.get $6) + (f64.mul + (f64.load offset=40 + (local.get $2) + ) + (local.get $3) + ) + ) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br $label$3) + ) + ) + ) + (f64.store offset=24 + (local.tee $1 + (if (result i32) + (i32.shr_u + (i32.load + (local.tee $1 + (i32.load + (local.get $0) + ) + ) + ) + (i32.const 2) + ) + (i32.load offset=8 + (local.get $1) + ) + (unreachable) + ) + ) + (f64.div + (local.get $4) + (f64.const -39.47841760435743) + ) + ) + (f64.store offset=32 + (local.get $1) + (f64.div + (local.get $5) + (f64.const -39.47841760435743) + ) + ) + (f64.store offset=40 + (local.get $1) + (f64.div + (local.get $6) + (f64.const -39.47841760435743) + ) + ) + (i32.store + (local.tee $1 + (call $~lib/allocator/arena/__memory_allocate + (i32.const 4) + ) + ) + (local.get $0) + ) + (local.get $1) + ) + (func $assembly/index/Body#constructor (; has Stack IR ;) (param $0 f64) (param $1 f64) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 f64) (param $6 f64) (result i32) + (local $7 i32) + (f64.store + (local.tee $7 + (call $~lib/allocator/arena/__memory_allocate + (i32.const 56) + ) + ) + (local.get $0) + ) + (f64.store offset=8 + (local.get $7) + (local.get $1) + ) + (f64.store offset=16 + (local.get $7) + (local.get $2) + ) + (f64.store offset=24 + (local.get $7) + (local.get $3) + ) + (f64.store offset=32 + (local.get $7) + (local.get $4) + ) + (f64.store offset=40 + (local.get $7) + (local.get $5) + ) + (f64.store offset=48 + (local.get $7) + (local.get $6) + ) + (local.get $7) + ) + (func $~lib/internal/memory/memset (; has Stack IR ;) (param $0 i32) + (local $1 i32) + (local $2 i32) + (i32.store8 + (local.get $0) + (i32.const 0) + ) + (i32.store8 + (i32.sub + (local.tee $1 + (i32.add + (local.get $0) + (i32.const 20) + ) + ) + (i32.const 1) + ) + (i32.const 0) + ) + (i32.store8 + (i32.add + (local.get $0) + (i32.const 1) + ) + (i32.const 0) + ) + (i32.store8 + (i32.add + (local.get $0) + (i32.const 2) + ) + (i32.const 0) + ) + (i32.store8 + (i32.sub + (local.get $1) + (i32.const 2) + ) + (i32.const 0) + ) + (i32.store8 + (i32.sub + (local.get $1) + (i32.const 3) + ) + (i32.const 0) + ) + (i32.store8 + (i32.add + (local.get $0) + (i32.const 3) + ) + (i32.const 0) + ) + (i32.store8 + (i32.sub + (local.get $1) + (i32.const 4) + ) + (i32.const 0) + ) + (i32.store + (local.tee $0 + (i32.add + (local.tee $1 + (i32.and + (i32.sub + (i32.const 0) + (local.get $0) + ) + (i32.const 3) + ) + ) + (local.get $0) + ) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (i32.add + (local.tee $1 + (i32.and + (i32.sub + (i32.const 20) + (local.get $1) + ) + (i32.const -4) + ) + ) + (local.get $0) + ) + (i32.const 4) + ) + (i32.const 0) + ) + (if + (i32.le_u + (local.get $1) + (i32.const 8) + ) + (return) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 4) + ) + (i32.const 0) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 8) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (local.tee $2 + (i32.add + (local.get $0) + (local.get $1) + ) + ) + (i32.const 12) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (local.get $2) + (i32.const 8) + ) + (i32.const 0) + ) + (if + (i32.le_u + (local.get $1) + (i32.const 24) + ) + (return) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 12) + ) + (i32.const 0) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 16) + ) + (i32.const 0) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 20) + ) + (i32.const 0) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 24) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (local.tee $2 + (i32.add + (local.get $0) + (local.get $1) + ) + ) + (i32.const 28) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (local.get $2) + (i32.const 24) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (local.get $2) + (i32.const 20) + ) + (i32.const 0) + ) + (i32.store + (i32.sub + (local.get $2) + (i32.const 16) + ) + (i32.const 0) + ) + (local.set $0 + (i32.add + (local.tee $2 + (i32.add + (i32.and + (local.get $0) + (i32.const 4) + ) + (i32.const 24) + ) + ) + (local.get $0) + ) + ) + (local.set $1 + (i32.sub + (local.get $1) + (local.get $2) + ) + ) + (loop $label$8 + (if + (i32.ge_u + (local.get $1) + (i32.const 32) + ) + (block + (i64.store + (local.get $0) + (i64.const 0) + ) + (i64.store + (i32.add + (local.get $0) + (i32.const 8) + ) + (i64.const 0) + ) + (i64.store + (i32.add + (local.get $0) + (i32.const 16) + ) + (i64.const 0) + ) + (i64.store + (i32.add + (local.get $0) + (i32.const 24) + ) + (i64.const 0) + ) + (local.set $1 + (i32.sub + (local.get $1) + (i32.const 32) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 32) + ) + ) + (br $label$8) + ) + ) + ) + ) + (func $~lib/array/Array#constructor (; has Stack IR ;) (result i32) + (local $0 i32) + (local $1 i32) + (i32.store + (local.tee $1 + (call $~lib/allocator/arena/__memory_allocate + (i32.const 32) + ) + ) + (i32.const 20) + ) + (i32.store + (local.tee $0 + (call $~lib/allocator/arena/__memory_allocate + (i32.const 8) + ) + ) + (i32.const 0) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (i32.store + (local.get $0) + (local.get $1) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 5) + ) + (call $~lib/internal/memory/memset + (i32.add + (local.get $1) + (i32.const 8) + ) + ) + (local.get $0) + ) + (func $assembly/index/init (; has Stack IR ;) + (local $0 i32) + (local $1 i32) + (local.set $1 + (call $~lib/array/Array#constructor) + ) + (local.set $0 + (call $assembly/index/Body#constructor + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 39.47841760435743) + ) + ) + (i32.store offset=8 + (i32.load + (local.get $1) + ) + (local.get $0) + ) + (local.set $0 + (call $assembly/index/Body#constructor + (f64.const 4.841431442464721) + (f64.const -1.1603200440274284) + (f64.const -0.10362204447112311) + (f64.const 0.606326392995832) + (f64.const 2.81198684491626) + (f64.const -0.02521836165988763) + (f64.const 0.03769367487038949) + ) + ) + (i32.store offset=8 + (i32.add + (i32.load + (local.get $1) + ) + (i32.const 4) + ) + (local.get $0) + ) + (local.set $0 + (call $assembly/index/Body#constructor + (f64.const 8.34336671824458) + (f64.const 4.124798564124305) + (f64.const -0.4035234171143214) + (f64.const -1.0107743461787924) + (f64.const 1.8256623712304119) + (f64.const 0.008415761376584154) + (f64.const 0.011286326131968767) + ) + ) + (i32.store offset=8 + (i32.add + (i32.load + (local.get $1) + ) + (i32.const 8) + ) + (local.get $0) + ) + (local.set $0 + (call $assembly/index/Body#constructor + (f64.const 12.894369562139131) + (f64.const -15.111151401698631) + (f64.const -0.22330757889265573) + (f64.const 1.0827910064415354) + (f64.const 0.8687130181696082) + (f64.const -0.010832637401363636) + (f64.const 1.7237240570597112e-03) + ) + ) + (i32.store offset=8 + (i32.add + (i32.load + (local.get $1) + ) + (i32.const 12) + ) + (local.get $0) + ) + (local.set $0 + (call $assembly/index/Body#constructor + (f64.const 15.379697114850917) + (f64.const -25.919314609987964) + (f64.const 0.17925877295037118) + (f64.const 0.979090732243898) + (f64.const 0.5946989986476762) + (f64.const -0.034755955504078104) + (f64.const 2.0336868699246304e-03) + ) + ) + (i32.store offset=8 + (i32.add + (i32.load + (local.get $1) + ) + (i32.const 16) + ) + (local.get $0) + ) + (global.set $global$5 + (call $assembly/index/NBodySystem#constructor + (local.get $1) + ) + ) + ) + (func $assembly/index/NBodySystem#advance (; has Stack IR ;) (param $0 i32) + (local $1 i32) + (local $2 f64) + (local $3 i32) + (local $4 f64) + (local $5 f64) + (local $6 f64) + (local $7 i32) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local $11 f64) + (local $12 i32) + (local $13 i32) + (local $14 f64) + (local $15 f64) + (local $16 f64) + (local $17 f64) + (local.set $13 + (i32.load offset=4 + (local.tee $12 + (i32.load + (local.get $0) + ) + ) + ) + ) + (loop $label$3 + (if + (i32.lt_u + (local.get $3) + (local.get $13) + ) + (block + (local.set $14 + (f64.load + (local.tee $0 + (i32.load offset=8 + (i32.add + (i32.load + (local.get $12) + ) + (i32.shl + (local.get $3) + (i32.const 2) + ) + ) + ) + ) + ) + ) + (local.set $15 + (f64.load offset=8 + (local.get $0) + ) + ) + (local.set $16 + (f64.load offset=16 + (local.get $0) + ) + ) + (local.set $4 + (f64.load offset=24 + (local.get $0) + ) + ) + (local.set $5 + (f64.load offset=32 + (local.get $0) + ) + ) + (local.set $6 + (f64.load offset=40 + (local.get $0) + ) + ) + (local.set $17 + (f64.load offset=48 + (local.get $0) + ) + ) + (local.set $7 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (loop $label$6 + (if + (i32.lt_u + (local.get $7) + (local.get $13) + ) + (block + (local.set $11 + (f64.sqrt + (local.tee $8 + (f64.add + (f64.add + (f64.mul + (local.tee $2 + (f64.sub + (local.get $14) + (f64.load + (local.tee $1 + (i32.load offset=8 + (i32.add + (i32.load + (local.get $12) + ) + (i32.shl + (local.get $7) + (i32.const 2) + ) + ) + ) + ) + ) + ) + ) + (local.get $2) + ) + (f64.mul + (local.tee $9 + (f64.sub + (local.get $15) + (f64.load offset=8 + (local.get $1) + ) + ) + ) + (local.get $9) + ) + ) + (f64.mul + (local.tee $10 + (f64.sub + (local.get $16) + (f64.load offset=16 + (local.get $1) + ) + ) + ) + (local.get $10) + ) + ) + ) + ) + ) + (local.set $4 + (f64.sub + (local.get $4) + (f64.mul + (local.get $2) + (local.tee $8 + (f64.mul + (f64.load offset=48 + (local.get $1) + ) + (local.tee $11 + (f64.div + (f64.const 0.01) + (f64.mul + (local.get $8) + (local.get $11) + ) + ) + ) + ) + ) + ) + ) + ) + (local.set $5 + (f64.sub + (local.get $5) + (f64.mul + (local.get $9) + (local.get $8) + ) + ) + ) + (local.set $6 + (f64.sub + (local.get $6) + (f64.mul + (local.get $10) + (local.get $8) + ) + ) + ) + (f64.store offset=24 + (local.get $1) + (f64.add + (f64.load offset=24 + (local.get $1) + ) + (f64.mul + (local.get $2) + (local.tee $2 + (f64.mul + (local.get $17) + (local.get $11) + ) + ) + ) + ) + ) + (f64.store offset=32 + (local.get $1) + (f64.add + (f64.load offset=32 + (local.get $1) + ) + (f64.mul + (local.get $9) + (local.get $2) + ) + ) + ) + (f64.store offset=40 + (local.get $1) + (f64.add + (f64.load offset=40 + (local.get $1) + ) + (f64.mul + (local.get $10) + (local.get $2) + ) + ) + ) + (local.set $7 + (i32.add + (local.get $7) + (i32.const 1) + ) + ) + (br $label$6) + ) + ) + ) + (f64.store offset=24 + (local.get $0) + (local.get $4) + ) + (f64.store offset=32 + (local.get $0) + (local.get $5) + ) + (f64.store offset=40 + (local.get $0) + (local.get $6) + ) + (f64.store + (local.get $0) + (f64.add + (f64.load + (local.get $0) + ) + (f64.mul + (local.get $4) + (f64.const 0.01) + ) + ) + ) + (f64.store offset=8 + (local.get $0) + (f64.add + (f64.load offset=8 + (local.get $0) + ) + (f64.mul + (local.get $5) + (f64.const 0.01) + ) + ) + ) + (f64.store offset=16 + (local.get $0) + (f64.add + (f64.load offset=16 + (local.get $0) + ) + (f64.mul + (local.get $6) + (f64.const 0.01) + ) + ) + ) + (local.set $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (br $label$3) + ) + ) + ) + ) + (func $assembly/index/NBodySystem#energy (; has Stack IR ;) (param $0 i32) (result f64) + (local $1 f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 f64) + (local $7 f64) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local.set $5 + (i32.load offset=4 + (local.tee $4 + (i32.load + (local.get $0) + ) + ) + ) + ) + (loop $label$4 + (if + (i32.lt_u + (local.get $2) + (local.get $5) + ) + (block + (local.set $7 + (f64.load + (local.tee $0 + (i32.load offset=8 + (i32.add + (i32.load + (local.get $4) + ) + (i32.shl + (local.get $2) + (i32.const 2) + ) + ) + ) + ) + ) + ) + (local.set $8 + (f64.load offset=8 + (local.get $0) + ) + ) + (local.set $9 + (f64.load offset=16 + (local.get $0) + ) + ) + (local.set $1 + (f64.add + (local.get $1) + (f64.mul + (f64.mul + (local.tee $10 + (f64.load offset=48 + (local.get $0) + ) + ) + (f64.const 0.5) + ) + (f64.add + (f64.add + (f64.mul + (local.tee $1 + (f64.load offset=24 + (local.get $0) + ) + ) + (local.get $1) + ) + (f64.mul + (local.tee $1 + (f64.load offset=32 + (local.get $0) + ) + ) + (local.get $1) + ) + ) + (f64.mul + (local.tee $1 + (f64.load offset=40 + (local.get $0) + ) + ) + (local.get $1) + ) + ) + ) + ) + ) + (local.set $0 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (loop $label$7 + (if + (i32.lt_u + (local.get $0) + (local.get $5) + ) + (block + (local.set $6 + (f64.sub + (local.get $7) + (f64.load + (local.tee $3 + (i32.load offset=8 + (i32.add + (i32.load + (local.get $4) + ) + (i32.shl + (local.get $0) + (i32.const 2) + ) + ) + ) + ) + ) + ) + ) + (local.set $1 + (f64.sub + (local.get $1) + (f64.div + (f64.mul + (local.get $10) + (f64.load offset=48 + (local.get $3) + ) + ) + (f64.sqrt + (f64.add + (f64.add + (f64.mul + (local.get $6) + (local.get $6) + ) + (f64.mul + (local.tee $1 + (f64.sub + (local.get $8) + (f64.load offset=8 + (local.get $3) + ) + ) + ) + (local.get $1) + ) + ) + (f64.mul + (local.tee $1 + (f64.sub + (local.get $9) + (f64.load offset=16 + (local.get $3) + ) + ) + ) + (local.get $1) + ) + ) + ) + ) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (br $label$7) + ) + ) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (br $label$4) + ) + ) + ) + (local.get $1) + ) + (func $assembly/index/step (; has Stack IR ;) (result f64) + (call $assembly/index/NBodySystem#advance + (global.get $global$5) + ) + (call $assembly/index/NBodySystem#energy + (global.get $global$5) + ) + ) + (func $assembly/index/bench (; has Stack IR ;) (param $0 i32) + (local $1 i32) + (block $label$1 + (loop $label$2 + (br_if $label$1 + (i32.le_u + (local.get $0) + (local.get $1) + ) + ) + (call $assembly/index/NBodySystem#advance + (global.get $global$5) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br $label$2) + ) + ) + ) + (func $assembly/index/getBody (; has Stack IR ;) (param $0 i32) (result i32) + (local $1 i32) + (if (result i32) + (i32.gt_u + (i32.load offset=4 + (local.tee $1 + (i32.load + (global.get $global$5) + ) + ) + ) + (local.get $0) + ) + (if (result i32) + (i32.gt_u + (i32.shr_u + (i32.load + (local.tee $1 + (i32.load + (local.get $1) + ) + ) + ) + (i32.const 2) + ) + (local.get $0) + ) + (i32.load offset=8 + (i32.add + (i32.shl + (local.get $0) + (i32.const 2) + ) + (local.get $1) + ) + ) + (unreachable) + ) + (i32.const 0) + ) + ) + (func $start (; has Stack IR ;) + (global.set $global$0 + (i32.const 104) + ) + (global.set $global$1 + (i32.const 104) + ) + ) + (func $null (; has Stack IR ;) + (nop) + ) +) diff -Nru binaryen-108/test/passes/O4_disable-bulk-memory.wast binaryen-99/test/passes/O4_disable-bulk-memory.wast --- binaryen-108/test/passes/O4_disable-bulk-memory.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O4_disable-bulk-memory.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1759 @@ +(module + (type $0 (func)) + (global $global$0 (mut i32) (i32.const 10)) + (export "func_59_invoker" (func $0)) + (func $0 (; 0 ;) (type $0) + (if + (block $label$1 (result i32) + (global.set $global$0 + (i32.const 0) + ) + (i32.const 127) + ) + (unreachable) + ) + (global.set $global$0 + (i32.const -1) + ) + (if + (global.get $global$0) + (unreachable) + ) + (unreachable) + ) +) +;; AssemblyScript n-body benchmark +(module + (type $0 (func)) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func (param i32 f64 f64 f64) (result i32))) + (type $3 (func (param i32) (result i32))) + (type $4 (func (result i32))) + (type $5 (func (param i32 f64 f64 f64 f64 f64 f64 f64) (result i32))) + (type $6 (func (param i32 i32 i32 i32))) + (type $7 (func (param i32 i32 i32))) + (type $8 (func (result f64))) + (type $9 (func (param i32 f64))) + (type $10 (func (param i32) (result f64))) + (type $11 (func (param i32))) + (import "env" "memory" (memory $1 1)) + (data (i32.const 8) "\0d\00\00\00~\00l\00i\00b\00/\00a\00r\00r\00a\00y\00.\00t\00s\00") + (data (i32.const 40) "\1c\00\00\00~\00l\00i\00b\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00a\00r\00r\00a\00y\00b\00u\00f\00f\00e\00r\00.\00t\00s\00") + (import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32))) + (table $0 1 funcref) + (elem (i32.const 0) $null) + (global $global$0 (mut i32) (i32.const 0)) + (global $global$1 (mut i32) (i32.const 0)) + (global $global$2 f64 (f64.const 3.141592653589793)) + (global $global$3 f64 (f64.const 39.47841760435743)) + (global $global$4 f64 (f64.const 365.24)) + (global $global$5 (mut i32) (i32.const 0)) + (global $global$6 i32 (i32.const 100)) + (export "memory" (memory $0)) + (export "table" (table $0)) + (export "init" (func $assembly/index/init)) + (export "step" (func $assembly/index/step)) + (export "bench" (func $assembly/index/bench)) + (export "getBody" (func $assembly/index/getBody)) + (start $start) + (func $start:~lib/allocator/arena (; 1 ;) (type $0) + (global.set $global$0 + (i32.and + (i32.add + (global.get $global$6) + (i32.const 7) + ) + (i32.xor + (i32.const 7) + (i32.const -1) + ) + ) + ) + (global.set $global$1 + (global.get $global$0) + ) + ) + (func $start:assembly/index (; 2 ;) (type $0) + (call $start:~lib/allocator/arena) + ) + (func $~lib/array/Array#__unchecked_get (; 3 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local.set $2 + (i32.load + (local.get $0) + ) + ) + (local.set $3 + (local.get $1) + ) + (local.set $4 + (i32.const 0) + ) + (i32.load offset=8 + (i32.add + (i32.add + (local.get $2) + (i32.shl + (local.get $3) + (i32.const 2) + ) + ) + (local.get $4) + ) + ) + ) + (func $~lib/array/Array#__get (; 4 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local.set $2 + (i32.load + (local.get $0) + ) + ) + (if (result i32) + (i32.lt_u + (local.get $1) + (i32.shr_u + (i32.load + (local.get $2) + ) + (i32.const 2) + ) + ) + (block (result i32) + (local.set $3 + (local.get $2) + ) + (local.set $4 + (local.get $1) + ) + (local.set $5 + (i32.const 0) + ) + (i32.load offset=8 + (i32.add + (i32.add + (local.get $3) + (i32.shl + (local.get $4) + (i32.const 2) + ) + ) + (local.get $5) + ) + ) + ) + (unreachable) + ) + ) + (func $assembly/index/Body#offsetMomentum (; 5 ;) (type $2) (param $0 i32) (param $1 f64) (param $2 f64) (param $3 f64) (result i32) + (f64.store offset=24 + (local.get $0) + (f64.div + (f64.neg + (local.get $1) + ) + (global.get $global$3) + ) + ) + (f64.store offset=32 + (local.get $0) + (f64.div + (f64.neg + (local.get $2) + ) + (global.get $global$3) + ) + ) + (f64.store offset=40 + (local.get $0) + (f64.div + (f64.neg + (local.get $3) + ) + (global.get $global$3) + ) + ) + (local.get $0) + ) + (func $~lib/allocator/arena/__memory_allocate (; 6 ;) (type $3) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.gt_u + (local.get $0) + (i32.const 1073741824) + ) + (unreachable) + ) + (local.set $1 + (global.get $global$1) + ) + (local.set $4 + (i32.and + (i32.add + (i32.add + (local.get $1) + (select + (local.tee $2 + (local.get $0) + ) + (local.tee $3 + (i32.const 1) + ) + (i32.gt_u + (local.get $2) + (local.get $3) + ) + ) + ) + (i32.const 7) + ) + (i32.xor + (i32.const 7) + (i32.const -1) + ) + ) + ) + (local.set $5 + (memory.size) + ) + (if + (i32.gt_u + (local.get $4) + (i32.shl + (local.get $5) + (i32.const 16) + ) + ) + (block + (local.set $2 + (i32.shr_u + (i32.and + (i32.add + (i32.sub + (local.get $4) + (local.get $1) + ) + (i32.const 65535) + ) + (i32.xor + (i32.const 65535) + (i32.const -1) + ) + ) + (i32.const 16) + ) + ) + (local.set $3 + (select + (local.tee $3 + (local.get $5) + ) + (local.tee $6 + (local.get $2) + ) + (i32.gt_s + (local.get $3) + (local.get $6) + ) + ) + ) + (if + (i32.lt_s + (memory.grow + (local.get $3) + ) + (i32.const 0) + ) + (if + (i32.lt_s + (memory.grow + (local.get $2) + ) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + ) + (global.set $global$1 + (local.get $4) + ) + (local.get $1) + ) + (func $~lib/memory/memory.allocate (; 7 ;) (type $3) (param $0 i32) (result i32) + (return + (call $~lib/allocator/arena/__memory_allocate + (local.get $0) + ) + ) + ) + (func $assembly/index/NBodySystem#constructor (; 8 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 f64) + (local $6 f64) + (local $7 f64) + (local $8 f64) + (local.set $5 + (f64.const 0) + ) + (local.set $6 + (f64.const 0) + ) + (local.set $7 + (f64.const 0) + ) + (local.set $3 + (block $label$1 (result i32) + (local.set $2 + (local.get $1) + ) + (i32.load offset=4 + (local.get $2) + ) + ) + ) + (block $label$2 + (local.set $2 + (i32.const 0) + ) + (loop $label$3 + (br_if $label$2 + (i32.eqz + (i32.lt_s + (local.get $2) + (local.get $3) + ) + ) + ) + (block $label$4 + (local.set $4 + (call $~lib/array/Array#__unchecked_get + (local.get $1) + (local.get $2) + ) + ) + (local.set $8 + (f64.load offset=48 + (local.get $4) + ) + ) + (local.set $5 + (f64.add + (local.get $5) + (f64.mul + (f64.load offset=24 + (local.get $4) + ) + (local.get $8) + ) + ) + ) + (local.set $6 + (f64.add + (local.get $6) + (f64.mul + (f64.load offset=32 + (local.get $4) + ) + (local.get $8) + ) + ) + ) + (local.set $7 + (f64.add + (local.get $7) + (f64.mul + (f64.load offset=40 + (local.get $4) + ) + (local.get $8) + ) + ) + ) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (br $label$3) + ) + ) + (drop + (call $assembly/index/Body#offsetMomentum + (call $~lib/array/Array#__get + (local.get $1) + (i32.const 0) + ) + (local.get $5) + (local.get $6) + (local.get $7) + ) + ) + (if + (i32.eqz + (local.get $0) + ) + (local.set $0 + (call $~lib/memory/memory.allocate + (i32.const 4) + ) + ) + ) + (i32.store + (local.get $0) + (local.get $1) + ) + (local.get $0) + ) + (func $assembly/index/Body#constructor (; 9 ;) (type $5) (param $0 i32) (param $1 f64) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 f64) (param $6 f64) (param $7 f64) (result i32) + (if + (i32.eqz + (local.get $0) + ) + (local.set $0 + (call $~lib/memory/memory.allocate + (i32.const 56) + ) + ) + ) + (f64.store + (local.get $0) + (local.get $1) + ) + (f64.store offset=8 + (local.get $0) + (local.get $2) + ) + (f64.store offset=16 + (local.get $0) + (local.get $3) + ) + (f64.store offset=24 + (local.get $0) + (local.get $4) + ) + (f64.store offset=32 + (local.get $0) + (local.get $5) + ) + (f64.store offset=40 + (local.get $0) + (local.get $6) + ) + (f64.store offset=48 + (local.get $0) + (local.get $7) + ) + (local.get $0) + ) + (func $assembly/index/Sun (; 10 ;) (type $4) (result i32) + (call $assembly/index/Body#constructor + (i32.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (f64.const 0) + (global.get $global$3) + ) + ) + (func $assembly/index/Jupiter (; 11 ;) (type $4) (result i32) + (call $assembly/index/Body#constructor + (i32.const 0) + (f64.const 4.841431442464721) + (f64.const -1.1603200440274284) + (f64.const -0.10362204447112311) + (f64.mul + (f64.const 0.001660076642744037) + (global.get $global$4) + ) + (f64.mul + (f64.const 0.007699011184197404) + (global.get $global$4) + ) + (f64.mul + (f64.const -6.90460016972063e-05) + (global.get $global$4) + ) + (f64.mul + (f64.const 9.547919384243266e-04) + (global.get $global$3) + ) + ) + ) + (func $assembly/index/Saturn (; 12 ;) (type $4) (result i32) + (call $assembly/index/Body#constructor + (i32.const 0) + (f64.const 8.34336671824458) + (f64.const 4.124798564124305) + (f64.const -0.4035234171143214) + (f64.mul + (f64.const -0.002767425107268624) + (global.get $global$4) + ) + (f64.mul + (f64.const 0.004998528012349172) + (global.get $global$4) + ) + (f64.mul + (f64.const 2.3041729757376393e-05) + (global.get $global$4) + ) + (f64.mul + (f64.const 2.858859806661308e-04) + (global.get $global$3) + ) + ) + ) + (func $assembly/index/Uranus (; 13 ;) (type $4) (result i32) + (call $assembly/index/Body#constructor + (i32.const 0) + (f64.const 12.894369562139131) + (f64.const -15.111151401698631) + (f64.const -0.22330757889265573) + (f64.mul + (f64.const 0.002964601375647616) + (global.get $global$4) + ) + (f64.mul + (f64.const 2.3784717395948095e-03) + (global.get $global$4) + ) + (f64.mul + (f64.const -2.9658956854023756e-05) + (global.get $global$4) + ) + (f64.mul + (f64.const 4.366244043351563e-05) + (global.get $global$3) + ) + ) + ) + (func $assembly/index/Neptune (; 14 ;) (type $4) (result i32) + (call $assembly/index/Body#constructor + (i32.const 0) + (f64.const 15.379697114850917) + (f64.const -25.919314609987964) + (f64.const 0.17925877295037118) + (f64.mul + (f64.const 2.6806777249038932e-03) + (global.get $global$4) + ) + (f64.mul + (f64.const 0.001628241700382423) + (global.get $global$4) + ) + (f64.mul + (f64.const -9.515922545197159e-05) + (global.get $global$4) + ) + (f64.mul + (f64.const 5.1513890204661145e-05) + (global.get $global$3) + ) + ) + ) + (func $~lib/internal/arraybuffer/computeSize (; 15 ;) (type $3) (param $0 i32) (result i32) + (i32.shl + (i32.const 1) + (i32.sub + (i32.const 32) + (i32.clz + (i32.sub + (i32.add + (local.get $0) + (i32.const 8) + ) + (i32.const 1) + ) + ) + ) + ) + ) + (func $~lib/internal/arraybuffer/allocateUnsafe (; 16 ;) (type $3) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (if + (i32.eqz + (i32.le_u + (local.get $0) + (i32.const 1073741816) + ) + ) + (block + (call $~lib/env/abort + (i32.const 0) + (i32.const 40) + (i32.const 26) + (i32.const 2) + ) + (unreachable) + ) + ) + (local.set $1 + (block $label$2 (result i32) + (local.set $2 + (call $~lib/internal/arraybuffer/computeSize + (local.get $0) + ) + ) + (br $label$2 + (call $~lib/allocator/arena/__memory_allocate + (local.get $2) + ) + ) + ) + ) + (i32.store + (local.get $1) + (local.get $0) + ) + (local.get $1) + ) + (func $~lib/internal/memory/memset (; 17 ;) (type $7) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i64) + (if + (i32.eqz + (local.get $2) + ) + (return) + ) + (i32.store8 + (local.get $0) + (local.get $1) + ) + (i32.store8 + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 1) + ) + (local.get $1) + ) + (if + (i32.le_u + (local.get $2) + (i32.const 2) + ) + (return) + ) + (i32.store8 + (i32.add + (local.get $0) + (i32.const 1) + ) + (local.get $1) + ) + (i32.store8 + (i32.add + (local.get $0) + (i32.const 2) + ) + (local.get $1) + ) + (i32.store8 + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 2) + ) + (local.get $1) + ) + (i32.store8 + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 3) + ) + (local.get $1) + ) + (if + (i32.le_u + (local.get $2) + (i32.const 6) + ) + (return) + ) + (i32.store8 + (i32.add + (local.get $0) + (i32.const 3) + ) + (local.get $1) + ) + (i32.store8 + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 4) + ) + (local.get $1) + ) + (if + (i32.le_u + (local.get $2) + (i32.const 8) + ) + (return) + ) + (local.set $3 + (i32.and + (i32.sub + (i32.const 0) + (local.get $0) + ) + (i32.const 3) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (local.get $3) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (local.get $3) + ) + ) + (local.set $2 + (i32.and + (local.get $2) + (i32.const -4) + ) + ) + (local.set $4 + (i32.mul + (i32.div_u + (i32.const -1) + (i32.const 255) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (i32.store + (local.get $0) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 4) + ) + (local.get $4) + ) + (if + (i32.le_u + (local.get $2) + (i32.const 8) + ) + (return) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 4) + ) + (local.get $4) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 8) + ) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 12) + ) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 8) + ) + (local.get $4) + ) + (if + (i32.le_u + (local.get $2) + (i32.const 24) + ) + (return) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 12) + ) + (local.get $4) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 16) + ) + (local.get $4) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 20) + ) + (local.get $4) + ) + (i32.store + (i32.add + (local.get $0) + (i32.const 24) + ) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 28) + ) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 24) + ) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 20) + ) + (local.get $4) + ) + (i32.store + (i32.sub + (i32.add + (local.get $0) + (local.get $2) + ) + (i32.const 16) + ) + (local.get $4) + ) + (local.set $3 + (i32.add + (i32.const 24) + (i32.and + (local.get $0) + (i32.const 4) + ) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (local.get $3) + ) + ) + (local.set $2 + (i32.sub + (local.get $2) + (local.get $3) + ) + ) + (local.set $5 + (i64.or + (i64.extend_i32_u + (local.get $4) + ) + (i64.shl + (i64.extend_i32_u + (local.get $4) + ) + (i64.const 32) + ) + ) + ) + (block $label$7 + (loop $label$8 + (if + (i32.ge_u + (local.get $2) + (i32.const 32) + ) + (block + (block $label$10 + (i64.store + (local.get $0) + (local.get $5) + ) + (i64.store + (i32.add + (local.get $0) + (i32.const 8) + ) + (local.get $5) + ) + (i64.store + (i32.add + (local.get $0) + (i32.const 16) + ) + (local.get $5) + ) + (i64.store + (i32.add + (local.get $0) + (i32.const 24) + ) + (local.get $5) + ) + (local.set $2 + (i32.sub + (local.get $2) + (i32.const 32) + ) + ) + (local.set $0 + (i32.add + (local.get $0) + (i32.const 32) + ) + ) + ) + (br $label$8) + ) + ) + ) + ) + ) + (func $~lib/array/Array#constructor (; 18 ;) (type $1) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (if + (i32.gt_u + (local.get $1) + (i32.const 268435454) + ) + (block + (call $~lib/env/abort + (i32.const 0) + (i32.const 8) + (i32.const 45) + (i32.const 39) + ) + (unreachable) + ) + ) + (local.set $2 + (i32.shl + (local.get $1) + (i32.const 2) + ) + ) + (local.set $3 + (call $~lib/internal/arraybuffer/allocateUnsafe + (local.get $2) + ) + ) + (i32.store + (block $label$2 (result i32) + (if + (i32.eqz + (local.get $0) + ) + (local.set $0 + (call $~lib/memory/memory.allocate + (i32.const 8) + ) + ) + ) + (i32.store + (local.get $0) + (i32.const 0) + ) + (i32.store offset=4 + (local.get $0) + (i32.const 0) + ) + (local.get $0) + ) + (local.get $3) + ) + (i32.store offset=4 + (local.get $0) + (local.get $1) + ) + (block $label$4 + (local.set $4 + (i32.add + (local.get $3) + (i32.const 8) + ) + ) + (local.set $5 + (i32.const 0) + ) + (local.set $6 + (local.get $2) + ) + (call $~lib/internal/memory/memset + (local.get $4) + (local.get $5) + (local.get $6) + ) + ) + (local.get $0) + ) + (func $~lib/array/Array#__unchecked_set (; 19 ;) (type $7) (param $0 i32) (param $1 i32) (param $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local.set $3 + (i32.load + (local.get $0) + ) + ) + (local.set $4 + (local.get $1) + ) + (local.set $5 + (local.get $2) + ) + (local.set $6 + (i32.const 0) + ) + (i32.store offset=8 + (i32.add + (i32.add + (local.get $3) + (i32.shl + (local.get $4) + (i32.const 2) + ) + ) + (local.get $6) + ) + (local.get $5) + ) + ) + (func $assembly/index/init (; 20 ;) (type $0) + (local $0 i32) + (global.set $global$5 + (call $assembly/index/NBodySystem#constructor + (i32.const 0) + (block $label$1 (result i32) + (local.set $0 + (call $~lib/array/Array#constructor + (i32.const 0) + (i32.const 5) + ) + ) + (call $~lib/array/Array#__unchecked_set + (local.get $0) + (i32.const 0) + (call $assembly/index/Sun) + ) + (call $~lib/array/Array#__unchecked_set + (local.get $0) + (i32.const 1) + (call $assembly/index/Jupiter) + ) + (call $~lib/array/Array#__unchecked_set + (local.get $0) + (i32.const 2) + (call $assembly/index/Saturn) + ) + (call $~lib/array/Array#__unchecked_set + (local.get $0) + (i32.const 3) + (call $assembly/index/Uranus) + ) + (call $~lib/array/Array#__unchecked_set + (local.get $0) + (i32.const 4) + (call $assembly/index/Neptune) + ) + (local.get $0) + ) + ) + ) + ) + (func $assembly/index/NBodySystem#advance (; 21 ;) (type $9) (param $0 i32) (param $1 f64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local $11 f64) + (local $12 f64) + (local $13 f64) + (local $14 f64) + (local $15 f64) + (local $16 f64) + (local $17 f64) + (local $18 f64) + (local $19 f64) + (local $20 f64) + (local $21 f64) + (local $22 f64) + (local.set $2 + (i32.load + (local.get $0) + ) + ) + (local.set $4 + (block $label$1 (result i32) + (local.set $3 + (local.get $2) + ) + (i32.load offset=4 + (local.get $3) + ) + ) + ) + (block $label$2 + (local.set $3 + (i32.const 0) + ) + (loop $label$3 + (br_if $label$2 + (i32.eqz + (i32.lt_u + (local.get $3) + (local.get $4) + ) + ) + ) + (block $label$4 + (local.set $5 + (call $~lib/array/Array#__unchecked_get + (local.get $2) + (local.get $3) + ) + ) + (local.set $8 + (f64.load + (local.get $5) + ) + ) + (local.set $9 + (f64.load offset=8 + (local.get $5) + ) + ) + (local.set $10 + (f64.load offset=16 + (local.get $5) + ) + ) + (local.set $11 + (f64.load offset=24 + (local.get $5) + ) + ) + (local.set $12 + (f64.load offset=32 + (local.get $5) + ) + ) + (local.set $13 + (f64.load offset=40 + (local.get $5) + ) + ) + (local.set $14 + (f64.load offset=48 + (local.get $5) + ) + ) + (block $label$5 + (local.set $6 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (loop $label$6 + (br_if $label$5 + (i32.eqz + (i32.lt_u + (local.get $6) + (local.get $4) + ) + ) + ) + (block $label$7 + (local.set $7 + (call $~lib/array/Array#__unchecked_get + (local.get $2) + (local.get $6) + ) + ) + (local.set $15 + (f64.sub + (local.get $8) + (f64.load + (local.get $7) + ) + ) + ) + (local.set $16 + (f64.sub + (local.get $9) + (f64.load offset=8 + (local.get $7) + ) + ) + ) + (local.set $17 + (f64.sub + (local.get $10) + (f64.load offset=16 + (local.get $7) + ) + ) + ) + (local.set $18 + (f64.add + (f64.add + (f64.mul + (local.get $15) + (local.get $15) + ) + (f64.mul + (local.get $16) + (local.get $16) + ) + ) + (f64.mul + (local.get $17) + (local.get $17) + ) + ) + ) + (local.set $19 + (block $label$8 (result f64) + (local.set $19 + (local.get $18) + ) + (f64.sqrt + (local.get $19) + ) + ) + ) + (local.set $20 + (f64.div + (local.get $1) + (f64.mul + (local.get $18) + (local.get $19) + ) + ) + ) + (local.set $21 + (f64.mul + (local.get $14) + (local.get $20) + ) + ) + (local.set $22 + (f64.mul + (f64.load offset=48 + (local.get $7) + ) + (local.get $20) + ) + ) + (local.set $11 + (f64.sub + (local.get $11) + (f64.mul + (local.get $15) + (local.get $22) + ) + ) + ) + (local.set $12 + (f64.sub + (local.get $12) + (f64.mul + (local.get $16) + (local.get $22) + ) + ) + ) + (local.set $13 + (f64.sub + (local.get $13) + (f64.mul + (local.get $17) + (local.get $22) + ) + ) + ) + (f64.store offset=24 + (local.get $7) + (f64.add + (f64.load offset=24 + (local.get $7) + ) + (f64.mul + (local.get $15) + (local.get $21) + ) + ) + ) + (f64.store offset=32 + (local.get $7) + (f64.add + (f64.load offset=32 + (local.get $7) + ) + (f64.mul + (local.get $16) + (local.get $21) + ) + ) + ) + (f64.store offset=40 + (local.get $7) + (f64.add + (f64.load offset=40 + (local.get $7) + ) + (f64.mul + (local.get $17) + (local.get $21) + ) + ) + ) + ) + (local.set $6 + (i32.add + (local.get $6) + (i32.const 1) + ) + ) + (br $label$6) + ) + ) + (f64.store offset=24 + (local.get $5) + (local.get $11) + ) + (f64.store offset=32 + (local.get $5) + (local.get $12) + ) + (f64.store offset=40 + (local.get $5) + (local.get $13) + ) + (f64.store + (local.get $5) + (f64.add + (f64.load + (local.get $5) + ) + (f64.mul + (local.get $1) + (local.get $11) + ) + ) + ) + (f64.store offset=8 + (local.get $5) + (f64.add + (f64.load offset=8 + (local.get $5) + ) + (f64.mul + (local.get $1) + (local.get $12) + ) + ) + ) + (f64.store offset=16 + (local.get $5) + (f64.add + (f64.load offset=16 + (local.get $5) + ) + (f64.mul + (local.get $1) + (local.get $13) + ) + ) + ) + ) + (local.set $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (br $label$3) + ) + ) + ) + (func $assembly/index/NBodySystem#energy (; 22 ;) (type $10) (param $0 i32) (result f64) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 f64) + (local $8 f64) + (local $9 f64) + (local $10 f64) + (local $11 f64) + (local $12 f64) + (local $13 f64) + (local $14 f64) + (local $15 f64) + (local $16 f64) + (local $17 f64) + (local $18 f64) + (local.set $7 + (f64.const 0) + ) + (local.set $1 + (i32.load + (local.get $0) + ) + ) + (block $label$1 + (block $label$2 + (local.set $2 + (i32.const 0) + ) + (local.set $3 + (block $label$3 (result i32) + (local.set $3 + (local.get $1) + ) + (i32.load offset=4 + (local.get $3) + ) + ) + ) + ) + (loop $label$4 + (br_if $label$1 + (i32.eqz + (i32.lt_u + (local.get $2) + (local.get $3) + ) + ) + ) + (block $label$5 + (local.set $4 + (call $~lib/array/Array#__unchecked_get + (local.get $1) + (local.get $2) + ) + ) + (local.set $8 + (f64.load + (local.get $4) + ) + ) + (local.set $9 + (f64.load offset=8 + (local.get $4) + ) + ) + (local.set $10 + (f64.load offset=16 + (local.get $4) + ) + ) + (local.set $11 + (f64.load offset=24 + (local.get $4) + ) + ) + (local.set $12 + (f64.load offset=32 + (local.get $4) + ) + ) + (local.set $13 + (f64.load offset=40 + (local.get $4) + ) + ) + (local.set $14 + (f64.load offset=48 + (local.get $4) + ) + ) + (local.set $7 + (f64.add + (local.get $7) + (f64.mul + (f64.mul + (f64.const 0.5) + (local.get $14) + ) + (f64.add + (f64.add + (f64.mul + (local.get $11) + (local.get $11) + ) + (f64.mul + (local.get $12) + (local.get $12) + ) + ) + (f64.mul + (local.get $13) + (local.get $13) + ) + ) + ) + ) + ) + (block $label$6 + (local.set $5 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (loop $label$7 + (br_if $label$6 + (i32.eqz + (i32.lt_u + (local.get $5) + (local.get $3) + ) + ) + ) + (block $label$8 + (local.set $6 + (call $~lib/array/Array#__unchecked_get + (local.get $1) + (local.get $5) + ) + ) + (local.set $15 + (f64.sub + (local.get $8) + (f64.load + (local.get $6) + ) + ) + ) + (local.set $16 + (f64.sub + (local.get $9) + (f64.load offset=8 + (local.get $6) + ) + ) + ) + (local.set $17 + (f64.sub + (local.get $10) + (f64.load offset=16 + (local.get $6) + ) + ) + ) + (local.set $18 + (block $label$9 (result f64) + (local.set $18 + (f64.add + (f64.add + (f64.mul + (local.get $15) + (local.get $15) + ) + (f64.mul + (local.get $16) + (local.get $16) + ) + ) + (f64.mul + (local.get $17) + (local.get $17) + ) + ) + ) + (f64.sqrt + (local.get $18) + ) + ) + ) + (local.set $7 + (f64.sub + (local.get $7) + (f64.div + (f64.mul + (local.get $14) + (f64.load offset=48 + (local.get $6) + ) + ) + (local.get $18) + ) + ) + ) + ) + (local.set $5 + (i32.add + (local.get $5) + (i32.const 1) + ) + ) + (br $label$7) + ) + ) + ) + (local.set $2 + (i32.add + (local.get $2) + (i32.const 1) + ) + ) + (br $label$4) + ) + ) + (local.get $7) + ) + (func $assembly/index/step (; 23 ;) (type $8) (result f64) + (call $assembly/index/NBodySystem#advance + (global.get $global$5) + (f64.const 0.01) + ) + (call $assembly/index/NBodySystem#energy + (global.get $global$5) + ) + ) + (func $assembly/index/bench (; 24 ;) (type $11) (param $0 i32) + (local $1 i32) + (block $label$1 + (local.set $1 + (i32.const 0) + ) + (loop $label$2 + (br_if $label$1 + (i32.eqz + (i32.lt_u + (local.get $1) + (local.get $0) + ) + ) + ) + (call $assembly/index/NBodySystem#advance + (global.get $global$5) + (f64.const 0.01) + ) + (local.set $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (br $label$2) + ) + ) + ) + (func $assembly/index/getBody (; 25 ;) (type $3) (param $0 i32) (result i32) + (local $1 i32) + (local $2 i32) + (local.set $1 + (i32.load + (global.get $global$5) + ) + ) + (if (result i32) + (i32.lt_u + (local.get $0) + (block $label$1 (result i32) + (local.set $2 + (local.get $1) + ) + (i32.load offset=4 + (local.get $2) + ) + ) + ) + (call $~lib/array/Array#__get + (local.get $1) + (local.get $0) + ) + (i32.const 0) + ) + ) + (func $start (; 26 ;) (type $0) + (call $start:assembly/index) + ) + (func $null (; 27 ;) (type $0) + ) +) + diff -Nru binaryen-108/test/passes/O_all-features_ignore-implicit-traps.txt binaryen-99/test/passes/O_all-features_ignore-implicit-traps.txt --- binaryen-108/test/passes/O_all-features_ignore-implicit-traps.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O_all-features_ignore-implicit-traps.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,8 @@ +(module + (type ${i32} (struct (field i32))) + (type $ref?|{i32}|_=>_none (func (param (ref null ${i32})))) + (export "foo" (func $0)) + (func $0 (; has Stack IR ;) (param $0 (ref null ${i32})) + (nop) + ) +) diff -Nru binaryen-108/test/passes/O_all-features_ignore-implicit-traps.wast binaryen-99/test/passes/O_all-features_ignore-implicit-traps.wast --- binaryen-108/test/passes/O_all-features_ignore-implicit-traps.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O_all-features_ignore-implicit-traps.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,17 @@ +;; Test that we can run GC types through the optimizer +(module + (type $struct.A (struct i32)) + + (func "foo" (param $x (ref null $struct.A)) + ;; get a struct reference + (drop + (local.get $x) + ) + ;; get a struct field value + ;; (note that since this is a nullable reference, it may trap, but we + ;; are ignoring implicit traps, so it has no side effects) + (drop + (struct.get $struct.A 0 (local.get $x)) + ) + ) +) diff -Nru binaryen-108/test/passes/O_all-features.txt binaryen-99/test/passes/O_all-features.txt --- binaryen-108/test/passes/O_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,12 @@ +(module + (type ${i32} (struct (field i32))) + (type $ref?|{i32}|_=>_none (func (param (ref null ${i32})))) + (export "foo" (func $0)) + (func $0 (; has Stack IR ;) (param $0 (ref null ${i32})) + (drop + (struct.get ${i32} 0 + (local.get $0) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/O_all-features.wast binaryen-99/test/passes/O_all-features.wast --- binaryen-108/test/passes/O_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,16 @@ +;; Test that we can run GC types through the optimizer +(module + (type $struct.A (struct i32)) + + (func "foo" (param $x (ref null $struct.A)) + ;; get a struct reference + (drop + (local.get $x) + ) + ;; get a struct field value + ;; (note that since this is a nullable reference, it may trap) + (drop + (struct.get $struct.A 0 (local.get $x)) + ) + ) +) diff -Nru binaryen-108/test/passes/O_fast-math.txt binaryen-99/test/passes/O_fast-math.txt --- binaryen-108/test/passes/O_fast-math.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O_fast-math.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,47 @@ +(module + (type $none_=>_f32 (func (result f32))) + (type $f32_=>_f32 (func (param f32) (result f32))) + (type $f64_=>_f64 (func (param f64) (result f64))) + (export "div" (func $0)) + (export "mul1" (func $1)) + (export "mul2" (func $2)) + (export "add1" (func $1)) + (export "add2" (func $2)) + (export "add3" (func $2)) + (export "add4" (func $2)) + (export "sub1" (func $1)) + (export "sub2" (func $2)) + (export "mul_neg_one1" (func $9)) + (export "mul_neg_one2" (func $10)) + (export "abs_sub_zero1" (func $11)) + (export "abs_sub_zero2" (func $12)) + (func $0 (; has Stack IR ;) (result f32) + (f32.const -nan:0x23017a) + ) + (func $1 (; has Stack IR ;) (result f32) + (f32.const -nan:0x34546d) + ) + (func $2 (; has Stack IR ;) (result f32) + (f32.const nan:0x400000) + ) + (func $9 (; has Stack IR ;) (param $0 f32) (result f32) + (f32.neg + (local.get $0) + ) + ) + (func $10 (; has Stack IR ;) (param $0 f64) (result f64) + (f64.neg + (local.get $0) + ) + ) + (func $11 (; has Stack IR ;) (param $0 f32) (result f32) + (f32.abs + (local.get $0) + ) + ) + (func $12 (; has Stack IR ;) (param $0 f64) (result f64) + (f64.abs + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/O_fast-math.wast binaryen-99/test/passes/O_fast-math.wast --- binaryen-108/test/passes/O_fast-math.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O_fast-math.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,87 @@ +;; with fast-math we can optimize some of these patterns +(module + (func "div" (result f32) + (f32.div + (f32.const -nan:0x23017a) + (f32.const 1) + ) + ) + (func "mul1" (result f32) + (f32.mul + (f32.const -nan:0x34546d) + (f32.const 1) + ) + ) + (func "mul2" (result f32) + (f32.mul + (f32.const 1) + (f32.const -nan:0x34546d) + ) + ) + (func "add1" (result f32) + (f32.add + (f32.const -nan:0x34546d) + (f32.const -0) + ) + ) + (func "add2" (result f32) + (f32.add + (f32.const -0) + (f32.const -nan:0x34546d) + ) + ) + (func "add3" (result f32) + (f32.add + (f32.const -nan:0x34546d) + (f32.const 0) + ) + ) + (func "add4" (result f32) + (f32.add + (f32.const 0) + (f32.const -nan:0x34546d) + ) + ) + (func "sub1" (result f32) + (f32.sub + (f32.const -nan:0x34546d) + (f32.const 0) + ) + ) + (func "sub2" (result f32) + (f32.sub + (f32.const -nan:0x34546d) + (f32.const -0) + ) + ) + (func "mul_neg_one1" (param $x f32) (result f32) + (f32.mul + (local.get $x) + (f32.const -1) + ) + ) + (func "mul_neg_one2" (param $x f64) (result f64) + (f64.mul + (local.get $x) + (f64.const -1) + ) + ) + (func "abs_sub_zero1" (param $x f32) (result f32) + ;; abs(0 - x) ==> abs(x) + (f32.abs + (f32.sub + (f32.const 0) + (local.get $x) + ) + ) + ) + (func "abs_sub_zero2" (param $x f64) (result f64) + ;; abs(0 - x) ==> abs(x) + (f64.abs + (f64.sub + (f64.const 0) + (local.get $x) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/optimize-instructions_all-features.txt binaryen-99/test/passes/optimize-instructions_all-features.txt --- binaryen-108/test/passes/optimize-instructions_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/optimize-instructions_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,5707 @@ +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i64_=>_none (func (param i32 i64))) + (type $none_=>_none (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i64_i64_=>_none (func (param i32 i32 i64 i64))) + (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) + (type $none_=>_i64 (func (result i64))) + (type $i64_=>_i64 (func (param i64) (result i64))) + (type $i32_i64_f32_=>_none (func (param i32 i64 f32))) + (type $f32_=>_none (func (param f32))) + (type $f64_=>_none (func (param f64))) + (type $i32_i32_i32_f64_=>_none (func (param i32 i32 i32 f64))) + (type $i32_i32_f64_f64_=>_none (func (param i32 i32 f64 f64))) + (type $i32_i64_f64_i32_=>_none (func (param i32 i64 f64 i32))) + (type $f32_f64_=>_none (func (param f32 f64))) + (type $f64_f32_=>_none (func (param f64 f32))) + (type $f64_f64_f32_f32_=>_none (func (param f64 f64 f32 f32))) + (type $none_=>_f64 (func (result f64))) + (memory $0 0) + (export "load-off-2" (func $load-off-2)) + (func $f (param $i1 i32) (param $i2 i64) + (drop + (i32.and + (local.get $i1) + (i32.const 1) + ) + ) + (drop + (i32.or + (local.get $i1) + (i32.const 3) + ) + ) + (drop + (i32.xor + (local.get $i1) + (i32.const 5) + ) + ) + (drop + (i32.mul + (local.get $i1) + (i32.const -10) + ) + ) + (drop + (i32.mul + (local.get $i1) + (i32.const -133169153) + ) + ) + (if + (i32.eqz + (local.get $i1) + ) + (drop + (i32.const 10) + ) + ) + (if + (local.get $i1) + (drop + (i32.const 12) + ) + (drop + (i32.const 11) + ) + ) + (if + (i64.eqz + (local.get $i2) + ) + (drop + (i32.const 11) + ) + (drop + (i32.const 12) + ) + ) + (drop + (i32.le_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.lt_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.ge_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.gt_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.le_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.lt_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.ge_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.gt_u + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.eqz + (f32.gt + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.ge + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.lt + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.le + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.gt + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.ge + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.lt + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.le + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (f32.ne + (f32.const 1) + (f32.const 2) + ) + ) + (drop + (f32.eq + (f32.const 1) + (f32.const 2) + ) + ) + (drop + (f64.ne + (f64.const 1) + (f64.const 2) + ) + ) + (drop + (f64.eq + (f64.const 1) + (f64.const 2) + ) + ) + (drop + (i32.eqz + (i32.const 100) + ) + ) + (drop + (i32.eq + (i32.const 0) + (i32.const 100) + ) + ) + (drop + (i32.eqz + (i32.const 0) + ) + ) + (drop + (i64.eqz + (i64.const 100) + ) + ) + (drop + (i64.eq + (i64.const 0) + (i64.const 100) + ) + ) + (drop + (i64.eqz + (i64.const 0) + ) + ) + (if + (i32.const 123) + (nop) + ) + (drop + (select + (i32.const 102) + (i32.const 101) + (local.get $i1) + ) + ) + (drop + (select + (local.tee $i1 + (i32.const 103) + ) + (local.tee $i1 + (i32.const 104) + ) + (i32.eqz + (local.get $i1) + ) + ) + ) + (drop + (i32.const 0) + ) + ) + (func $load-store + (drop + (i32.load8_u + (i32.const 0) + ) + ) + (drop + (i32.load8_u + (i32.const 1) + ) + ) + (drop + (i32.and + (i32.load8_s + (i32.const 2) + ) + (i32.const 254) + ) + ) + (drop + (i32.and + (i32.load8_u + (i32.const 3) + ) + (i32.const 1) + ) + ) + (drop + (i32.load16_u + (i32.const 4) + ) + ) + (drop + (i32.load16_u + (i32.const 5) + ) + ) + (drop + (i32.and + (i32.load16_s + (i32.const 6) + ) + (i32.const 65534) + ) + ) + (drop + (i32.and + (i32.load16_u + (i32.const 7) + ) + (i32.const 1) + ) + ) + (i32.store8 + (i32.const 8) + (i32.const -1) + ) + (i32.store8 + (i32.const 9) + (i32.and + (i32.const -2) + (i32.const 254) + ) + ) + (i32.store16 + (i32.const 10) + (i32.const -3) + ) + (i32.store16 + (i32.const 11) + (i32.and + (i32.const -4) + (i32.const 65534) + ) + ) + (i64.store8 + (i32.const 11) + (i64.const 1) + ) + (i64.store16 + (i32.const 11) + (i64.const 2) + ) + (i64.store32 + (i32.const 11) + (i64.const 3) + ) + (i32.store8 + (i32.const 7) + (i32.const 255) + ) + (i32.store8 + (i32.const 8) + (i32.const 255) + ) + (i32.store8 + (i32.const 9) + (i32.const 0) + ) + (i32.store16 + (i32.const 10) + (i32.const 65535) + ) + (i32.store16 + (i32.const 11) + (i32.const 0) + ) + (i32.store16 + (i32.const 13) + (i32.const 65535) + ) + (i32.store + (i32.const 14) + (i32.const 65536) + ) + (i64.store8 + (i32.const 8) + (i64.const 255) + ) + (i64.store8 + (i32.const 9) + (i64.const 0) + ) + (i64.store16 + (i32.const 10) + (i64.const 65535) + ) + (i64.store16 + (i32.const 11) + (i64.const 0) + ) + (i64.store32 + (i32.const 12) + (i64.const 4294967295) + ) + (i64.store32 + (i32.const 13) + (i64.const 0) + ) + (i64.store + (i32.const 14) + (i64.const 4294967296) + ) + ) + (func $and-neg1 + (drop + (i32.const 100) + ) + (drop + (i32.and + (i32.const 100) + (i32.const 1) + ) + ) + ) + (func $and-pos1 + (drop + (i32.eqz + (i32.const 1000) + ) + ) + (drop + (i32.eqz + (i32.const 1000) + ) + ) + (drop + (i32.and + (i32.const 100) + (i32.const 1) + ) + ) + (drop + (i32.lt_u + (i32.const 2000) + (i32.const 3000) + ) + ) + ) + (func $canonicalize (param $x i32) (param $y i32) (param $fx f64) (param $fy f64) + (drop + (i32.and + (unreachable) + (i32.const 1) + ) + ) + (drop + (i32.and + (i32.const 1) + (unreachable) + ) + ) + (drop + (i32.div_s + (unreachable) + (i32.const 1) + ) + ) + (drop + (i32.div_s + (i32.const 1) + (unreachable) + ) + ) + (drop + (i32.and + (i32.const 1) + (i32.const 2) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 4) + ) + ) + (drop + (i32.and + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.and + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.and + (local.tee $x + (i32.const -4) + ) + (local.get $y) + ) + ) + (drop + (i32.and + (block $block (result i32) + (i32.const -5) + ) + (local.get $x) + ) + ) + (drop + (i32.and + (block $block3 (result i32) + (i32.const -6) + ) + (local.get $x) + ) + ) + (drop + (i32.and + (block $block4 (result i32) + (i32.const 5) + ) + (loop $loop-in (result i32) + (i32.const 6) + ) + ) + ) + (drop + (i32.and + (block $block6 (result i32) + (i32.const 8) + ) + (loop $loop-in5 (result i32) + (i32.const 7) + ) + ) + ) + (drop + (i32.and + (block $block8 (result i32) + (i32.const 10) + ) + (loop $loop-in7 (result i32) + (call $and-pos1) + (i32.const 9) + ) + ) + ) + (drop + (i32.and + (block $block10 (result i32) + (call $and-pos1) + (i32.const 12) + ) + (loop $loop-in9 (result i32) + (i32.const 11) + ) + ) + ) + (drop + (i32.and + (loop $loop-in11 (result i32) + (call $and-pos1) + (i32.const 13) + ) + (block $block12 (result i32) + (call $and-pos1) + (i32.const 14) + ) + ) + ) + (drop + (i32.and + (block $block13 (result i32) + (call $and-pos1) + (i32.const 14) + ) + (loop $loop-in14 (result i32) + (call $and-pos1) + (i32.const 13) + ) + ) + ) + (drop + (i32.and + (block $block15 (result i32) + (i32.const 15) + ) + (local.get $x) + ) + ) + (drop + (i32.and + (block $block16 (result i32) + (i32.const 15) + ) + (local.get $x) + ) + ) + (drop + (i32.and + (i32.gt_u + (i32.const 16) + (i32.const 17) + ) + (i32.gt_u + (i32.const 18) + (i32.const 19) + ) + ) + ) + (drop + (i32.and + (i32.gt_u + (i32.const 20) + (i32.const 21) + ) + (i32.gt_u + (i32.const 22) + (i32.const 23) + ) + ) + ) + (drop + (i32.lt_s + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i32.const 0) + ) + (drop + (i32.ne + (local.get $x) + (i32.const -1) + ) + ) + (drop + (f64.ne + (local.get $fx) + (f64.const -1) + ) + ) + (drop + (f64.gt + (local.get $fx) + (f64.const -2) + ) + ) + (drop + (f64.le + (local.get $fx) + (f64.const inf) + ) + ) + (drop + (f64.ge + (local.get $fx) + (f64.const nan:0x8000000000000) + ) + ) + (drop + (f64.ge + (f64.const 1) + (f64.const 2) + ) + ) + (drop + (i32.add + (i32.ctz + (local.get $x) + ) + (i32.ctz + (local.get $y) + ) + ) + ) + (drop + (i32.add + (i32.ctz + (local.get $y) + ) + (i32.ctz + (local.get $x) + ) + ) + ) + (drop + (i32.add + (i32.ctz + (local.get $x) + ) + (i32.eqz + (local.get $y) + ) + ) + ) + (drop + (i32.add + (i32.ctz + (local.get $y) + ) + (i32.eqz + (local.get $x) + ) + ) + ) + ) + (func $ne0 (result i32) + (if + (call $ne0) + (nop) + ) + (if + (call $ne0) + (nop) + ) + (if + (i32.or + (call $ne0) + (call $ne0) + ) + (nop) + ) + (if + (i32.and + (i32.ne + (call $ne0) + (i32.const 0) + ) + (i32.ne + (call $ne0) + (i32.const 0) + ) + ) + (nop) + ) + (i32.const 1) + ) + (func $recurse-bool + (if + (if (result i32) + (i32.const 1) + (call $ne0) + (call $ne1) + ) + (nop) + ) + (if + (block $block (result i32) + (nop) + (call $ne0) + ) + (nop) + ) + ) + (func $ne1 (result i32) + (unreachable) + ) + (func $load-off-2 (param $0 i32) (result i32) + (i32.store + (i32.const 6) + (local.get $0) + ) + (i32.store + (i32.const 6) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (local.get $0) + (i32.const 7) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.sub + (local.get $0) + (i32.const 11) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.sub + (local.get $0) + (i32.const 13) + ) + (local.get $0) + ) + (i32.store + (i32.const 4) + (local.get $0) + ) + (i32.store offset=2 + (i32.const -2) + (local.get $0) + ) + (i32.store + (i32.const 25) + (local.get $0) + ) + (i32.store offset=2 + (i32.const -25) + (local.get $0) + ) + (drop + (i32.load + (i32.const 8) + ) + ) + (drop + (i32.load + (i32.const 8) + ) + ) + (drop + (i32.load offset=2 + (i32.add + (local.get $0) + (i32.const 6) + ) + ) + ) + (drop + (i32.load + (i32.const 10) + ) + ) + (i32.load offset=2 + (i32.add + (local.get $0) + (i32.const 10) + ) + ) + ) + (func $sign-ext (param $0 i32) (param $1 i32) + (drop + (i32.eqz + (i32.and + (local.get $0) + (i32.const 255) + ) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $0) + (i32.const 65535) + ) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $0) + (i32.const 134217727) + ) + ) + ) + (drop + (i32.eq + (i32.and + (local.get $0) + (i32.const 255) + ) + (i32.const 100) + ) + ) + (drop + (block (result i32) + (drop + (local.get $0) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (local.get $0) + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.and + (local.get $0) + (i32.const 255) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (drop + (i32.eq + (i32.and + (local.get $0) + (i32.const 65535) + ) + (i32.and + (local.get $1) + (i32.const 65535) + ) + ) + ) + (drop + (i32.eqz + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 23) + ) + ) + ) + (drop + (i32.eqz + (i32.shr_u + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (drop + (i32.lt_s + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 0) + ) + ) + (drop + (if (result i32) + (i32.shr_s + (i32.shl + (unreachable) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.const 111) + (i32.const 222) + ) + ) + ) + (func $sign-ext-input (param $0 i32) (param $1 i32) + (drop + (i32.const 100) + ) + (drop + (i32.const 127) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const 128) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (unreachable) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.const 1) + (i32.const 1) + ) + ) + (drop + (i32.and + (i32.const 127) + (i32.const 128) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.and + (i32.const 128) + (i32.const 129) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.xor + (i32.const 127) + (i32.const 126) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.xor + (i32.const 127) + (i32.const 128) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.or + (i32.const 127) + (i32.const 126) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.or + (i32.const 127) + (i32.const 128) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const 32) + (i32.const 26) + ) + (i32.const 24) + ) + ) + (drop + (i32.shl + (i32.const 32) + (i32.const 1) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const 32) + (i32.const 27) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.const 256) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.const 256) + (i32.const 2) + ) + ) + (drop + (i32.shr_u + (i32.const 128) + (i32.const 3) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.const 256) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.const 256) + (i32.const 2) + ) + ) + (drop + (i32.shr_u + (i32.const 128) + (i32.const 3) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const -1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.and + (i32.const -1) + (i32.const 2147483647) + ) + (i32.const 31) + ) + ) + (drop + (i32.const 0) + ) + (drop + (f32.le + (f32.const -1) + (f32.const -1) + ) + ) + (drop + (i32.clz + (i32.const 0) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.clz + (i32.const 0) + ) + (i32.const 26) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.clz + (i32.const 0) + ) + (i32.const 27) + ) + (i32.const 24) + ) + ) + (drop + (i32.wrap_i64 + (i64.clz + (i64.const 0) + ) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.wrap_i64 + (i64.clz + (i64.const 0) + ) + ) + (i32.const 25) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.wrap_i64 + (i64.clz + (i64.const 0) + ) + ) + (i32.const 26) + ) + (i32.const 24) + ) + ) + (drop + (i32.eqz + (i32.const -1) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.wrap_i64 + (i64.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.wrap_i64 + (i64.const -1) + ) + (i32.const 25) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.wrap_i64 + (i64.extend_i32_s + (i32.const -1) + ) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.wrap_i64 + (i64.extend_i32_s + (i32.const -1) + ) + ) + (i32.const 25) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.xor + (local.get $0) + (i32.le_u + (local.get $0) + (i32.const 2) + ) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $linear-sums (param $0 i32) (param $1 i32) + (drop + (i32.add + (i32.shl + (local.get $0) + (i32.const 4) + ) + (local.get $1) + ) + ) + (drop + (i32.add + (i32.add + (local.get $1) + (i32.shl + (local.get $0) + (i32.const 3) + ) + ) + (i32.const 12) + ) + ) + (drop + (i32.const 4) + ) + (drop + (i32.const 18) + ) + (drop + (i32.const 6) + ) + (drop + (i32.const -4) + ) + (drop + (i32.const 2) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 26) + ) + (drop + (i32.const -20) + ) + (drop + (i32.const 22) + ) + (drop + (i32.add + (i32.shl + (i32.const 1) + (local.get $0) + ) + (i32.const 14) + ) + ) + (drop + (i32.sub + (i32.shl + (local.get $1) + (i32.const 3) + ) + (i32.const 66) + ) + ) + (drop + (i32.const 44) + ) + (drop + (i32.add + (i32.mul + (local.get $0) + (i32.const 10) + ) + (i32.const 14) + ) + ) + (drop + (i32.add + (i32.shl + (local.get $0) + (i32.const 1) + ) + (i32.const 34) + ) + ) + (drop + (local.get $0) + ) + ) + (func $almost-sign-ext (param $0 i32) + (drop + (i32.shr_s + (i32.shl + (i32.const 100) + (i32.const 25) + ) + (i32.const 24) + ) + ) + (drop + (i32.shl + (i32.const 50) + (i32.const 1) + ) + ) + ) + (func $squaring (param $0 i32) (param $1 i32) + (drop + (i32.and + (local.get $0) + (i32.const 8) + ) + ) + (drop + (i32.and + (local.get $0) + (i32.const 11) + ) + ) + (drop + (i32.and + (local.get $0) + (i32.const 8) + ) + ) + (drop + (i32.or + (local.get $0) + (i32.const 203) + ) + ) + (drop + (i32.shl + (local.get $0) + (i32.const 19) + ) + ) + (drop + (i32.shr_s + (local.get $0) + (i32.const 19) + ) + ) + (drop + (i32.shr_u + (local.get $0) + (i32.const 19) + ) + ) + (drop + (i32.shr_u + (i32.shr_s + (local.get $0) + (i32.const 11) + ) + (i32.const 8) + ) + ) + ) + (func $sign-ext-ne (param $0 i32) (param $1 i32) + (drop + (block (result i32) + (drop + (local.get $0) + ) + (i32.const 1) + ) + ) + (drop + (block (result i32) + (drop + (local.get $0) + ) + (i32.const 1) + ) + ) + (drop + (block (result i32) + (drop + (local.get $0) + ) + (i32.const 1) + ) + ) + (drop + (i32.ne + (i32.and + (local.get $0) + (i32.const 255) + ) + (i32.const 111) + ) + ) + (drop + (i32.ne + (i32.and + (local.get $0) + (i32.const 255) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + ) + (func $sign-ext-eqz (param $0 i32) (param $1 i32) + (drop + (i32.eqz + (i32.and + (local.get $0) + (i32.const 255) + ) + ) + ) + ) + (func $sign-ext-boolean (param $0 i32) (param $1 i32) + (drop + (if (result i32) + (i32.and + (local.get $0) + (i32.const 255) + ) + (i32.const 100) + (i32.const 200) + ) + ) + ) + (func $add-sub-zero (param $0 i32) (param $1 i64) + (drop + (local.get $0) + ) + (drop + (local.get $0) + ) + (drop + (local.get $1) + ) + (drop + (local.get $1) + ) + ) + (func $store-signext (param $0 i32) + (i32.store8 + (i32.const 8) + (local.get $0) + ) + (i32.store8 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 25) + ) + (i32.const 25) + ) + ) + (i32.store8 + (i32.const 8) + (local.get $0) + ) + (i32.store16 + (i32.const 8) + (local.get $0) + ) + (i32.store16 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 17) + ) + (i32.const 17) + ) + ) + (i32.store16 + (i32.const 8) + (local.get $0) + ) + (i32.store + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + ) + (i32.store + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 8) + ) + (i32.const 8) + ) + ) + ) + (func $sign-ext-tee (param $0 i32) (param $1 i32) + (drop + (i32.shr_s + (i32.shl + (local.tee $0 + (i32.const 128) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (local.tee $0 + (i32.const 127) + ) + ) + ) + (func $sign-ext-load (param $0 i32) (param $1 i32) + (drop + (i32.load8_s + (i32.const 256) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.load8_s + (i32.const 256) + ) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_u + (i32.load8_u + (i32.const 256) + ) + (i32.const 1) + ) + ) + (drop + (i32.load16_s + (i32.const 256) + ) + ) + (drop + (local.tee $1 + (i32.load8_s + (i32.const 1) + ) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.tee $1 + (i32.load8_u + (i32.const 1) + ) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.and + (local.tee $1 + (i32.load8_s + (i32.const 1) + ) + ) + (i32.const 255) + ) + ) + (drop + (local.tee $1 + (i32.load8_u + (i32.const 1) + ) + ) + ) + ) + (func $mask-bits (param $0 i32) (param $1 i32) + (drop + (local.tee $0 + (i32.const 127) + ) + ) + (drop + (local.tee $0 + (i32.const 128) + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 254) + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 1279) + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 1290) + ) + ) + (drop + (local.tee $0 + (i32.const 128) + ) + ) + (drop + (local.tee $0 + (i32.const 128) + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 127) + ) + ) + ) + (func $local-info-zero-ext (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.const 212) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.const 500) + ) + (drop + (i32.and + (local.get $y) + (i32.const 255) + ) + ) + (local.set $0 + (i32.const 212) + ) + (drop + (i32.and + (local.get $0) + (i32.const 255) + ) + ) + (local.set $z + (i32.const 212) + ) + (local.set $z + (i32.const 220) + ) + (drop + (local.get $z) + ) + (local.set $w + (i32.const 212) + ) + (local.set $w + (i32.const 1000) + ) + (drop + (i32.and + (local.get $w) + (i32.const 255) + ) + ) + ) + (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.const 127) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.const 128) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $0 + (i32.const 127) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.const 127) + ) + (local.set $z + (i32.const 100) + ) + (drop + (local.get $z) + ) + (local.set $w + (i32.const 127) + ) + (local.set $w + (i32.const 150) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $w) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $0 + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (local.get $z) + ) + (local.set $w + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $w + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 23) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $w) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 23) + ) + ) + ) + (func $signed-loads-fill-the-bits (param $$e i32) (result i32) + (local $$0 i32) + (local $$conv i32) + (local.set $$0 + (i32.load8_s + (i32.const 1024) + ) + ) + (local.set $$conv + (i32.and + (local.get $$0) + (i32.const 255) + ) + ) + (return + (i32.eq + (local.get $$e) + (local.get $$conv) + ) + ) + ) + (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.load8_s + (i32.const 1024) + ) + ) + (drop + (local.get $x) + ) + (local.set $y + (i32.load8_u + (i32.const 1024) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.load16_s + (i32.const 1024) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $z) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32) + (drop + (i32.eq + (i32.load8_u + (local.get $0) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (drop + (i32.eq + (i32.load8_u + (local.get $0) + ) + (i32.and + (local.get $1) + (i32.const 255) + ) + ) + ) + (drop + (i32.eq + (i32.load8_u + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (drop + (i32.eq + (i32.load8_s + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (drop + (i32.eq + (i32.load8_u + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (drop + (i32.eq + (i32.load8_s + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + ) + (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.and + (call $unsign-same-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 255) + ) + (i32.and + (call $unsign-same-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 255) + ) + ) + ) + (func $fuzz-almost-sign-ext + (drop + (i32.shr_s + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 17) + ) + (i32.const 16) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 17) + ) + (i32.const 16) + ) + ) + ) + (func $fuzz-comp-impossible (param $x i32) + (drop + (block (result i32) + (drop + (local.get $x) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (local.get $x) + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 127) + ) + ) + (drop + (block (result i32) + (drop + (local.get $x) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (local.get $x) + ) + (i32.const 0) + ) + ) + (drop + (block (result i32) + (drop + (local.get $x) + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.const 252) + ) + ) + ) + (func $if-parallel (param $0 i32) (param $1 i32) + (drop + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (drop + (block (result i32) + (drop + (local.tee $0 + (local.get $1) + ) + ) + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + ) + (drop + (block (result i32) + (i32.add + (local.get $1) + (unreachable) + ) + ) + ) + (drop + (block (result i32) + (drop + (local.tee $0 + (local.get $1) + ) + ) + (i32.add + (local.get $1) + (unreachable) + ) + ) + ) + (drop + (if (result i32) + (unreachable) + (i32.add + (local.get $1) + (unreachable) + ) + (i32.add + (local.get $1) + (unreachable) + ) + ) + ) + ) + (func $select-parallel (param $0 i32) (param $1 i32) + (drop + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select + (local.tee $0 + (local.get $1) + ) + (local.tee $0 + (local.get $1) + ) + (local.get $0) + ) + ) + (drop + (block (result i32) + (drop + (local.tee $0 + (local.get $1) + ) + ) + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + ) + (drop + (select + (local.tee $0 + (local.get $1) + ) + (local.tee $0 + (local.get $1) + ) + (local.tee $0 + (local.get $1) + ) + ) + ) + (drop + (select + (local.tee $0 + (local.get $1) + ) + (local.tee $0 + (local.get $1) + ) + (unreachable) + ) + ) + ) + (func $zero-shifts-is-not-sign-ext + (drop + (i32.eq + (i32.load16_s align=1 + (i32.const 790656516) + ) + (i32.const -5431187) + ) + ) + (drop + (i32.eq + (i32.shl + (i32.load16_s align=1 + (i32.const 790656516) + ) + (i32.const 1) + ) + (i32.const -5431187) + ) + ) + ) + (func $zero-ops (result i32) + (return + (i32.eq + (i32.load16_s align=1 + (i32.const 790656516) + ) + (i32.const -1337) + ) + ) + ) + (func $zero-ops-64 (result i32) + (return + (i64.eq + (i64.load16_s align=1 + (i32.const 790656516) + ) + (i64.const -1337) + ) + ) + ) + (func $zero-ops-64-special (result i32) + (return + (i32.wrap_i64 + (i64.popcnt + (i64.const 7377) + ) + ) + ) + ) + (func $sign-ext-1-and-ne (result i32) + (drop + (call $sign-ext-1-and-ne) + ) + (i32.const 1) + ) + (func $neg-shifts-and-255 (result i32) + (i32.and + (i32.const -99) + (i32.const 255) + ) + ) + (func $neg-shifts-and-255-b (result i32) + (i32.and + (i32.const -2349025) + (i32.const 255) + ) + ) + (func $shifts-square-overflow (param $x i32) (result i32) + (i32.shr_u + (i32.shr_u + (local.get $x) + (i32.const 31) + ) + (i32.const 31) + ) + ) + (func $shifts-square-no-overflow-small (param $x i32) (result i32) + (i32.shr_u + (local.get $x) + (i32.const 9) + ) + ) + (func $shifts-square-overflow-64 (param $x i64) (result i64) + (i64.shr_u + (i64.shr_u + (local.get $x) + (i64.const 63) + ) + (i64.const 63) + ) + ) + (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64) + (i64.shr_u + (local.get $x) + (i64.const 9) + ) + ) + (func $shifts-square-unreachable (param $x i32) (result i32) + (i32.shr_u + (i32.shr_u + (unreachable) + (i32.const 1031) + ) + (i32.const 4098) + ) + ) + (func $mix-shifts (result i32) + (i32.shr_u + (i32.shl + (i32.const 23) + (i32.const 3) + ) + (i32.const 8) + ) + ) + (func $actually-no-shifts (result i32) + (i32.const 33) + ) + (func $less-shifts-than-it-seems (param $x i32) (result i32) + (i32.const 4800) + ) + (func $and-popcount32 (result i32) + (i32.and + (i32.popcnt + (i32.const -1) + ) + (i32.const 31) + ) + ) + (func $and-popcount32-big (result i32) + (i32.popcnt + (i32.const -1) + ) + ) + (func $and-popcount64 (result i64) + (i64.and + (i64.popcnt + (i64.const -1) + ) + (i64.const 63) + ) + ) + (func $and-popcount64-big (result i64) + (i64.and + (i64.popcnt + (i64.const -1) + ) + (i64.const 127) + ) + ) + (func $and-popcount64-bigger (result i64) + (i64.and + (i64.popcnt + (i64.const -1) + ) + (i64.const 255) + ) + ) + (func $optimizeAddedConstants-filters-through-nonzero (result i32) + (i32.sub + (i32.shl + (i32.const -536870912) + (i32.wrap_i64 + (i64.const 0) + ) + ) + (i32.const 31744) + ) + ) + (func $optimizeAddedConstants-filters-through-nonzero-b (result i32) + (i32.sub + (i32.shl + (i32.const -536870912) + (i32.wrap_i64 + (i64.const -1) + ) + ) + (i32.const 31744) + ) + ) + (func $return-proper-value-from-shift-left-by-zero (result i32) + (if (result i32) + (i32.add + (loop $label$0 (result i32) + (block $label$1 + (br_if $label$1 + (i32.load + (i32.const 0) + ) + ) + ) + (i32.const -62) + ) + (i32.const 40) + ) + (i32.const 1) + (i32.const 0) + ) + ) + (func $de-morgan-2 (param $x i32) (param $y i32) + (drop + (i32.eqz + (i32.or + (local.get $x) + (local.get $y) + ) + ) + ) + (drop + (i32.or + (i32.eqz + (local.get $x) + ) + (i32.eqz + (local.get $y) + ) + ) + ) + (drop + (i32.xor + (i32.eqz + (local.get $x) + ) + (i32.eqz + (local.get $y) + ) + ) + ) + (drop + (i32.and + (local.get $y) + (i32.eqz + (local.get $x) + ) + ) + ) + (drop + (i32.and + (i32.eqz + (local.get $y) + ) + (local.get $x) + ) + ) + (drop + (i32.and + (i32.eqz + (local.get $x) + ) + (i32.wrap_i64 + (i64.const 2) + ) + ) + ) + (drop + (i32.and + (i32.eqz + (local.get $y) + ) + (i32.wrap_i64 + (i64.const 1) + ) + ) + ) + ) + (func $subzero1 (param $0 i32) (result i32) + (i32.sub + (i32.const 32) + (i32.clz + (local.get $0) + ) + ) + ) + (func $subzero2 (param $0 i32) (result i32) + (i32.sub + (i32.const 32) + (i32.clz + (local.get $0) + ) + ) + ) + (func $subzero3 (param $0 i32) (param $1 i32) (result i32) + (i32.sub + (local.get $1) + (i32.clz + (local.get $0) + ) + ) + ) + (func $subzero4 (param $0 i32) (param $1 i32) (result i32) + (i32.sub + (local.get $0) + (i32.clz + (local.get $1) + ) + ) + ) + (func $mul-32-power-2 (param $x i32) (result i32) + (drop + (call $mul-32-power-2 + (i32.shl + (local.get $x) + (i32.const 2) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 5) + ) + ) + ) + (drop + (call $mul-32-power-2 + (local.get $x) + ) + ) + (drop + (call $mul-32-power-2 + (i32.const 0) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (call $mul-32-power-2 + (i32.const 123) + ) + (i32.const 0) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.sub + (i32.const 0) + (local.get $x) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.shl + (local.get $x) + (i32.const 31) + ) + ) + ) + (unreachable) + ) + (func $mul-64-power-2 (param $x i64) (result i64) + (drop + (call $mul-64-power-2 + (i64.shl + (local.get $x) + (i64.const 2) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 5) + ) + ) + ) + (drop + (call $mul-64-power-2 + (local.get $x) + ) + ) + (drop + (call $mul-64-power-2 + (i64.const 0) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (call $mul-64-power-2 + (i64.const 123) + ) + (i64.const 0) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.sub + (i64.const 0) + (local.get $x) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.shl + (local.get $x) + (i64.const 63) + ) + ) + ) + (unreachable) + ) + (func $div-32-power-2 (param $x i32) (result i32) + (drop + (call $div-32-power-2 + (i32.shr_u + (local.get $x) + (i32.const 2) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 5) + ) + ) + ) + (drop + (call $div-32-power-2 + (local.get $x) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (call $div-32-power-2 + (i32.const 123) + ) + (i32.const 0) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.eq + (local.get $x) + (i32.const -1) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.shr_u + (local.get $x) + (i32.const 31) + ) + ) + ) + (unreachable) + ) + (func $urem-32-power-2 (param $x i32) (result i32) + (drop + (call $urem-32-power-2 + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 5) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.const 0) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const -1) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.const 0) + ) + ) + (unreachable) + ) + (func $fdiv-32-power-2 (param $x f32) + (drop + (f32.mul + (local.get $x) + (f32.const 0.5) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const -0.5) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const 2.3283064365386963e-10) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const 5.421010862427522e-20) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const 8507059173023461586584365e13) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const 1.1754943508222875e-38) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const -8507059173023461586584365e13) + ) + ) + (drop + (f32.mul + (local.get $x) + (f32.const -1.1754943508222875e-38) + ) + ) + (drop + (f32.div + (local.get $x) + (f32.const 5.877471754111438e-39) + ) + ) + (drop + (f32.div + (local.get $x) + (f32.const 5.877471754111438e-39) + ) + ) + (drop + (f32.div + (local.get $x) + (f32.const 0) + ) + ) + (drop + (f32.div + (local.get $x) + (f32.const nan:0x400000) + ) + ) + (drop + (f32.div + (local.get $x) + (f32.const inf) + ) + ) + (drop + (f32.div + (local.get $x) + (f32.const -inf) + ) + ) + ) + (func $fdiv-64-power-2 (param $x f64) + (drop + (f64.mul + (local.get $x) + (f64.const 0.5) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const -0.5) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const 2.3283064365386963e-10) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const 5.421010862427522e-20) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const 4494232837155789769323262e283) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const 2.2250738585072014e-308) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const -4494232837155789769323262e283) + ) + ) + (drop + (f64.mul + (local.get $x) + (f64.const -2.2250738585072014e-308) + ) + ) + (drop + (f64.div + (local.get $x) + (f64.const 1.1125369292536007e-308) + ) + ) + (drop + (f64.div + (local.get $x) + (f64.const 8988465674311579538646525e283) + ) + ) + (drop + (f64.div + (local.get $x) + (f64.const 0) + ) + ) + (drop + (f64.div + (local.get $x) + (f64.const nan:0x8000000000000) + ) + ) + (drop + (f64.div + (local.get $x) + (f64.const inf) + ) + ) + (drop + (f64.div + (local.get $x) + (f64.const -inf) + ) + ) + ) + (func $srem-by-const (param $x i32) (param $y i64) + (drop + (i32.const 0) + ) + (drop + (i64.const 0) + ) + (drop + (i32.rem_s + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i64.rem_s + (local.get $y) + (i64.const -9223372036854775808) + ) + ) + ) + (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 3) + ) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 3) + ) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 1) + ) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 3) + ) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i32.wrap_i64 + (i64.and + (local.get $y) + (i64.const 1) + ) + ) + ) + (drop + (i32.eqz + (i32.const 0) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + ) + ) + (drop + (i32.ne + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const 0) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 9223372036854775807) + ) + ) + ) + (drop + (i64.ne + (i64.and + (local.get $y) + (i64.const 9223372036854775807) + ) + (i64.const 0) + ) + ) + (drop + (i32.eqz + (i32.rem_s + (local.get $x) + (i32.const 3) + ) + ) + ) + (drop + (i64.eqz + (i64.rem_s + (local.get $y) + (i64.const 3) + ) + ) + ) + ) + (func $orZero (param $0 i32) (result i32) + (local.get $0) + ) + (func $andZero (param $0 i32) (result i32) + (drop + (i32.const 0) + ) + (drop + (i32.and + (call $andZero + (i32.const 1234) + ) + (i32.const 0) + ) + ) + (unreachable) + ) + (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64) + (drop + (local.get $x32) + ) + (drop + (local.get $x32) + ) + (drop + (local.get $x32) + ) + (drop + (local.get $x32) + ) + (drop + (local.get $x64) + ) + (drop + (local.get $x64) + ) + (drop + (local.get $x64) + ) + (drop + (local.get $x64) + ) + (drop + (i32.const 0) + ) + (drop + (i64.const 0) + ) + (drop + (f32.mul + (local.get $y32) + (f32.const 0) + ) + ) + (drop + (f64.mul + (local.get $y64) + (f64.const 0) + ) + ) + (drop + (local.get $x32) + ) + (drop + (local.get $x64) + ) + (drop + (f32.mul + (local.get $y32) + (f32.const 1) + ) + ) + (drop + (f64.mul + (local.get $y64) + (f64.const 1) + ) + ) + (drop + (i32.const 0) + ) + (drop + (i64.const 0) + ) + (drop + (i32.and + (unreachable) + (i32.const 0) + ) + ) + (drop + (i64.and + (unreachable) + (i64.const 0) + ) + ) + (drop + (local.get $x32) + ) + (drop + (local.get $x32) + ) + (drop + (local.get $x64) + ) + (drop + (local.get $x64) + ) + (drop + (f32.mul + (local.get $y32) + (f32.const 1) + ) + ) + (drop + (f64.mul + (local.get $y64) + (f64.const 1) + ) + ) + (drop + (f32.div + (local.get $y32) + (f32.const 1.2000000476837158) + ) + ) + (drop + (i32.sub + (i32.const 0) + (local.get $x32) + ) + ) + (drop + (i64.sub + (i64.const 0) + (local.get $x64) + ) + ) + (drop + (f32.sub + (f32.const -0) + (local.get $y32) + ) + ) + (drop + (f64.sub + (f64.const -0) + (local.get $y64) + ) + ) + (drop + (i32.eq + (local.get $x32) + (i32.const 10) + ) + ) + (drop + (i32.le_u + (i32.add + (local.get $x32) + (i32.const 10) + ) + (i32.const 20) + ) + ) + (drop + (i32.eq + (local.get $x32) + (i32.const 30) + ) + ) + (drop + (i64.eq + (local.get $x64) + (i64.const 10) + ) + ) + (drop + (i32.eq + (local.get $x32) + (i32.const 10) + ) + ) + (drop + (i32.eq + (i32.add + (local.get $x32) + (i32.const 10) + ) + (local.get $x32) + ) + ) + (drop + (i32.eq + (local.get $x32) + (i32.const 30) + ) + ) + (drop + (i32.eq + (i32.sub + (local.get $x32) + (i32.const 30) + ) + (local.get $x32) + ) + ) + (drop + (i32.eq + (i32.add + (local.get $x32) + (i32.const 30) + ) + (local.get $x32) + ) + ) + (drop + (i32.eq + (i32.sub + (local.get $x32) + (i32.const 10) + ) + (local.get $x32) + ) + ) + (drop + (i32.const 1) + ) + ) + (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32) + (drop + (i32.sub + (local.get $x) + (i32.const -64) + ) + ) + (drop + (i32.add + (local.get $x) + (i32.const -64) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const -8192) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const -1048576) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const -134217728) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -64) + ) + ) + (drop + (i64.add + (local.get $y) + (i64.const -64) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -8192) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -1048576) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -134217728) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -17179869184) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -2199023255552) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -281474976710656) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -36028797018963968) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const -4611686018427387904) + ) + ) + (drop + (f32.add + (local.get $z) + (f32.const 64) + ) + ) + ) + (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i64.const 0) + ) + (drop + (i32.shl + (i32.const 0) + (unreachable) + ) + ) + ) + (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32) + (drop + (i32.const 0) + ) + (drop + (i64.const 0) + ) + (drop + (f64.sub + (local.get $z) + (local.get $z) + ) + ) + (drop + (i32.sub + (local.get $x) + (local.get $xx) + ) + ) + (drop + (i32.sub + (unreachable) + (unreachable) + ) + ) + (drop + (i32.add + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (local.get $x) + ) + (drop + (local.get $x) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i64.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (local.get $y) + ) + (drop + (local.get $y) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + ) + (func $all_ones (param $x i32) (param $y i64) + (drop + (local.get $x) + ) + (drop + (i32.const -1) + ) + (drop + (i32.or + (local.tee $x + (i32.const 1337) + ) + (i32.const -1) + ) + ) + (drop + (local.get $y) + ) + (drop + (i64.const -1) + ) + ) + (func $xor (param $x i32) (param $y i64) + (drop + (local.get $x) + ) + ) + (func $select-on-const (param $x i32) (param $y i64) + (drop + (local.get $x) + ) + (drop + (i32.const 3) + ) + (drop + (local.tee $x + (i32.const 5) + ) + ) + (drop + (block (result i32) + (drop + (local.tee $x + (i32.const 6) + ) + ) + (i32.const 7) + ) + ) + (drop + (select + (i32.const 4) + (local.tee $x + (i32.const 5) + ) + (i32.const 1) + ) + ) + (drop + (local.tee $x + (i32.const 6) + ) + ) + (drop + (i32.eqz + (i32.eqz + (local.get $x) + ) + ) + ) + (drop + (i32.eqz + (local.get $x) + ) + ) + (drop + (i32.ge_s + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i32.gt_s + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i32.le_s + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i32.ge_s + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i64.extend_i32_u + (i32.eqz + (i32.eqz + (local.get $x) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (i32.eqz + (local.get $x) + ) + ) + ) + (drop + (i64.extend_i32_u + (i64.eqz + (local.get $y) + ) + ) + ) + (drop + (i64.extend_i32_u + (i32.eqz + (i64.eqz + (local.get $y) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (i64.ge_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (i64.extend_i32_u + (i64.lt_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (i64.extend_i32_u + (i64.lt_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (i64.extend_i32_u + (i64.ge_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (select + (i32.const 0) + (local.get $x) + (i32.const 0) + ) + ) + (drop + (select + (i32.const 2) + (local.get $x) + (i32.const 2) + ) + ) + (drop + (select + (local.get $x) + (i32.const 2) + (local.get $x) + ) + ) + (drop + (select + (local.get $y) + (i64.const 0) + (i64.eqz + (i64.const 0) + ) + ) + ) + (drop + (select + (local.get $y) + (i64.const 2) + (i64.eqz + (i64.const 2) + ) + ) + ) + ) + (func $optimize-boolean (param $x i32) (param $y i64) + (drop + (select + (i32.const 1) + (i32.const 2) + (local.get $x) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i32.eqz + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + ) + (drop + (i32.wrap_i64 + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + ) + ) + (drop + (i32.eqz + (i32.shr_u + (local.get $x) + (i32.const 31) + ) + ) + ) + (drop + (i64.eqz + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + ) + ) + (drop + (i64.eqz + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + ) + ) + (drop + (i64.eqz + (local.get $y) + ) + ) + (drop + (i32.eqz + (i32.wrap_i64 + (local.get $y) + ) + ) + ) + (drop + (i32.wrap_i64 + (i64.and + (local.get $y) + (i64.const 1) + ) + ) + ) + (drop + (i64.eqz + (i64.and + (local.get $y) + (i64.const 1) + ) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i64.and + (local.get $y) + (i64.const 1) + ) + ) + (drop + (i64.const 1) + ) + (drop + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i64.ne + (local.get $y) + (i64.const 0) + ) + ) + (drop + (i32.ne + (local.get $x) + (i32.const 0) + ) + ) + (drop + (if (result i32) + (i32.and + (local.get $x) + (i32.const 3) + ) + (i32.const 1) + (i32.const 0) + ) + ) + (drop + (if (result i32) + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const 1) + (i32.const 0) + ) + ) + ) + (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64) + (drop + (i32.rotl + (i32.const -2) + (local.get $x) + ) + ) + (drop + (i64.rotl + (i64.const -2) + (local.get $z) + ) + ) + ) + (func $getFallthrough + (local $x0 i32) + (local $x1 i32) + (local $x2 i32) + (local $x3 i32) + (local $x4 i32) + (local $x5 i32) + (local $x6 i32) + (local $x7 i32) + (local.set $x0 + (i32.const 1) + ) + (drop + (local.get $x0) + ) + (local.set $x1 + (local.tee $x2 + (i32.const 1) + ) + ) + (drop + (local.get $x1) + ) + (local.set $x3 + (loop $loop-in (result i32) + (i32.const 1) + ) + ) + (drop + (local.get $x3) + ) + (local.set $x4 + (if (result i32) + (i32.const 1) + (i32.const 2) + (i32.const 3) + ) + ) + (drop + (i32.and + (local.get $x4) + (i32.const 7) + ) + ) + (local.set $x5 + (if (result i32) + (i32.const 1) + (unreachable) + (i32.const 3) + ) + ) + (drop + (local.get $x5) + ) + (local.set $x6 + (if (result i32) + (i32.const 1) + (i32.const 3) + (unreachable) + ) + ) + (drop + (local.get $x6) + ) + (drop + (block $out (result i32) + (local.set $x7 + (br_if $out + (i32.const 1) + (i32.const 1) + ) + ) + (drop + (local.get $x7) + ) + (unreachable) + ) + ) + ) + (func $tee-with-unreachable-value (result f64) + (local $var$0 i32) + (block $label$1 (result f64) + (local.tee $var$0 + (br_if $label$1 + (f64.const 1) + (unreachable) + ) + ) + ) + ) + (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) + (i32.add + (i32.add + (i32.sub + (i32.const 0) + (local.get $temp) + ) + (local.tee $temp + (i32.const 1) + ) + ) + (i32.const 2) + ) + ) + (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) + (i32.add + (i32.sub + (local.tee $temp + (i32.const 1) + ) + (local.get $temp) + ) + (i32.const 2) + ) + ) + (func $const-float-zero (param $fx f32) (param $fy f64) + (drop + (f32.sub + (local.get $fx) + (f32.const 0) + ) + ) + (drop + (f64.sub + (local.get $fy) + (f64.const 0) + ) + ) + (drop + (f32.add + (local.get $fx) + (f32.const -0) + ) + ) + (drop + (f64.add + (local.get $fy) + (f64.const -0) + ) + ) + (drop + (f32.add + (local.get $fx) + (f32.const 0) + ) + ) + (drop + (f64.add + (local.get $fy) + (f64.const 0) + ) + ) + (drop + (f32.sub + (f32.const 0) + (local.get $fx) + ) + ) + (drop + (f64.sub + (f64.const 0) + (local.get $fy) + ) + ) + (drop + (f32.add + (local.get $fx) + (f32.const 0) + ) + ) + (drop + (f64.add + (local.get $fy) + (f64.const 0) + ) + ) + (drop + (f32.sub + (f32.const -nan:0x34546d) + (f32.const 0) + ) + ) + ) + (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) + (drop + (i32.add + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i64.add + (local.get $y) + (i64.const 1) + ) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.gt_s + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i64.gt_s + (local.get $y) + (i64.const -1) + ) + ) + (drop + (i64.extend_i32_s + (i32.const 0) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.le_s + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i64.le_s + (local.get $y) + (i64.const -1) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i64.eq + (local.get $y) + (i64.const -1) + ) + ) + (drop + (i32.ne + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i64.ne + (local.get $y) + (i64.const -1) + ) + ) + (drop + (i32.sub + (i32.const 0) + (local.get $x) + ) + ) + (drop + (i64.sub + (i64.const 0) + (local.get $y) + ) + ) + (drop + (f32.sub + (f32.const -0) + (local.get $fx) + ) + ) + (drop + (f64.sub + (f64.const -0) + (local.get $fy) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i64.extend_i32_u + (i64.eq + (local.get $y) + (i64.const -1) + ) + ) + ) + ) + (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) + (drop + (i32.eq + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i64.extend_i32_u + (i64.eq + (local.get $y) + (i64.const -9223372036854775808) + ) + ) + ) + (drop + (i64.div_s + (local.get $y) + (i64.const -2147483648) + ) + ) + (drop + (i32.ge_u + (local.get $x) + (i32.const -2) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i32.ge_u + (local.get $x) + (i32.const -2147483647) + ) + ) + (drop + (i32.shr_u + (local.get $x) + (i32.const 31) + ) + ) + (drop + (i64.extend_i32_u + (i64.eq + (local.get $y) + (i64.const -1) + ) + ) + ) + (drop + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.ne + (local.get $x) + (i32.const 0) + ) + ) + (drop + (i64.ne + (local.get $y) + (i64.const 0) + ) + ) + (drop + (i32.eqz + (local.get $x) + ) + ) + (drop + (i64.eqz + (local.get $y) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.ne + (local.get $x) + (i32.const 2147483647) + ) + ) + (drop + (i64.ne + (local.get $y) + (i64.const 9223372036854775807) + ) + ) + (drop + (i32.ne + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i64.ne + (local.get $y) + (i64.const -9223372036854775808) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i64.eq + (local.get $y) + (i64.const -9223372036854775808) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const 2147483647) + ) + ) + (drop + (i64.eq + (local.get $y) + (i64.const 9223372036854775807) + ) + ) + (drop + (f32.sub + (f32.const -0) + (local.get $fx) + ) + ) + (drop + (f64.mul + (local.get $fy) + (f64.const 2.1) + ) + ) + (drop + (f64.mul + (local.get $fy) + (f64.const -2) + ) + ) + (drop + (f32.div + (local.get $fx) + (f32.const -inf) + ) + ) + (drop + (f64.div + (local.get $fy) + (f64.const 0) + ) + ) + (drop + (f64.div + (local.get $fy) + (f64.const -nan:0x8000000000000) + ) + ) + (drop + (f64.div + (f64.const -5) + (local.get $fy) + ) + ) + ) + (func $lhs-is-neg-one (param $x i32) (param $y i64) + (drop + (i32.const -1) + ) + (drop + (i64.const -1) + ) + (drop + (i32.const -1) + ) + (drop + (i64.const -1) + ) + (drop + (i32.const -1) + ) + (drop + (i64.const -1) + ) + (drop + (i32.shr_s + (i32.const -1) + (call $ne0) + ) + ) + (drop + (i32.shr_u + (i32.const -1) + (local.get $x) + ) + ) + ) + (func $lhs-is-const (param $x i32) (param $y i64) + (drop + (i32.sub + (i32.const 1) + (local.get $x) + ) + ) + (drop + (i64.sub + (i64.const 1) + (local.get $y) + ) + ) + (drop + (i32.sub + (i32.const -2) + (local.get $x) + ) + ) + (drop + (i64.sub + (i64.const -2) + (local.get $y) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i64.sub + (local.get $y) + (i64.const 1) + ) + ) + (drop + (i32.sub + (local.get $x) + (i32.const -2147483648) + ) + ) + ) + (func $pre-combine-or (param $x i32) (param $y i32) + (drop + (i32.ge_s + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.ge_s + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.or + (i32.eq + (local.get $x) + (i32.const 1) + ) + (i32.gt_s + (local.get $x) + (local.get $y) + ) + ) + ) + (drop + (i32.or + (i32.eq + (local.get $x) + (local.get $y) + ) + (i32.gt_s + (local.get $x) + (i32.const 1) + ) + ) + ) + (drop + (i32.or + (i32.gt_s + (call $ne0) + (local.get $y) + ) + (i32.eq + (call $ne0) + (local.get $y) + ) + ) + ) + (drop + (i32.or + (i32.lt_s + (call $ne0) + (local.get $y) + ) + (i32.eq + (call $ne0) + (local.get $y) + ) + ) + ) + ) + (func $combine-or (param $x i32) (param $y i32) + (drop + (i32.ge_s + (local.get $x) + (local.get $y) + ) + ) + ) + (func $select-into-arms (param $x i32) (param $y i32) + (if + (select + (local.get $x) + (local.get $y) + (local.get $y) + ) + (unreachable) + ) + ) + (func $optimize-boolean-context (param $x i32) (param $y i32) + (if + (local.get $x) + (unreachable) + ) + (drop + (select + (local.get $x) + (local.get $y) + (local.get $x) + ) + ) + ) + (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64) + (drop + (i32.eq + (local.get $x) + (i32.const -2147483647) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const 2147483647) + ) + ) + (drop + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + (drop + (i64.eq + (local.get $X) + (local.get $Y) + ) + ) + (drop + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + (drop + (i64.eq + (local.get $X) + (local.get $Y) + ) + ) + (drop + (i32.ne + (local.get $x) + (local.get $y) + ) + ) + (drop + (i64.ne + (local.get $X) + (local.get $Y) + ) + ) + (drop + (i32.gt_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + ) + ) + (drop + (i32.ge_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + ) + ) + (drop + (i32.ne + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 1) + ) + (drop + (i32.lt_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + ) + ) + (drop + (i32.le_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + ) + ) + (drop + (i32.const 0) + ) + (drop + (i32.const 0) + ) + (drop + (i32.eq + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.eq + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i32.ne + (local.get $x) + (i32.const -2147483648) + ) + ) + (drop + (i32.lt_s + (i32.sub + (local.get $x) + (i32.const -2147483648) + ) + (i32.const 0) + ) + ) + (drop + (i32.ge_s + (i32.sub + (local.get $x) + (i32.const -2147483648) + ) + (i32.const 0) + ) + ) + (drop + (i32.gt_s + (i32.sub + (local.get $x) + (block $block (result i32) + (i32.const -2147483648) + ) + ) + (i32.const 0) + ) + ) + (drop + (i32.gt_s + (i32.sub + (local.get $x) + (block $block29 (result i32) + (i32.const -2147483648) + ) + ) + (i32.const 0) + ) + ) + ) + (func $unsigned-context (param $x i32) (param $y i64) + (drop + (i32.div_u + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const 3) + ) + ) + (drop + (i32.div_s + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const -3) + ) + ) + (drop + (i32.eq + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const -2147483648) + ) + ) + (drop + (i64.shr_u + (i64.and + (local.get $y) + (i64.const 9223372036854775807) + ) + (i64.const 1) + ) + ) + (drop + (i64.div_s + (i64.and + (local.get $y) + (i64.const 9223372036854775807) + ) + (i64.const -1) + ) + ) + (drop + (i32.rem_u + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const 3) + ) + ) + (drop + (i32.shr_u + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const 7) + ) + ) + (drop + (i32.ge_u + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const 7) + ) + ) + (drop + (i32.ge_s + (i32.and + (local.get $x) + (i32.const 2147483647) + ) + (i32.const -7) + ) + ) + ) + (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32) + (drop + (f64.add + (local.get $0) + (local.get $0) + ) + ) + (drop + (f32.add + (local.get $1) + (local.get $1) + ) + ) + (drop + (f64.mul + (call $tee-with-unreachable-value) + (f64.const 2) + ) + ) + (drop + (f64.mul + (local.get $0) + (f64.const -2) + ) + ) + ) + (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) + (drop + (f64.abs + (local.get $w) + ) + ) + (drop + (f64.ceil + (local.get $w) + ) + ) + (drop + (f64.floor + (local.get $w) + ) + ) + (drop + (f64.trunc + (local.get $w) + ) + ) + (drop + (f64.nearest + (local.get $w) + ) + ) + (drop + (f64.nearest + (f64.trunc + (local.get $w) + ) + ) + ) + (drop + (f64.trunc + (f64.nearest + (local.get $w) + ) + ) + ) + (drop + (local.get $w) + ) + (drop + (f64.neg + (local.get $w) + ) + ) + (drop + (local.get $w) + ) + (drop + (i32.eqz + (i32.eqz + (local.get $x) + ) + ) + ) + (drop + (i32.eqz + (local.get $x) + ) + ) + (drop + (i64.eqz + (i64.const 1) + ) + ) + (drop + (i32.ne + (local.get $x) + (i32.const 2) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + (drop + (i32.rem_s + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.rem_u + (local.get $x) + (local.get $y) + ) + ) + (drop + (local.get $y) + ) + (drop + (local.get $y) + ) + (drop + (i32.sub + (local.get $y) + (i32.sub + (local.get $x) + (local.get $y) + ) + ) + ) + (drop + (local.get $y) + ) + (drop + (local.get $y) + ) + (drop + (local.get $y) + ) + (drop + (local.get $y) + ) + (drop + (local.get $x) + ) + (drop + (i32.and + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.and + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.and + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.and + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.or + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.or + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.or + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.or + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.or + (local.get $z) + (i32.or + (local.get $x) + (local.get $y) + ) + ) + ) + (drop + (i32.or + (local.get $y) + (i32.or + (local.get $x) + (local.get $z) + ) + ) + ) + (drop + (i32.or + (call $ne0) + (local.get $x) + ) + ) + (drop + (i32.or + (i32.or + (call $ne0) + (local.get $x) + ) + (call $ne0) + ) + ) + (drop + (i32.or + (call $ne0) + (local.get $x) + ) + ) + (drop + (i32.or + (call $ne0) + (i32.or + (call $ne0) + (local.get $x) + ) + ) + ) + (drop + (i32.rem_s + (i32.rem_s + (local.get $y) + (local.get $x) + ) + (local.get $y) + ) + ) + (drop + (i32.rem_u + (local.get $y) + (i32.rem_u + (local.get $x) + (local.get $y) + ) + ) + ) + (drop + (i32.or + (local.get $x) + (i32.or + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.or + (i32.or + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) + (drop + (i32.xor + (local.get $x) + (i32.xor + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.xor + (i32.xor + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) + ) + (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64) + (drop + (local.get $x) + ) + (drop + (local.get $x) + ) + (drop + (local.get $x) + ) + (drop + (local.get $x) + ) + (drop + (local.get $x) + ) + (drop + (local.get $z) + ) + (drop + (local.get $z) + ) + (drop + (local.get $z) + ) + (drop + (local.get $z) + ) + (drop + (local.get $z) + ) + (drop + (i32.shl + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.shl + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.shr_s + (local.get $x) + (local.get $y) + ) + ) + (drop + (i32.shr_u + (local.get $x) + (local.get $y) + ) + ) + (drop + (i64.shl + (local.get $z) + (local.get $w) + ) + ) + (drop + (i64.shl + (local.get $z) + (local.get $w) + ) + ) + (drop + (i64.shr_s + (local.get $z) + (local.get $w) + ) + ) + (drop + (i64.shr_u + (local.get $z) + (local.get $w) + ) + ) + (drop + (local.get $x) + ) + (drop + (local.get $z) + ) + (drop + (i64.shl + (local.get $z) + (i64.and + (local.get $w) + (i64.const 32) + ) + ) + ) + (drop + (i64.shr_u + (local.get $z) + (i64.and + (local.get $w) + (i64.const 31) + ) + ) + ) + ) + (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32) + (drop + (f64.mul + (local.get $x0) + (local.get $x0) + ) + ) + (drop + (f32.mul + (local.get $y0) + (local.get $y0) + ) + ) + (drop + (f64.mul + (f64.add + (local.get $x0) + (local.get $x1) + ) + (f64.add + (local.get $x0) + (local.get $x1) + ) + ) + ) + (drop + (f64.abs + (f64.mul + (local.get $x0) + (local.get $x1) + ) + ) + ) + (drop + (f32.abs + (f32.mul + (local.get $y1) + (local.get $y0) + ) + ) + ) + (drop + (f64.abs + (f64.mul + (local.get $x0) + (f64.const 0) + ) + ) + ) + (drop + (f32.abs + (f32.mul + (f32.const 0) + (local.get $y0) + ) + ) + ) + (drop + (f64.abs + (f64.mul + (f64.add + (local.get $x0) + (local.get $x1) + ) + (f64.add + (local.get $x0) + (local.get $x0) + ) + ) + ) + ) + (drop + (f64.abs + (local.get $x0) + ) + ) + (drop + (f32.abs + (local.get $y0) + ) + ) + (drop + (f64.abs + (f64.sub + (f64.const 0) + (local.get $x0) + ) + ) + ) + (drop + (f32.abs + (f32.sub + (f32.const 0) + (local.get $y0) + ) + ) + ) + (drop + (f64.div + (local.get $x0) + (local.get $x0) + ) + ) + (drop + (f32.div + (local.get $y0) + (local.get $y0) + ) + ) + (drop + (f64.div + (f64.add + (local.get $x0) + (local.get $x1) + ) + (f64.add + (local.get $x0) + (local.get $x1) + ) + ) + ) + (drop + (f64.abs + (f64.div + (local.get $x0) + (local.get $x1) + ) + ) + ) + (drop + (f32.abs + (f32.div + (local.get $y1) + (local.get $y0) + ) + ) + ) + (drop + (f64.mul + (local.get $x0) + (local.get $x0) + ) + ) + (drop + (f32.mul + (local.get $y0) + (local.get $y0) + ) + ) + (drop + (f64.div + (local.get $x0) + (local.get $x0) + ) + ) + (drop + (f32.div + (local.get $y0) + (local.get $y0) + ) + ) + (drop + (f64.abs + (f64.div + (local.get $x0) + (f64.const 0) + ) + ) + ) + (drop + (f32.abs + (f32.div + (f32.const 0) + (local.get $y0) + ) + ) + ) + (drop + (f64.abs + (f64.div + (f64.add + (local.get $x0) + (local.get $x1) + ) + (f64.add + (local.get $x0) + (local.get $x0) + ) + ) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (import "env" "memory" (memory $0 (shared 256 256))) + (func $x + (drop + (i32.shr_s + (i32.shl + (i32.atomic.load8_u + (i32.const 100) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) +) +(module + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (memory $0 0) + (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) + (memory.copy + (local.get $dst) + (local.get $dst) + (local.get $sz) + ) + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 0) + ) + (i32.store8 + (local.get $dst) + (i32.load8_u + (local.get $src) + ) + ) + (i32.store16 align=1 + (local.get $dst) + (i32.load16_u align=1 + (local.get $src) + ) + ) + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 3) + ) + (i32.store align=1 + (local.get $dst) + (i32.load align=1 + (local.get $src) + ) + ) + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 5) + ) + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 6) + ) + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 7) + ) + (i64.store align=1 + (local.get $dst) + (i64.load align=1 + (local.get $src) + ) + ) + (v128.store align=1 + (local.get $dst) + (v128.load align=1 + (local.get $src) + ) + ) + (memory.copy + (local.get $dst) + (local.get $src) + (local.get $sz) + ) + (memory.copy + (i32.const 0) + (i32.const 0) + (i32.load + (i32.const 3) + ) + ) + ) +) +(module + (type $none_=>_anyref (func (result anyref))) + (func $if-arms-subtype-fold (result anyref) + (ref.null extern) + ) + (func $if-arms-subtype-nofold (result anyref) + (if (result anyref) + (i32.const 0) + (ref.null extern) + (ref.null func) + ) + ) +) +(module + (type $i32_i32_i32_f64_=>_none (func (param i32 i32 i32 f64))) + (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) + (drop + (i32.extend8_s + (local.get $x) + ) + ) + (drop + (i32.extend16_s + (local.get $x) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (func $test + (if + (try (result i32) + (do + (i32.const 123) + ) + (catch + (drop + (pop exnref) + ) + (i32.const 456) + ) + ) + (nop) + ) + ) +) +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) + (func $call_from-param (param $f (ref null $i32_=>_i32)) (result i32) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/optimize-instructions_all-features.wast binaryen-99/test/passes/optimize-instructions_all-features.wast --- binaryen-108/test/passes/optimize-instructions_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/optimize-instructions_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,6187 @@ +(module + (memory 0) + (type $0 (func (param i32 i64))) + (func $f (type $0) (param $i1 i32) (param $i2 i64) + (drop + (i32.and + (i32.and + (local.get $i1) + (i32.const 5) + ) + (i32.const 3) + ) + ) + (drop + (i32.or + (i32.or + (local.get $i1) + (i32.const 1) + ) + (i32.const 2) + ) + ) + (drop + (i32.xor + (i32.xor + (local.get $i1) + (i32.const -2) + ) + (i32.const -5) + ) + ) + (drop + (i32.mul + (i32.mul + (local.get $i1) + (i32.const -2) + ) + (i32.const 5) + ) + ) + ;; overflow also valid + (drop + (i32.mul + (i32.mul + (local.get $i1) + (i32.const 0xfffff) + ) + (i32.const 0x8000001) + ) + ) + (if + (i32.eqz + (local.get $i1) + ) + (drop + (i32.const 10) + ) + ) + (if + (i32.eqz + (local.get $i1) + ) + (drop + (i32.const 11) + ) + (drop + (i32.const 12) + ) + ) + (if + (i64.eqz + (local.get $i2) + ) + (drop + (i32.const 11) + ) + (drop + (i32.const 12) + ) + ) + (drop + (i32.eqz + (i32.gt_s + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.ge_s + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.lt_s + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.le_s + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.gt_u + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.ge_u + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.lt_u + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (i32.le_u + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.gt + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.ge + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.lt + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.le + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.gt + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.ge + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.lt + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.le + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.eq + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f32.ne + (f32.const 1) + (f32.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.eq + (f64.const 1) + (f64.const 2) + ) + ) + ) + (drop + (i32.eqz + (f64.ne + (f64.const 1) + (f64.const 2) + ) + ) + ) + ;; we handle only 0 in the right position, as we assume a const is there, and don't care about if + ;; both are consts here (precompute does that, so no need) + (drop + (i32.eq + (i32.const 100) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.const 0) + (i32.const 100) + ) + ) + (drop + (i32.eq + (i32.const 0) + (i32.const 0) + ) + ) + (drop + (i64.eq + (i64.const 100) + (i64.const 0) + ) + ) + (drop + (i64.eq + (i64.const 0) + (i64.const 100) + ) + ) + (drop + (i64.eq + (i64.const 0) + (i64.const 0) + ) + ) + (if + (i32.eqz + (i32.eqz + (i32.const 123) + ) + ) + (nop) + ) + (drop + (select + (i32.const 101) + (i32.const 102) + (i32.eqz + (local.get $i1) + ) + ) + ) + (drop + (select + (local.tee $i1 + (i32.const 103) + ) ;; these conflict + (local.tee $i1 + (i32.const 104) + ) + (i32.eqz + (local.get $i1) + ) + ) + ) + (drop + (select + (i32.const 0) + (i32.const 1) + (i32.eqz + (i32.eqz + (i32.const 2) + ) + ) + ) + ) + ) + (func $load-store + (drop (i32.and (i32.load8_s (i32.const 0)) (i32.const 255))) + (drop (i32.and (i32.load8_u (i32.const 1)) (i32.const 255))) + (drop (i32.and (i32.load8_s (i32.const 2)) (i32.const 254))) + (drop (i32.and (i32.load8_u (i32.const 3)) (i32.const 1))) + (drop (i32.and (i32.load16_s (i32.const 4)) (i32.const 65535))) + (drop (i32.and (i32.load16_u (i32.const 5)) (i32.const 65535))) + (drop (i32.and (i32.load16_s (i32.const 6)) (i32.const 65534))) + (drop (i32.and (i32.load16_u (i32.const 7)) (i32.const 1))) + ;; + (i32.store8 (i32.const 8) (i32.and (i32.const -1) (i32.const 255))) + (i32.store8 (i32.const 9) (i32.and (i32.const -2) (i32.const 254))) + (i32.store16 (i32.const 10) (i32.and (i32.const -3) (i32.const 65535))) + (i32.store16 (i32.const 11) (i32.and (i32.const -4) (i32.const 65534))) + ;; + (i32.store8 (i32.const 11) (i32.wrap_i64 (i64.const 1))) + (i32.store16 (i32.const 11) (i32.wrap_i64 (i64.const 2))) + (i32.store (i32.const 11) (i32.wrap_i64 (i64.const 3))) + ;; + (i32.store8 (i32.const 7) (i32.const -1)) ;; 255 + (i32.store8 (i32.const 8) (i32.const 255)) + (i32.store8 (i32.const 9) (i32.const 256)) ;; 0 + (i32.store16 (i32.const 10) (i32.const 65535)) + (i32.store16 (i32.const 11) (i32.const 65536)) ;; 0 + (i32.store16 (i32.const 13) (i32.const -1)) ;; 65535 + (i32.store (i32.const 14) (i32.const 65536)) + ;; + (i64.store8 (i32.const 8) (i64.const 255)) + (i64.store8 (i32.const 9) (i64.const 256)) ;; 0 + (i64.store16 (i32.const 10) (i64.const 65535)) + (i64.store16 (i32.const 11) (i64.const 65536)) ;; 0 + (i64.store32 (i32.const 12) (i64.const 4294967295)) + (i64.store32 (i32.const 13) (i64.const 4294967296)) ;; 0 + (i64.store (i32.const 14) (i64.const 4294967296)) + ) + (func $and-neg1 + (drop (i32.and (i32.const 100) (i32.const -1))) + (drop (i32.and (i32.const 100) (i32.const 1))) + ) + (func $and-pos1 + (drop (i32.and (i32.eqz (i32.const 1000)) (i32.const 1))) + (drop (i32.and (i32.const 1) (i32.eqz (i32.const 1000)))) + (drop (i32.and (i32.const 100) (i32.const 1))) + (drop (i32.and (i32.lt_s (i32.const 2000) (i32.const 3000)) (i32.const 1))) + ) + (func $canonicalize (param $x i32) (param $y i32) (param $fx f64) (param $fy f64) + (drop (i32.and (unreachable) (i32.const 1))) ;; ok to reorder + (drop (i32.and (i32.const 1) (unreachable))) + (drop (i32.div_s (unreachable) (i32.const 1))) ;; not ok + (drop (i32.div_s (i32.const 1) (unreachable))) + ;; the various orderings + (drop (i32.and (i32.const 1) (i32.const 2))) + (drop (i32.and (local.get $x) (i32.const 3))) + (drop (i32.and (i32.const 4) (local.get $x))) + (drop (i32.and (local.get $x) (local.get $y))) + (drop (i32.and (local.get $y) (local.get $x))) + (drop (i32.and (local.get $y) (local.tee $x (i32.const -4)))) + (drop (i32.and + (block (result i32) + (i32.const -5) + ) + (local.get $x) + )) + (drop (i32.and + (local.get $x) + (block (result i32) + (i32.const -6) + ) + )) + (drop (i32.and + (block (result i32) + (i32.const 5) + ) + (loop (result i32) + (i32.const 6) + ) + )) + (drop (i32.and + (loop (result i32) + (i32.const 7) + ) + (block (result i32) + (i32.const 8) + ) + )) + (drop (i32.and + (loop (result i32) + (call $and-pos1) + (i32.const 9) + ) + (block (result i32) + (i32.const 10) + ) + )) + (drop (i32.and + (loop (result i32) + (i32.const 11) + ) + (block (result i32) + (call $and-pos1) + (i32.const 12) + ) + )) + (drop (i32.and + (loop (result i32) + (call $and-pos1) + (i32.const 13) + ) + (block (result i32) + (call $and-pos1) + (i32.const 14) + ) + )) + (drop (i32.and + (block (result i32) + (call $and-pos1) + (i32.const 14) + ) + (loop (result i32) + (call $and-pos1) + (i32.const 13) + ) + )) + (drop (i32.and + (block (result i32) + (i32.const 15) + ) + (local.get $x) + )) + (drop (i32.and + (local.get $x) + (block (result i32) + (i32.const 15) + ) + )) + (drop (i32.and + (i32.gt_s + (i32.const 16) + (i32.const 17) + ) + (i32.gt_u + (i32.const 18) + (i32.const 19) + ) + )) + (drop (i32.and + (i32.gt_u + (i32.const 20) + (i32.const 21) + ) + (i32.gt_s + (i32.const 22) + (i32.const 23) + ) + )) + (drop (i32.gt_s + (i32.const 1) + (local.get $x) + )) + (drop (i32.gt_u + (i32.const 0) + (local.get $x) + )) + (drop (i32.ne + (i32.const -1) + (local.get $x) + )) + (drop (f64.ne + (f64.const -1) + (local.get $fx) + )) + (drop (f64.lt + (f64.const -2) + (local.get $fx) + )) + (drop (f64.ge + (f64.const inf) + (local.get $fx) + )) + (drop (f64.le + (f64.const nan) + (local.get $fx) + )) + ;; skip + (drop (f64.ge + (f64.const 1) + (f64.const 2) + )) + (drop (i32.add (i32.ctz (local.get $x)) (i32.ctz (local.get $y)))) + (drop (i32.add (i32.ctz (local.get $y)) (i32.ctz (local.get $x)))) + (drop (i32.add (i32.ctz (local.get $x)) (i32.eqz (local.get $y)))) + (drop (i32.add (i32.eqz (local.get $x)) (i32.ctz (local.get $y)))) + ) + (func $ne0 (result i32) + (if (i32.ne (call $ne0) (i32.const 0)) + (nop) + ) + (if (i32.ne (i32.const 0) (call $ne0)) + (nop) + ) + ;; through an or + (if + (i32.or + (i32.ne (i32.const 0) (call $ne0)) + (i32.ne (i32.const 0) (call $ne0)) + ) + (nop) + ) + ;; but not an and + (if + (i32.and + (i32.ne (i32.const 0) (call $ne0)) + (i32.ne (i32.const 0) (call $ne0)) + ) + (nop) + ) + (i32.const 1) + ) + (func $recurse-bool + (if + (if (result i32) + (i32.const 1) + (i32.ne (call $ne0) (i32.const 0)) + (i32.ne (call $ne1) (i32.const 0)) + ) + (nop) + ) + (if + (block (result i32) + (nop) + (i32.ne (call $ne0) (i32.const 0)) + ) + (nop) + ) + ) + (func $ne1 (result i32) + (unreachable) + ) + (func $load-off-2 "load-off-2" (param $0 i32) (result i32) + (i32.store offset=2 + (i32.add + (i32.const 1) + (i32.const 3) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (i32.const 3) + (i32.const 1) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (i32.const 7) + (local.get $0) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (i32.const -11) ;; do not fold this! + (local.get $0) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (local.get $0) + (i32.const -13) ;; do not fold this! + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (i32.const -15) + (i32.const 17) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.add + (i32.const -21) + (i32.const 19) + ) + (local.get $0) + ) + (i32.store offset=2 + (i32.const 23) + (local.get $0) + ) + (i32.store offset=2 + (i32.const -25) + (local.get $0) + ) + (drop + (i32.load offset=2 + (i32.add + (i32.const 2) + (i32.const 4) + ) + ) + ) + (drop + (i32.load offset=2 + (i32.add + (i32.const 4) + (i32.const 2) + ) + ) + ) + (drop + (i32.load offset=2 + (i32.add + (local.get $0) + (i32.const 6) + ) + ) + ) + (drop + (i32.load offset=2 + (i32.const 8) + ) + ) + (i32.load offset=2 + (i32.add + (i32.const 10) + (local.get $0) + ) + ) + ) + (func $sign-ext (param $0 i32) (param $1 i32) + ;; eq of sign-ext to const, can be a zext + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 5) ;; weird size, but still valid + ) + (i32.const 5) + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 100) ;; non-zero + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 32767) ;; non-zero and bigger than the mask, with sign bit + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const -149) ;; non-zero and bigger than the mask, without sign bit + ) + ) + ;; eq of two sign-ext, can both be a zext + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + ;; corner cases we should not opt + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 23) ;; different shift, smaller + ) + (i32.const 0) + ) + ) + (drop + (i32.eq + (i32.shr_u ;; unsigned + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 0) + ) + ) + (drop + (i32.lt_s ;; non-eq + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 0) + ) + ) + (drop + (if (result i32) + (i32.shr_s + (i32.shl + (unreachable) ;; ignore an unreachable value + (i32.const 16) + ) + (i32.const 16) + ) + (i32.const 111) + (i32.const 222) + ) + ) + ) + (func $sign-ext-input (param $0 i32) (param $1 i32) + (drop + (i32.shr_s + (i32.shl + (i32.const 100) ;; small! + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const 127) ;; just small enough + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const 128) ;; just too big + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) ;; who knows... + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (unreachable) ;; ignore + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.div_s ;; this could be optimizable in theory, but currently we don't look into adds etc. + (i32.const 1) + (i32.const 2) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.and ;; takes the min, here it is ok + (i32.const 127) + (i32.const 128) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.and ;; takes the min, here it is not + (i32.const 128) + (i32.const 129) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.xor ;; takes the max, here it is ok + (i32.const 127) + (i32.const 126) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.xor ;; takes the max, here it is not + (i32.const 127) + (i32.const 128) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.or ;; takes the max, here it is ok + (i32.const 127) + (i32.const 126) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.or ;; takes the max, here it is not + (i32.const 127) + (i32.const 128) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl ;; adds, here it is too much + (i32.const 32) + (i32.const 2) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl ;; adds, here it is ok + (i32.const 32) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl ;; adds, here it is too much and "overflows" + (i32.const 32) + (i32.const 35) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u ;; subtracts, here it is still too much + (i32.const 256) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u ;; subtracts, here it is ok + (i32.const 256) + (i32.const 2) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u ;; subtracts, here it "overflows" + (i32.const 128) + (i32.const 35) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_s ;; subtracts, here it is still too much + (i32.const 256) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_s ;; subtracts, here it is ok + (i32.const 256) + (i32.const 2) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_s ;; subtracts, here it "overflows" + (i32.const 128) + (i32.const 35) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_s ;; subtracts, here there is a sign bit, so it stays 32 bits no matter how much we shift + (i32.const -1) + (i32.const 32) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_s ;; subtracts, here we mask out that sign bit + (i32.and + (i32.const -1) + (i32.const 2147483647) + ) + (i32.const 31) ;; adjusted after we fixed shift computation to just look at lower 5 bits + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.ne ;; 1 bit + (i32.const -1) + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (f32.le + (f32.const -1) + (f32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.clz ;; assumed 5 bits + (i32.const 0) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl + (i32.clz ;; assumed 5 bits + (i32.const 0) + ) + (i32.const 2) ;; + 2, so 7 + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl + (i32.clz ;; assumed 5 bits + (i32.const 0) + ) + (i32.const 3) ;; + 3, so 8, too much + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.wrap_i64 ;; preserves 6 + (i64.clz ;; assumed 6 bits + (i64.const 0) + ) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl + (i32.wrap_i64 ;; preserves 6 + (i64.clz ;; assumed 6 bits + (i64.const 0) + ) + ) + (i32.const 1) ;; + 1, so 7 + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl + (i32.wrap_i64 ;; preserves 6 + (i64.clz ;; assumed 6 bits + (i64.const 0) + ) + ) + (i32.const 2) ;; + 2, so 8, too much + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.eqz ;; 1 bit + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.wrap_i64 ;; down to 32 + (i64.const -1) ;; 64 + ) + (i32.const 24) ;; 32 - 24 = 8 + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.wrap_i64 ;; down to 32 + (i64.const -1) ;; 64 + ) + (i32.const 25) ;; 32 - 25 = 7, ok + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.wrap_i64 ;; stay 32 + (i64.extend_i32_s + (i32.const -1) + ) + ) + (i32.const 24) ;; 32 - 24 = 8 + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.wrap_i64 ;; stay 32 + (i64.extend_i32_s + (i32.const -1) + ) + ) + (i32.const 25) ;; 32 - 25 = 7, ok + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop ;; fuzz testcase + (i32.shr_s + (i32.shl + (i32.xor ;; should be 32 bits + (i32.le_u ;; 1 bit + (local.get $0) + (i32.const 2) + ) + (local.get $0) ;; unknown, so 32 bits + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $linear-sums (param $0 i32) (param $1 i32) + (drop + (i32.add + (i32.add + (local.get $1) + (i32.const 16) + ) + (i32.shl + (i32.add + (local.get $0) + (i32.const -1) ;; -16, so cancels out! + ) + (i32.const 4) + ) + ) + ) + (drop + (i32.add + (i32.add + (local.get $1) + (i32.const 20) + ) + (i32.shl + (i32.add + (local.get $0) + (i32.const -1) ;; -8, so sum is +12 + ) + (i32.const 3) + ) + ) + ) + (drop + (i32.add ;; simple sum + (i32.const 1) + (i32.const 3) + ) + ) + (drop + (i32.add ;; nested sum + (i32.add + (i32.const 1) + (i32.const 3) + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.add + (i32.const 1) + (i32.const 3) + ) + (i32.sub ;; internal sub + (i32.const 5) + (i32.const 3) + ) + ) + ) + (drop + (i32.sub ;; external sub + (i32.add + (i32.const 1) + (i32.const 3) + ) + (i32.add + (i32.const 5) + (i32.const 3) + ) + ) + ) + (drop + (i32.sub ;; external sub + (i32.add + (i32.const 1) + (i32.const 3) + ) + (i32.sub ;; and also internal sub + (i32.const 5) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.add + (i32.const 1) + (i32.const 3) + ) + (i32.sub ;; negating sub + (i32.const 0) + (i32.const 3) + ) + ) + ) + (drop + (i32.add + (i32.sub + (i32.const 0) + (i32.sub ;; two negating subs + (i32.const 0) + (i32.add + (i32.const 3) + (i32.const 20) + ) + ) + ) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.add + (i32.add + (i32.const 0) + (i32.sub ;; one negating sub + (i32.const 0) + (i32.add + (i32.const 3) + (i32.const 20) + ) + ) + ) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (i32.add + (i32.shl ;; shifted value + (i32.const 1) + (i32.const 3) + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.shl ;; shifted value + (i32.const 1) + (local.get $0) ;; but not by const + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.shl ;; shifted nested value + (i32.sub + (local.get $1) + (i32.const 10) + ) + (i32.const 3) + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.mul ;; multiplied + (i32.const 10) + (i32.const 3) + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.mul ;; multiplied by nonconstant - can't recurse + (i32.const 10) + (local.get $0) + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.mul ;; nested mul + (i32.add + (i32.const 10) + (local.get $0) + ) + (i32.const 2) + ) + (i32.add + (i32.const 5) + (i32.const 9) + ) + ) + ) + (drop + (i32.add + (i32.add + (local.get $0) + (i32.const 10) ;; cancelled out with the below + ) + (i32.sub + (i32.const -5) + (i32.const 5) + ) + ) + ) + ) + (func $almost-sign-ext (param $0 i32) + (drop + (i32.shr_s + (i32.shl + (i32.const 100) ;; too big, there is a sign bit, due to the extra shift + (i32.const 25) + ) + (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift, in theory + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.const 50) ;; small enough, no sign bit + (i32.const 25) + ) + (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift + ) + ) + ) + (func $squaring (param $0 i32) (param $1 i32) + (drop + (i32.and + (i32.and + (local.get $0) + (i32.const 11) + ) + (i32.const 200) + ) + ) + (drop + (i32.and + (i32.and + (local.get $0) + (i32.const 11) + ) + (local.get $0) ;; non-const, cannot optimize this! + ) + ) + (drop + (i32.and + (i32.and + (i32.const 11) ;; flipped order + (local.get $0) + ) + (i32.const 200) + ) + ) + (drop + (i32.or + (i32.or + (local.get $0) + (i32.const 11) + ) + (i32.const 200) + ) + ) + (drop + (i32.shl + (i32.shl + (local.get $0) + (i32.const 11) + ) + (i32.const 200) + ) + ) + (drop + (i32.shr_s + (i32.shr_s + (local.get $0) + (i32.const 11) + ) + (i32.const 200) + ) + ) + (drop + (i32.shr_u + (i32.shr_u + (local.get $0) + (i32.const 11) + ) + (i32.const 200) + ) + ) + (drop + (i32.shr_u + (i32.shr_s ;; but do not optimize a mixture or different shifts! + (local.get $0) + (i32.const 11) + ) + (i32.const 200) + ) + ) + ) + (func $sign-ext-ne (param $0 i32) (param $1 i32) + ;; ne of sign-ext to const, can be a zext + (drop + (i32.ne + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 65000) + ) + ) + (drop + (i32.ne + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 64872) ;; no sign bit + ) + ) + (drop + (i32.ne + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const -149) ;; no sign bit, not all ones + ) + ) + (drop + (i32.ne + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 111) + ) + ) + (drop + (i32.ne + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + ) + (func $sign-ext-eqz (param $0 i32) (param $1 i32) + (drop + (i32.eqz + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + ) + (func $sign-ext-boolean (param $0 i32) (param $1 i32) + (drop + (if (result i32) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 100) + (i32.const 200) + ) + ) + ) + (func $add-sub-zero (param $0 i32) (param $1 i64) + (drop + (i32.add + (local.get $0) + (i32.const 0) + ) + ) + (drop + (i32.sub + (local.get $0) + (i32.const 0) + ) + ) + (drop + (i64.add + (local.get $1) + (i64.const 0) + ) + ) + (drop + (i64.sub + (local.get $1) + (i64.const 0) + ) + ) + ) + (func $store-signext (param $0 i32) + (i32.store8 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) ;; exact size we store, sign-ext of 8 bits + ) + (i32.const 24) + ) + ) + (i32.store8 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 25) ;; 7 bits. so the ext can alter a bit we store, do not optimize + ) + (i32.const 25) + ) + ) + (i32.store8 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 23) ;; 9 bits, this is good to optimize + ) + (i32.const 23) + ) + ) + (i32.store16 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) ;; exact size we store, sign-ext of 16 bits + ) + (i32.const 16) + ) + ) + (i32.store16 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 17) ;; 15 bits. so the ext can alter a bit we store, do not optimize + ) + (i32.const 17) + ) + ) + (i32.store16 + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 14) ;; 17 bits, this is good to optimize + ) + (i32.const 14) + ) + ) + (i32.store + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 16) ;; 4 bytes stored, do nothing + ) + (i32.const 16) + ) + ) + (i32.store + (i32.const 8) + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 8) ;; 4 bytes stored, do nothing + ) + (i32.const 8) + ) + ) + ) + (func $sign-ext-tee (param $0 i32) (param $1 i32) + (drop + (i32.shr_s + (i32.shl + (local.tee $0 + (i32.const 128) ;; too big + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.tee $0 + (i32.const 127) ;; just right + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $sign-ext-load (param $0 i32) (param $1 i32) + (drop + (i32.shr_s + (i32.shl + (i32.load8_s ;; one byte, so perfect + (i32.const 256) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.load8_s ;; one byte, but sexted to 32 + (i32.const 256) + ) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shr_u + (i32.load8_u ;; one byte, but reduced to 7 + (i32.const 256) + ) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.load16_s ;; two, so perfect + (i32.const 256) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ;; through tees, we cannot alter the load sign + (drop + (i32.shr_s + (i32.shl + (local.tee $1 + (i32.load8_s + (i32.const 1) + ) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.tee $1 + (i32.load8_u + (i32.const 1) + ) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.and + (local.tee $1 + (i32.load8_s + (i32.const 1) + ) + ) + (i32.const 255) + ) + ) + (drop + (i32.and + (local.tee $1 + (i32.load8_u + (i32.const 1) + ) + ) + (i32.const 255) + ) + ) + ) + (func $mask-bits (param $0 i32) (param $1 i32) + (drop + (i32.and + (local.tee $0 + (i32.const 127) ;; 7 bits + ) + (i32.const 255) ;; mask 8, so we don't need this + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) ;; 8 bits + ) + (i32.const 255) ;; mask 8, so we don't need this + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 254) ;; improper mask, small + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 1279) ;; improper mask, large + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 1290) ;; improper mask, large + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 4095) ;; proper mask, huge + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 511) ;; proper mask, large + ) + ) + (drop + (i32.and + (local.tee $0 + (i32.const 128) + ) + (i32.const 127) ;; proper mask, just too small + ) + ) + ) + (func $local-info-zero-ext (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.const 212) ;; mask is unneeded, we are small + ) + (drop + (i32.and + (local.get $x) + (i32.const 255) + ) + ) + (local.set $y + (i32.const 500) ;; mask is needed, we are too big + ) + (drop + (i32.and + (local.get $y) + (i32.const 255) + ) + ) + (local.set $0 + (i32.const 212) ;; mask is unneeded, but we are a param, not a var, so no + ) + (drop + (i32.and + (local.get $0) + (i32.const 255) + ) + ) + (local.set $z + (i32.const 212) ;; mask is unneeded, we are small + ) + (local.set $z + (i32.const 220) ;; mask is still unneeded even with 2 uses + ) + (drop + (i32.and + (local.get $z) + (i32.const 255) + ) + ) + (local.set $w + (i32.const 212) ;; mask is unneeded, we are small + ) + (local.set $w + (i32.const 1000) ;; mask is needed, one use is too big + ) + (drop + (i32.and + (local.get $w) + (i32.const 255) + ) + ) + ) + (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.const 127) ;; mask is unneeded, we are small + ) + (drop + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $y + (i32.const 128) ;; mask is needed, we are too big + ) + (drop + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $0 + (i32.const 127) ;; mask is unneeded, but we are a param, not a var, so no + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.const 127) ;; mask is unneeded, we are small + ) + (local.set $z + (i32.const 100) ;; mask is still unneeded even with 2 uses + ) + (drop + (i32.shr_s + (i32.shl + (local.get $z) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $w + (i32.const 127) ;; mask is unneeded, we are small + ) + (local.set $w + (i32.const 150) ;; mask is needed, one use is too big + ) + (drop + (i32.shr_s + (i32.shl + (local.get $w) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.shr_s + (i32.shl + (local.get $0) ;; already sign-exted here, so no need later + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $y + (i32.shr_s + (i32.shl + (local.get $0) ;; already sign-exted here, but wrong bit size + (i32.const 16) + ) + (i32.const 16) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $0 + (i32.shr_s + (i32.shl + (local.get $0) ;; already sign-exted here, so no need later, but we are a param + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $0) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.shr_s + (i32.shl + (local.get $0) ;; already sign-exted here, so no need later + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.shr_s + (i32.shl + (local.get $1) ;; already sign-exted here, so no need later + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $z) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $w + (i32.shr_s + (i32.shl + (local.get $0) ;; already sign-exted here, so no need later + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $w + (i32.shr_s + (i32.shl + (local.get $0) ;; not quite a sign-ext + (i32.const 23) + ) + (i32.const 24) + ) + ) + (drop + (i32.shr_s + (i32.shl + (local.get $w) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (drop ;; odd corner case + (i32.shr_s + (i32.shl + (local.get $0) ;; param, so we should know nothing + (i32.const 24) + ) + (i32.const 23) ;; different shift, smaller + ) + ) + ) + (func $signed-loads-fill-the-bits (param $$e i32) (result i32) + (local $$0 i32) + (local $$conv i32) + (local.set $$0 + (i32.load8_s ;; one byte, but 32 bits due to sign-extend + (i32.const 1024) + ) + ) + (local.set $$conv + (i32.and + (local.get $$0) + (i32.const 255) ;; so we need this zexting! + ) + ) + (return + (i32.eq + (local.get $$conv) + (local.get $$e) + ) + ) + ) + (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32) + (local $x i32) + (local $y i32) + (local $z i32) + (local $w i32) + (local.set $x + (i32.load8_s (i32.const 1024)) ;; 8 bits, sign extended, no need to do it again + ) + (drop + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $y + (i32.load8_u (i32.const 1024)) ;; 8 bits, zext, so bad + ) + (drop + (i32.shr_s + (i32.shl + (local.get $y) + (i32.const 24) + ) + (i32.const 24) + ) + ) + (local.set $z + (i32.load16_s (i32.const 1024)) ;; 16 bits sign-extended, wrong size + ) + (drop + (i32.shr_s + (i32.shl + (local.get $z) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32) + (drop + (i32.eq + (i32.load8_s + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.load8_s + (local.get $0) ;; flip order, we should canonicalize + ) + ) + ) + (drop + (i32.eq + (i32.load8_u ;; unsigned, bad + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (drop + (i32.eq + (i32.load8_s + (local.get $0) + ) + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) ;; wrong size + ) + (i32.const 16) + ) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.load8_u ;; unsigned, bad + (local.get $0) + ) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $1) + (i32.const 16) ;; wrong size + ) + (i32.const 16) + ) + (i32.load8_s + (local.get $0) + ) + ) + ) + ) + (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (call $unsign-diff-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) + (i32.ne + (i32.shr_s + (i32.shl + (call $unsign-same-sizes + (i32.const -1) + (i32.const 5) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.shr_s + (i32.shl + (call $unsign-same-sizes + (i32.const 1) + (i32.const 2006) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) + (func $fuzz-almost-sign-ext + (drop + (i32.shr_s + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 17) + ) + (i32.const 16) + ) + ) + (drop + (i32.shr_s + (i32.shl + (i32.shl + (i32.load16_u + (i32.const 2278) + ) + (i32.const 1) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + (func $fuzz-comp-impossible (param $x i32) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 16) + ) + (i32.const 16) + ) + (i32.const 65535) ;; impossible to be equal, the effective sign bit is set, but not the higher bits, which the sign-ext will set on the non-const value + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 127) ;; safe + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 128) ;; unsafe again + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 4223) ;; more big bits, so sign bit though + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 4224) ;; more big bits + ) + ) + (drop + (i32.eq + (i32.shr_s + (i32.shl + (local.get $x) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const -4) ;; safe even with more big bits, as they are all 1s + ) + ) + ) + (func $if-parallel (param $0 i32) (param $1 i32) + (drop + (if (result i32) + (local.get $0) + (i32.add (local.get $1) (i32.const 1)) + (i32.add (local.get $1) (i32.const 1)) + ) + ) + (drop + (if (result i32) + (local.tee $0 (local.get $1)) ;; side effects! + (i32.add (local.get $1) (i32.const 1)) + (i32.add (local.get $1) (i32.const 1)) + ) + ) + (drop + (if (result i32) + (local.get $0) + (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if + (i32.add (local.get $1) (unreachable)) + ) + ) + (drop + (if (result i32) + (local.tee $0 (local.get $1)) ;; side effects! + (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if + (i32.add (local.get $1) (unreachable)) + ) + ) + (drop + (if (result i32) + (unreachable) ;; !!! + (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if + (i32.add (local.get $1) (unreachable)) + ) + ) + ) + (func $select-parallel (param $0 i32) (param $1 i32) + (drop + (select + (i32.add (local.get $1) (i32.const 1)) + (i32.add (local.get $1) (i32.const 1)) + (local.get $0) + ) + ) + (drop + (select + (local.tee $0 (local.get $1)) ;; side effects! + (local.tee $0 (local.get $1)) ;; side effects! + (local.get $0) + ) + ) + (drop + (select + (i32.add (local.get $1) (i32.const 1)) + (i32.add (local.get $1) (i32.const 1)) + (local.tee $0 (local.get $1)) ;; side effects! (but no interference with values) + ) + ) + (drop + (select + (local.tee $0 (local.get $1)) ;; side effects! interference! + (local.tee $0 (local.get $1)) ;; side effects! interference! + (local.tee $0 (local.get $1)) ;; side effects! interference! + ) + ) + (drop + (select + (local.tee $0 (local.get $1)) ;; side effects! + (local.tee $0 (local.get $1)) ;; side effects! + (unreachable) ;; side effects! (but no interference with values) + ) + ) + ) + (func $zero-shifts-is-not-sign-ext + (drop + (i32.eq + (i32.const -5431187) + (i32.add + (i32.const 0) + (i32.shr_s + (i32.shl + (i32.load16_s align=1 + (i32.const 790656516) + ) + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + ) + (drop + (i32.eq + (i32.const -5431187) + (i32.add + (i32.const 0) + (i32.shr_s + (i32.shl + (i32.load16_s align=1 + (i32.const 790656516) + ) + (i32.const 1) + ) + (i32.const 0) + ) + ) + ) + ) + ) + (func $zero-ops (result i32) + (return + (i32.eq + (i32.const -1337) + (i32.shr_u + (i32.add + (i32.const 0) + (i32.shr_s + (i32.shl + (i32.load16_s align=1 + (i32.const 790656516) + ) + (i32.const 0) + ) + (i32.const 0) + ) + ) + (i32.const 0) + ) + ) + ) + ) + (func $zero-ops-64 (result i32) + (return + (i64.eq + (i64.const -1337) + (i64.shr_u + (i64.add + (i64.const 0) + (i64.shr_s + (i64.shl + (i64.load16_s align=1 + (i32.const 790656516) + ) + (i64.const 0) + ) + (i64.const 0) + ) + ) + (i64.const 0) + ) + ) + ) + ) + (func $zero-ops-64-special (result i32) + (return + (i32.wrap_i64 + (i64.popcnt + (i64.sub + (i64.shl + (i64.const 4294783828) + (i64.const 17179869183) + ) + (i64.const -7377) + ) + ) + ) + ) + ) + (func $sign-ext-1-and-ne (result i32) + (select + (i32.ne + (i32.const 1333788672) + (i32.shr_s + (i32.shl + (call $sign-ext-1-and-ne) + (i32.const 1) + ) + (i32.const 1) + ) + ) + (i32.const 2) + (i32.const 1) + ) + ) + (func $neg-shifts-and-255 (result i32) + (i32.and + (i32.shr_u + (i32.const -99) + (i32.const -32) ;; this shift does nothing + ) + (i32.const 255) + ) + ) + (func $neg-shifts-and-255-b (result i32) + (i32.and + (i32.shl + (i32.const -2349025) + (i32.const -32) ;; this shift does nothing + ) + (i32.const 255) + ) + ) + (func $shifts-square-overflow (param $x i32) (result i32) + (i32.shr_u + (i32.shr_u + (local.get $x) + (i32.const 65535) ;; 31 bits effectively + ) + (i32.const 32767) ;; also 31 bits, so two shifts that force the value into nothing for sure + ) + ) + (func $shifts-square-no-overflow-small (param $x i32) (result i32) + (i32.shr_u + (i32.shr_u + (local.get $x) + (i32.const 1031) ;; 7 bits effectively + ) + (i32.const 4098) ;; 2 bits effectively + ) + ) + (func $shifts-square-overflow-64 (param $x i64) (result i64) + (i64.shr_u + (i64.shr_u + (local.get $x) + (i64.const 65535) ;; 63 bits effectively + ) + (i64.const 64767) ;; also 63 bits, so two shifts that force the value into nothing for sure + ) + ) + (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64) + (i64.shr_u + (i64.shr_u + (local.get $x) + (i64.const 1031) ;; 7 bits effectively + ) + (i64.const 4098) ;; 2 bits effectively + ) + ) + (func $shifts-square-unreachable (param $x i32) (result i32) + (i32.shr_u + (i32.shr_u + (unreachable) + (i32.const 1031) ;; 7 bits effectively + ) + (i32.const 4098) ;; 2 bits effectively + ) + ) + (func $mix-shifts (result i32) + (i32.shr_s + (i32.shl + (i32.const 23) + (i32.const -61) + ) + (i32.const 168) + ) + ) + (func $actually-no-shifts (result i32) + (i32.add + (i32.shl + (i32.const 23) + (i32.const 32) ;; really 0 + ) + (i32.const 10) + ) + ) + (func $less-shifts-than-it-seems (param $x i32) (result i32) + (i32.add + (i32.shl + (i32.const 200) + (i32.const 36) ;; really 4 + ) + (i32.shl + (i32.const 100) + (i32.const 4) + ) + ) + ) + (func $and-popcount32 (result i32) + (i32.and + (i32.popcnt + (i32.const -1) + ) + (i32.const 31) + ) + ) + (func $and-popcount32-big (result i32) + (i32.and + (i32.popcnt + (i32.const -1) + ) + (i32.const 63) + ) + ) + (func $and-popcount64 (result i64) ;; these are TODOs + (i64.and + (i64.popcnt + (i64.const -1) + ) + (i64.const 63) + ) + ) + (func $and-popcount64-big (result i64) + (i64.and + (i64.popcnt + (i64.const -1) + ) + (i64.const 127) + ) + ) + (func $and-popcount64-bigger (result i64) + (i64.and + (i64.popcnt + (i64.const -1) + ) + (i64.const 255) + ) + ) + (func $optimizeAddedConstants-filters-through-nonzero (result i32) + (i32.sub + (i32.add + (i32.shl + (i32.const -536870912) + (i32.wrap_i64 + (i64.const 0) + ) + ) + (i32.const -32768) + ) + (i32.const -1024) + ) + ) + (func $optimizeAddedConstants-filters-through-nonzero-b (result i32) + (i32.sub + (i32.add + (i32.shl + (i32.const -536870912) + (i32.wrap_i64 + (i64.const -1) + ) + ) + (i32.const -32768) + ) + (i32.const -1024) + ) + ) + (func $return-proper-value-from-shift-left-by-zero (result i32) + (if (result i32) + (i32.sub + (i32.add + (loop $label$0 (result i32) + (block $label$1 + (br_if $label$1 + (i32.shl + (i32.load + (i32.const 0) + ) + (i32.const -31904) ;; really 0 shifts + ) + ) + ) + (i32.const -62) + ) + (i32.const 38) + ) + (i32.const -2) + ) + (i32.const 1) + (i32.const 0) + ) + ) + (func $de-morgan-2 (param $x i32) (param $y i32) + (drop + (i32.and (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) + ) + (drop + (i32.or (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) + ) + (drop + (i32.xor (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) + ) + (drop + (i32.and (i32.eqz (local.get $x)) (local.get $y)) + ) + (drop + (i32.and (local.get $x) (i32.eqz (local.get $y))) + ) + (drop + (i32.and (i32.eqz (local.get $x)) (i32.wrap_i64 (i64.const 2))) + ) + (drop + (i32.and (i32.wrap_i64 (i64.const 1)) (i32.eqz (local.get $y))) + ) + ) + (func $subzero1 (param $0 i32) (result i32) + (i32.add + (i32.sub + (i32.const 1) + (i32.clz + (local.get $0) + ) + ) + (i32.const 31) + ) + ) + (func $subzero2 (param $0 i32) (result i32) + (i32.add + (i32.const 31) + (i32.sub + (i32.const 1) + (i32.clz + (local.get $0) + ) + ) + ) + ) + (func $subzero3 (param $0 i32) (param $1 i32) (result i32) + (i32.add + (i32.sub + (i32.const 0) + (i32.clz + (local.get $0) + ) + ) + (local.get $1) + ) + ) + (func $subzero4 (param $0 i32) (param $1 i32) (result i32) + (i32.add + (local.get $0) + (i32.sub + (i32.const 0) + (i32.clz + (local.get $1) + ) + ) + ) + ) + (func $mul-32-power-2 (param $x i32) (result i32) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 4) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 5) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 1) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (call $mul-32-power-2 (i32.const 123)) ;; side effects + (i32.const 0) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 0xffffffff) + ) + ) + ) + (drop + (call $mul-32-power-2 + (i32.mul + (local.get $x) + (i32.const 0x80000000) + ) + ) + ) + (unreachable) + ) + (func $mul-64-power-2 (param $x i64) (result i64) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 4) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 5) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 1) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 0) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (call $mul-64-power-2 (i64.const 123)) ;; side effects + (i64.const 0) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 0xffffffffffffffff) + ) + ) + ) + (drop + (call $mul-64-power-2 + (i64.mul + (local.get $x) + (i64.const 0x8000000000000000) + ) + ) + ) + (unreachable) + ) + (func $div-32-power-2 (param $x i32) (result i32) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 4) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 5) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 1) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (call $div-32-power-2 (i32.const 123)) ;; side effects + (i32.const 0) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 0xffffffff) + ) + ) + ) + (drop + (call $div-32-power-2 + (i32.div_u + (local.get $x) + (i32.const 0x80000000) + ) + ) + ) + (unreachable) + ) + (func $urem-32-power-2 (param $x i32) (result i32) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 4) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 5) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 1) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 0xffffffff) + ) + ) + ) + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 0x80000000) + ) + ) + ) + ;; (unsigned)x % 1 + (drop + (call $urem-32-power-2 + (i32.rem_u + (local.get $x) + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (func $fdiv-32-power-2 (param $x f32) + (drop (f32.div + (local.get $x) + (f32.const 2) + )) + (drop (f32.div + (local.get $x) + (f32.const -2) + )) + (drop (f32.div + (local.get $x) + (f32.const 4294967296) + )) + (drop (f32.div + (local.get $x) + (f32.const 18446744073709551616) + )) + (drop (f32.div + (local.get $x) + (f32.const 0x1p-126) + )) + (drop (f32.div + (local.get $x) + (f32.const 0x1p+126) + )) + (drop (f32.div + (local.get $x) + (f32.const -0x1p-126) + )) + (drop (f32.div + (local.get $x) + (f32.const -0x1p+126) + )) + (drop (f32.div + (local.get $x) + (f32.const 0x1p-127) ;; skip + )) + (drop (f32.div + (local.get $x) + (f32.const 0x1p-127) ;; skip + )) + (drop (f32.div + (local.get $x) + (f32.const 0) ;; skip + )) + (drop (f32.div + (local.get $x) + (f32.const nan) ;; skip + )) + (drop (f32.div + (local.get $x) + (f32.const inf) ;; skip + )) + (drop (f32.div + (local.get $x) + (f32.const -inf) ;; skip + )) + ) + (func $fdiv-64-power-2 (param $x f64) + (drop (f64.div + (local.get $x) + (f64.const 2) + )) + (drop (f64.div + (local.get $x) + (f64.const -2) + )) + (drop (f64.div + (local.get $x) + (f64.const 4294967296) + )) + (drop (f64.div + (local.get $x) + (f64.const 18446744073709551616) + )) + (drop (f64.div + (local.get $x) + (f64.const 0x1p-1022) + )) + (drop (f64.div + (local.get $x) + (f64.const 0x1p+1022) + )) + (drop (f64.div + (local.get $x) + (f64.const -0x1p-1022) + )) + (drop (f64.div + (local.get $x) + (f64.const -0x1p+1022) + )) + (drop (f64.div + (local.get $x) + (f64.const 0x1p-1023) ;; skip + )) + (drop (f64.div + (local.get $x) + (f64.const 0x1p+1023) ;; skip + )) + (drop (f64.div + (local.get $x) + (f64.const 0) ;; skip + )) + (drop (f64.div + (local.get $x) + (f64.const nan) ;; skip + )) + (drop (f64.div + (local.get $x) + (f64.const inf) ;; skip + )) + (drop (f64.div + (local.get $x) + (f64.const -inf) ;; skip + )) + ) + (func $srem-by-const (param $x i32) (param $y i64) + ;; (signed)x % 1 + (drop (i32.rem_s + (local.get $x) + (i32.const 1) + )) + (drop (i64.rem_s + (local.get $y) + (i64.const 1) + )) + ;; (signed)x % 0x80000000 -> x & 0x7FFFFFFF + (drop (i32.rem_s + (local.get $x) + (i32.const 0x80000000) + )) + ;; (signed)x % 0x8000000000000000 -> x & 0x7FFFFFFFFFFFFFFF + (drop (i64.rem_s + (local.get $y) + (i64.const 0x8000000000000000) + )) + ) + (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) + ;; eqz((signed)x % 4) + (drop (i32.eqz + (i32.rem_s + (local.get $x) + (i32.const 4) + ) + )) + (drop (i64.eqz + (i64.rem_s + (local.get $y) + (i64.const 4) + ) + )) + ;; eqz((signed)x % -4) + (drop (i32.eqz + (i32.rem_s + (local.get $x) + (i32.const -4) + ) + )) + (drop (i64.eqz + (i64.rem_s + (local.get $y) + (i64.const -4) + ) + )) + ;; (signed)x % 4 == 0 + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const 4) + ) + (i32.const 0) + )) + (drop (i64.eq + (i64.rem_s + (local.get $y) + (i64.const 2) + ) + (i64.const 0) + )) + ;; (signed)x % -4 == 0 + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const -4) + ) + (i32.const 0) + )) + (drop (i64.eq + (i64.rem_s + (local.get $y) + (i64.const -4) + ) + (i64.const 0) + )) + ;; (signed)x % 2 != 0 + (drop (i32.ne + (i32.rem_s + (local.get $x) + (i32.const 2) + ) + (i32.const 0) + )) + (drop (i64.ne + (i64.rem_s + (local.get $y) + (i64.const 2) + ) + (i64.const 0) + )) + ;; (signed)x % -1 == 0 -> 0 == 0 + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const -1) + ) + (i32.const 0) + )) + ;; (signed)x % 0x80000000 == 0 + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 0) + )) + ;; (signed)x % 0x80000000 != 0 + (drop (i32.ne + (i32.rem_s + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 0) + )) + ;; (signed)x % 0x8000000000000000 == 0 + (drop (i64.eq + (i64.rem_s + (local.get $y) + (i64.const 0x8000000000000000) + ) + (i64.const 0) + )) + ;; (signed)x % 0x8000000000000000 != 0 + (drop (i64.ne + (i64.rem_s + (local.get $y) + (i64.const 0x8000000000000000) + ) + (i64.const 0) + )) + ;; + (drop (i32.eq + (i32.rem_s + (local.get $x) + (i32.const 3) ;; skip + ) + (i32.const 0) + )) + (drop (i64.eq + (i64.rem_s + (local.get $y) + (i64.const 3) ;; skip + ) + (i64.const 0) + )) + ) + (func $orZero (param $0 i32) (result i32) + (i32.or + (local.get $0) + (i32.const 0) + ) + ) + (func $andZero (param $0 i32) (result i32) + (drop + (i32.and + (local.get $0) + (i32.const 0) + ) + ) + (drop + (i32.and + (call $andZero (i32.const 1234)) ;; side effects + (i32.const 0) + ) + ) + (unreachable) + ) + (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64) + (drop + (i32.or + (i32.const 0) + (local.get $x32) + ) + ) + (drop + (i32.shl + (local.get $x32) + (i32.const 0) + ) + ) + (drop + (i32.shr_u + (local.get $x32) + (i32.const 0) + ) + ) + (drop + (i32.shr_s + (local.get $x32) + (i32.const 0) + ) + ) + (drop + (i64.or + (i64.const 0) + (local.get $x64) + ) + ) + (drop + (i64.shl + (local.get $x64) + (i64.const 0) + ) + ) + (drop + (i64.shr_u + (local.get $x64) + (i64.const 0) + ) + ) + (drop + (i64.shr_s + (local.get $x64) + (i64.const 0) + ) + ) + (drop + (i32.mul + (local.get $x32) + (i32.const 0) + ) + ) + (drop + (i64.mul + (local.get $x64) + (i64.const 0) + ) + ) + (drop + (f32.mul + (local.get $y32) + (f32.const 0) + ) + ) + (drop + (f64.mul + (local.get $y64) + (f64.const 0) + ) + ) + (drop + (i32.mul + (local.get $x32) + (i32.const 1) + ) + ) + (drop + (i64.mul + (local.get $x64) + (i64.const 1) + ) + ) + (drop + (f32.mul + (local.get $y32) + (f32.const 1) + ) + ) + (drop + (f64.mul + (local.get $y64) + (f64.const 1) + ) + ) + (drop + (i32.and + (local.get $x32) + (i32.const 0) + ) + ) + (drop + (i64.and + (local.get $x64) + (i64.const 0) + ) + ) + (drop + (i32.and + (unreachable) + (i32.const 0) + ) + ) + (drop + (i64.and + (unreachable) + (i64.const 0) + ) + ) + (drop + (i32.div_s + (local.get $x32) + (i32.const 1) + ) + ) + (drop + (i32.div_u + (local.get $x32) + (i32.const 1) + ) + ) + (drop + (i64.div_s + (local.get $x64) + (i64.const 1) + ) + ) + (drop + (i64.div_u + (local.get $x64) + (i64.const 1) + ) + ) + (drop + (f32.div + (local.get $y32) + (f32.const 1) + ) + ) + (drop + (f64.div + (local.get $y64) + (f64.const 1) + ) + ) + (drop + (f32.div + (local.get $y32) + (f32.const 1.2) + ) + ) + (drop + (i32.mul + (local.get $x32) + (i32.const -1) + ) + ) + (drop + (i64.mul + (local.get $x64) + (i64.const -1) + ) + ) + (drop + (f32.mul + (local.get $y32) + (f32.const -1) + ) + ) + (drop + (f64.mul + (local.get $y64) + (f64.const -1) + ) + ) + (drop + (i32.eq + (i32.add + (local.get $x32) + (i32.const 10) + ) + (i32.const 20) + ) + ) + (drop + (i32.le_u + (i32.add + (local.get $x32) + (i32.const 10) + ) + (i32.const 20) + ) + ) + (drop + (i32.eq + (i32.sub + (local.get $x32) + (i32.const 10) + ) + (i32.const 20) + ) + ) + (drop + (i64.eq + (i64.add + (local.get $x64) + (i64.const 10) + ) + (i64.const 20) + ) + ) + (drop + (i32.eq + (i32.const 20) + (i32.add + (local.get $x32) + (i32.const 10) + ) + ) + ) + (drop + (i32.eq + (i32.add + (local.get $x32) + (i32.const 10) + ) + (i32.add + (local.get $x32) + (i32.const 20) + ) + ) + ) + (drop + (i32.eq + (i32.sub + (local.get $x32) + (i32.const 10) + ) + (i32.const 20) + ) + ) + (drop + (i32.eq + (i32.add + (local.get $x32) + (i32.const 10) + ) + (i32.sub + (local.get $x32) + (i32.const 20) + ) + ) + ) + (drop + (i32.eq + (i32.sub + (local.get $x32) + (i32.const 10) + ) + (i32.add + (local.get $x32) + (i32.const 20) + ) + ) + ) + (drop + (i32.eq + (i32.sub + (local.get $x32) + (i32.const 10) + ) + (i32.sub + (local.get $x32) + (i32.const 20) + ) + ) + ) + (drop + (i64.le_s + (i64.sub + (local.get $x64) + (i64.const 288230376151711744) + ) + (i64.const 9223372036854775807) + ) + ) + ) + (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32) + (drop (i32.add (local.get $x) (i32.const 0x40))) + (drop (i32.sub (local.get $x) (i32.const 0x40))) + (drop (i32.add (local.get $x) (i32.const 0x2000))) + (drop (i32.add (local.get $x) (i32.const 0x100000))) + (drop (i32.add (local.get $x) (i32.const 0x8000000))) + + (drop (i64.add (local.get $y) (i64.const 0x40))) + (drop (i64.sub (local.get $y) (i64.const 0x40))) + (drop (i64.add (local.get $y) (i64.const 0x2000))) + (drop (i64.add (local.get $y) (i64.const 0x100000))) + (drop (i64.add (local.get $y) (i64.const 0x8000000))) + + (drop (i64.add (local.get $y) (i64.const 0x400000000))) + (drop (i64.add (local.get $y) (i64.const 0x20000000000))) + (drop (i64.add (local.get $y) (i64.const 0x1000000000000))) + (drop (i64.add (local.get $y) (i64.const 0x80000000000000))) + (drop (i64.add (local.get $y) (i64.const 0x4000000000000000))) + + (drop (f32.add (local.get $z) (f32.const 0x40))) + ) + (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32) + (drop + (i32.shl + (i32.const 0) + (local.get $x) + ) + ) + (drop + (i32.shr_u + (i32.const 0) + (local.get $x) + ) + ) + (drop + (i32.shr_s + (i32.const 0) + (local.get $x) + ) + ) + (drop + (i64.shl + (i64.const 0) + (local.get $y) + ) + ) + (drop + (i32.shl + (i32.const 0) + (unreachable) + ) + ) + ) + (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32) + (drop + (i32.sub + (local.get $x) + (local.get $x) + ) + ) + (drop + (i64.sub + (local.get $y) + (local.get $y) + ) + ) + (drop + (f64.sub + (local.get $z) + (local.get $z) + ) + ) + (drop + (i32.sub + (local.get $x) + (local.get $xx) + ) + ) + (drop + (i32.sub + (unreachable) + (unreachable) + ) + ) + (drop + (i32.add + (local.get $x) + (local.get $x) + ) + ) + ;; more ops + (drop + (i32.xor + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.ne + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.lt_s + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.lt_u + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.gt_s + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.gt_u + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.and + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.or + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.eq + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.le_s + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.le_u + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.ge_s + (local.get $x) + (local.get $x) + ) + ) + (drop + (i32.ge_u + (local.get $x) + (local.get $x) + ) + ) + (drop + (i64.xor + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.ne + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.lt_s + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.lt_u + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.gt_s + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.gt_u + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.and + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.or + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.eq + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.le_s + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.le_u + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.ge_s + (local.get $y) + (local.get $y) + ) + ) + (drop + (i64.ge_u + (local.get $y) + (local.get $y) + ) + ) + ) + (func $all_ones (param $x i32) (param $y i64) + (drop + (i32.and + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i32.or + (local.get $x) + (i32.const -1) + ) + ) + (drop + (i32.or + (local.tee $x + (i32.const 1337) + ) + (i32.const -1) + ) + ) + (drop + (i64.and + (local.get $y) + (i64.const -1) + ) + ) + (drop + (i64.or + (local.get $y) + (i64.const -1) + ) + ) + ) + (func $xor (param $x i32) (param $y i64) + (drop + (i32.xor + (local.get $x) + (i32.const 0) + ) + ) + ) + (func $select-on-const (param $x i32) (param $y i64) + (drop + (select + (i32.const 2) + (local.get $x) + (i32.const 0) + ) + ) + (drop + (select + (i32.const 3) + (local.get $x) + (i32.const 1) + ) + ) + (drop + (select + (i32.const 4) + (local.tee $x + (i32.const 5) + ) + (i32.const 0) + ) + ) + (drop + (select + (local.tee $x + (i32.const 6) + ) + (i32.const 7) + (i32.const 0) + ) + ) + (drop + (select + (i32.const 4) + (local.tee $x + (i32.const 5) + ) + (i32.const 1) + ) + ) + (drop + (select + (local.tee $x + (i32.const 6) + ) + (i32.const 7) + (i32.const 1) + ) + ) + (drop + (select + (i32.const 1) + (i32.const 0) + (local.get $x) + ) + ) + (drop + (select + (i32.const 0) + (i32.const 1) + (local.get $x) + ) + ) + (drop + (select + (i32.const 0) + (i32.const 1) + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (select + (i32.const 1) + (i32.const 0) + (i32.lt_s + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (select + (i32.const 0) + (i32.const 1) + (i32.ge_s + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (select + (i32.const 1) + (i32.const 0) + (i32.gt_s + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (select + (i32.const 0) + (i32.const 1) + (i32.gt_s + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (select + (i32.const 1) + (i32.const 0) + (i32.ge_s + (local.get $x) + (i32.const 0) + ) + ) + ) + (drop + (select + (i64.const 1) + (i64.const 0) + (local.get $x) + ) + ) + (drop + (select + (i64.const 0) + (i64.const 1) + (local.get $x) + ) + ) + (drop + (select + (i64.const 1) + (i64.const 0) + (i64.eqz + (local.get $y) + ) + ) + ) + (drop + (select + (i64.const 0) + (i64.const 1) + (i64.eqz + (local.get $y) + ) + ) + ) + (drop + (select + (i64.const 0) + (i64.const 1) + (i64.lt_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (select + (i64.const 1) + (i64.const 0) + (i64.lt_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (select + (i64.const 0) + (i64.const 1) + (i64.ge_s + (local.get $y) + (i64.const 0) + ) + ) + ) + (drop + (select + (i64.const 1) + (i64.const 0) + (i64.ge_s + (local.get $y) + (i64.const 0) + ) + ) + ) + ;; optimize boolean + (drop + (select + (local.get $x) + (i32.const 0) + (i32.eqz + (i32.const 0) + ) + ) + ) + (drop + (select + (local.get $x) + (i32.const 2) + (i32.eqz + (i32.const 2) + ) + ) + ) + (drop + (select + (local.get $x) + (i32.const 2) + (i32.eqz + (i32.eqz + (local.get $x) + ) + ) + ) + ) + (drop + (select + (local.get $y) + (i64.const 0) + (i64.eqz + (i64.const 0) + ) + ) + ) + (drop + (select + (local.get $y) + (i64.const 2) + (i64.eqz + (i64.const 2) + ) + ) + ) + ) + (func $optimize-boolean (param $x i32) (param $y i64) + ;; bool(-x) -> bool(x) + (drop + (select + (i32.const 1) + (i32.const 2) + (i32.sub + (i32.const 0) + (local.get $x) + ) + ) + ) + ;; i32(bool(expr)) == 1 -> bool(expr) + (drop (i32.eq + (i32.and + (local.get $x) + (i32.const 1) + ) + (i32.const 1) + )) + ;; i32(bool(expr)) != 1 -> !bool(expr) + (drop (i32.ne + (i32.and + (local.get $x) + (i32.const 1) + ) + (i32.const 1) + )) + ;; i64(bool(expr)) != 0 -> i32(bool(expr)) + (drop (i64.ne + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + (i64.const 0) + )) + ;; eqz((i32(bool(expr)) != 0) != 0) + (drop (i32.eqz + (i32.ne + (i32.ne + (i32.shr_u + (local.get $x) + (i32.const 31) + ) + (i32.const 0) + ) + (i32.const 0) + ) + )) + ;; i32.eqz(wrap(i64(x))) + (drop (i32.eqz + (i32.wrap_i64 + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + ) + )) + ;; eqz((i64(bool(expr)) != 0) != 0) + (drop (i32.eqz + (i32.ne + (i64.ne + (i64.shr_u + (local.get $y) + (i64.const 63) + ) + (i64.const 0) + ) + (i32.const 0) + ) + )) + ;; eqz((i64(bool(expr)) != 0) != 0) + (drop (i32.eqz + (i32.ne + (i64.ne + (local.get $y) + (i64.const 0) + ) + (i32.const 0) + ) + )) + ;; i32.eqz(wrap(i64(x))) -> skip + (drop (i32.eqz + (i32.wrap_i64 + (local.get $y) + ) + )) + ;; i64(bool(expr)) == 1 -> i32(bool(expr)) + (drop (i64.eq + (i64.and + (local.get $y) + (i64.const 1) + ) + (i64.const 1) + )) + ;; i64(bool(expr)) != 1 -> !i64(bool(expr)) + (drop (i64.ne + (i64.and + (local.get $y) + (i64.const 1) + ) + (i64.const 1) + )) + ;; i32(bool(expr)) & 1 -> bool(expr) + (drop (i32.and + (i32.and + (local.get $x) + (i32.const 1) + ) + (i32.const 1) + )) + ;; i32(bool(expr)) | 1 -> 1 + (drop (i32.or + (i32.and + (local.get $x) + (i32.const 1) + ) + (i32.const 1) + )) + ;; i64(bool(expr)) & 1 -> i64(bool(expr)) + (drop (i64.and + (i64.and + (local.get $y) + (i64.const 1) + ) + (i64.const 1) + )) + ;; i64(bool(expr)) | 1 -> 1 + (drop (i64.or + (i64.and + (local.get $y) + (i64.const 1) + ) + (i64.const 1) + )) + ;; i32(bool(expr)) != 0 -> i32(bool(expr)) + (drop (i32.ne + (i32.and + (local.get $x) + (i32.const 1) + ) + (i32.const 0) + )) + ;; i32(bool(expr)) != 0 -> i32(bool(expr)) + (drop (i32.ne + (i64.ne + (local.get $y) + (i64.const 0) + ) + (i32.const 0) + )) + ;; (i32(expr) != 0) != 0 -> (expr != 0) + (drop (i32.ne + (i32.ne + (local.get $x) + (i32.const 0) + ) + (i32.const 0) + )) + ;; (signed)x % 4 ? 1 : 0 + (drop (if (result i32) + (i32.rem_s + (local.get $x) + (i32.const 4) + ) + (i32.const 1) + (i32.const 0) + )) + ;; (signed)x % min_s ? 1 : 0 + (drop (if (result i32) + (i32.rem_s + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 1) + (i32.const 0) + )) + ) + (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64) + ;; ~(1 << x) -> rotl(-2, x) + (drop (i32.xor + (i32.shl + (i32.const 1) + (local.get $x) + ) + (i32.const -1) + )) + (drop (i64.xor + (i64.shl + (i64.const 1) + (local.get $z) + ) + (i64.const -1) + )) + ) + (func $getFallthrough ;; unit tests for Properties::getFallthrough + (local $x0 i32) + (local $x1 i32) + (local $x2 i32) + (local $x3 i32) + (local $x4 i32) + (local $x5 i32) + (local $x6 i32) + (local $x7 i32) + ;; the trivial case + (local.set $x0 (i32.const 1)) + (drop (i32.and (local.get $x0) (i32.const 7))) + ;; tees + (local.set $x1 (local.tee $x2 (i32.const 1))) + (drop (i32.and (local.get $x1) (i32.const 7))) + ;; loop + (local.set $x3 (loop (result i32) (i32.const 1))) + (drop (i32.and (local.get $x3) (i32.const 7))) + ;; if - two sides, can't + (local.set $x4 (if (result i32) (i32.const 1) (i32.const 2) (i32.const 3))) + (drop (i32.and (local.get $x4) (i32.const 7))) + ;; if - one side, can + (local.set $x5 (if (result i32) (i32.const 1) (unreachable) (i32.const 3))) + (drop (i32.and (local.get $x5) (i32.const 7))) + ;; if - one side, can + (local.set $x6 (if (result i32) (i32.const 1) (i32.const 3) (unreachable))) + (drop (i32.and (local.get $x6) (i32.const 7))) + ;; br_if with value + (drop + (block $out (result i32) + (local.set $x7 (br_if $out (i32.const 1) (i32.const 1))) + (drop (i32.and (local.get $x7) (i32.const 7))) + (unreachable) + ) + ) + ) + (func $tee-with-unreachable-value (result f64) + (local $var$0 i32) + (block $label$1 (result f64) + (local.tee $var$0 + (br_if $label$1 ;; the f64 does not actually flow through this, it's unreachable (and the type is wrong - but unchecked) + (f64.const 1) + (unreachable) + ) + ) + ) + ) + (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) + (i32.add + (i32.add + (i32.sub + (i32.const 0) ;; this zero looks like we could remove it by subtracting the get of $temp from the parent, but that would reorder it *after* the tee :( + (local.get $temp) + ) + (local.tee $temp ;; cannot move this tee before the get + (i32.const 1) + ) + ) + (i32.const 2) + ) + ) + (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) + (i32.add + (i32.add + (local.tee $temp ;; in this order, the tee already comes first, so all is good for the optimization + (i32.const 1) + ) + (i32.sub + (i32.const 0) + (local.get $temp) + ) + ) + (i32.const 2) + ) + ) + (func $const-float-zero (param $fx f32) (param $fy f64) + ;; x - 0.0 ==> x + (drop (f32.sub + (local.get $fx) + (f32.const 0) + )) + (drop (f64.sub + (local.get $fy) + (f64.const 0) + )) + ;; x + (-0.0) ==> x + (drop (f32.add + (local.get $fx) + (f32.const -0) + )) + (drop (f64.add + (local.get $fy) + (f64.const -0) + )) + ;; x - (-0.0) ==> x + 0.0 + (drop (f32.sub + (local.get $fx) + (f32.const -0) ;; skip + )) + (drop (f64.sub + (local.get $fy) + (f64.const -0) ;; skip + )) + ;; 0.0 - x ==> 0.0 - x + (drop (f32.sub + (f32.const 0) + (local.get $fx) ;; skip + )) + (drop (f64.sub + (f64.const 0) + (local.get $fy) ;; skip + )) + ;; x + 0.0 ==> x + 0.0 + (drop (f32.add + (local.get $fx) ;; skip + (f32.const 0) + )) + (drop (f64.add + (local.get $fy) ;; skip + (f64.const 0) + )) + (drop (f32.sub + (f32.const -nan:0x34546d) ;; skip + (f32.const 0) + )) + ) + (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) + (drop (i32.sub + (local.get $x) + (i32.const -1) + )) + (drop (i64.sub + (local.get $y) + (i64.const -1) + )) + ;; (unsigned)x > -1 ==> 0 + (drop (i32.gt_u + (local.get $x) + (i32.const -1) + )) + (drop (i64.gt_u + (local.get $y) + (i64.const -1) + )) + (drop (i32.gt_s + (local.get $x) + (i32.const -1) + )) + (drop (i64.gt_s + (local.get $y) + (i64.const -1) + )) + (drop (i64.extend_i32_s + (i64.gt_u + (i64.const 0) + (i64.const -1) + ) + )) + ;; (unsigned)x <= -1 ==> 1 + (drop (i32.le_u + (local.get $x) + (i32.const -1) + )) + (drop (i64.le_u + (local.get $y) + (i64.const -1) + )) + (drop (i32.le_s + (local.get $x) + (i32.const -1) + )) + (drop (i64.le_s + (local.get $y) + (i64.const -1) + )) + ;; (unsigned)x >= -1 ==> x == -1 + (drop (i32.ge_u + (local.get $x) + (i32.const -1) + )) + (drop (i64.ge_u + (local.get $y) + (i64.const -1) + )) + ;; (unsigned)x < -1 ==> x != -1 + (drop (i32.lt_u + (local.get $x) + (i32.const -1) + )) + (drop (i64.lt_u + (local.get $y) + (i64.const -1) + )) + ;; x * -1 + (drop (i32.mul + (local.get $x) + (i32.const -1) + )) + (drop (i64.mul + (local.get $y) + (i64.const -1) + )) + (drop (f32.mul ;; skip + (local.get $fx) + (f32.const -1) + )) + (drop (f64.mul ;; skip + (local.get $fy) + (f64.const -1) + )) + ;; (unsigned)x / -1 + (drop (i32.div_u + (local.get $x) + (i32.const -1) + )) + (drop (i64.div_u + (local.get $y) + (i64.const -1) + )) + ) + (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) + ;; signed divs + ;; i32(x) / -2147483648 -> x == -2147483648 + (drop (i32.div_s + (local.get $x) + (i32.const -2147483648) + )) + ;; i64(x) / -9223372036854775808 -> x == -9223372036854775808 + (drop (i64.div_s + (local.get $y) + (i64.const -9223372036854775808) + )) + ;; skip + (drop (i64.div_s + (local.get $y) + (i64.const -2147483648) + )) + + ;; unsigned divs + ;; u32(x) / -2 => x >= -2 + (drop (i32.div_u + (local.get $x) + (i32.const -2) + )) + ;; u32(x) / -1 => x == -1 + (drop (i32.div_u + (local.get $x) + (i32.const -1) + )) + ;; u32(x) / (i32.min + 1) + (drop (i32.div_u + (local.get $x) + (i32.const -2147483647) + )) + ;; u32(x) / i32.min => x >>> 31 + (drop (i32.div_u + (local.get $x) + (i32.const -2147483648) + )) + ;; u64(x) / -1 => u64(x == -1) + (drop (i64.div_u + (local.get $y) + (i64.const -1) + )) + ;; u64(x) / i64.min => x >>> 63 + (drop (i64.div_u + (local.get $y) + (i64.const -9223372036854775808) + )) + + ;; (unsigned)x >= 0 => i32(1) + (drop (i32.ge_u + (local.get $x) + (i32.const 0) + )) + (drop (i64.ge_u + (local.get $y) + (i64.const 0) + )) + + ;; (unsigned)x < 0 => i32(0) + (drop (i32.lt_u + (local.get $x) + (i32.const 0) + )) + (drop (i64.lt_u + (local.get $y) + (i64.const 0) + )) + + ;; (unsigned)x > 0 => x != 0 + (drop (i32.gt_u + (local.get $x) + (i32.const 0) + )) + (drop (i64.gt_u + (local.get $y) + (i64.const 0) + )) + + ;; (unsigned)x <= 0 => x == 0 + (drop (i32.le_u + (local.get $x) + (i32.const 0) + )) + (drop (i64.le_u + (local.get $y) + (i64.const 0) + )) + + ;; i32(x) <= 0x7fffffff => i32(1) + (drop (i32.le_s + (local.get $x) + (i32.const 0x7fffffff) + )) + ;; i64(x) <= 0x7fffffffffffffff => i32(1) + (drop (i64.le_s + (local.get $y) + (i64.const 0x7fffffffffffffff) + )) + + ;; i32(x) >= 0x80000000 => i32(1) + (drop (i32.ge_s + (local.get $x) + (i32.const 0x80000000) + )) + ;; i64(x) >= 0x8000000000000000 => i32(1) + (drop (i64.ge_s + (local.get $y) + (i64.const 0x8000000000000000) + )) + + ;; i32(x) < 0x80000000 => 0 + (drop (i32.lt_s + (local.get $x) + (i32.const 0x80000000) + )) + ;; i64(x) < 0x8000000000000000 => 0 + (drop (i64.lt_s + (local.get $y) + (i64.const 0x8000000000000000) + )) + + ;; i32(x) > 0x7fffffff => 0 + (drop (i32.gt_s + (local.get $x) + (i32.const 0x7fffffff) + )) + ;; i64(x) > 0x7fffffffffffffff => 0 + (drop (i64.gt_s + (local.get $y) + (i64.const 0x7fffffffffffffff) + )) + + ;; i32(x) < 0x7fffffff => x != 0x7fffffff + (drop (i32.lt_s + (local.get $x) + (i32.const 0x7fffffff) + )) + ;; i64(x) < 0x7fffffffffffffff => x != 0x7fffffffffffffff + (drop (i64.lt_s + (local.get $y) + (i64.const 0x7fffffffffffffff) + )) + + ;; i32(x) > 0x80000000 => x != 0x80000000 + (drop (i32.gt_s + (local.get $x) + (i32.const 0x80000000) + )) + ;; i64(x) > 0x8000000000000000 => x != 0x8000000000000000 + (drop (i64.gt_s + (local.get $y) + (i64.const 0x8000000000000000) + )) + + ;; i32(x) <= 0x80000000 => x == 0x80000000 + (drop (i32.le_s + (local.get $x) + (i32.const 0x80000000) + )) + ;; i64(x) <= 0x8000000000000000 => x == 0x8000000000000000 + (drop (i64.le_s + (local.get $y) + (i64.const 0x8000000000000000) + )) + + ;; i32(x) >= 0x7fffffff => x == 0x7fffffff + (drop (i32.ge_s + (local.get $x) + (i32.const 0x7fffffff) + )) + ;; i64(x) >= 0x7fffffffffffffff => x == 0x7fffffffffffffff + (drop (i64.ge_s + (local.get $y) + (i64.const 0x7fffffffffffffff) + )) + + ;; -x * 1 => x * -1 + (drop (f32.mul + (f32.neg + (local.get $fx) + ) + (f32.const 1) + )) + ;; -x * -2.1 => x * 2.1 + (drop (f64.mul + (f64.neg + (local.get $fy) + ) + (f64.const -2.1) + )) + ;; 2 * -x => x * -2 + (drop (f64.mul + (f64.const 2) + (f64.neg + (local.get $fy) + ) + )) + ;; -x / inf => x / -inf + (drop (f32.div + (f32.neg + (local.get $fx) + ) + (f32.const inf) + )) + ;; -x / -0.0 => x / 0.0 + (drop (f64.div + (f64.neg + (local.get $fy) + ) + (f64.const -0.0) + )) + ;; -x / nan => x / -nan + (drop (f64.div + (f64.neg + (local.get $fy) + ) + (f64.const nan) + )) + ;; 5.0 / -x => -5 / x + (drop (f64.div + (f64.const 5) + (f64.neg + (local.get $fy) + ) + )) + ) + (func $lhs-is-neg-one (param $x i32) (param $y i64) + ;; -1 >> x ==> -1 + (drop (i32.shr_s + (i32.const -1) + (local.get $x) + )) + (drop (i64.shr_s + (i64.const -1) + (local.get $y) + )) + ;; rotl(-1, x) ==> -1 + (drop (i32.rotl + (i32.const -1) + (local.get $x) + )) + (drop (i64.rotl + (i64.const -1) + (local.get $y) + )) + ;; rotr(-1, x) ==> -1 + (drop (i32.rotr + (i32.const -1) + (local.get $x) + )) + (drop (i64.rotr + (i64.const -1) + (local.get $y) + )) + ;; skip + (drop (i32.shr_s + (i32.const -1) + (call $ne0) ;; side effect + )) + ;; skip + (drop (i32.shr_u + (i32.const -1) + (local.get $x) + )) + ) + (func $lhs-is-const (param $x i32) (param $y i64) + ;; 0 - (x - 1) + (drop (i32.sub + (i32.const 0) + (i32.sub + (local.get $x) + (i32.const 1) + ) + )) + (drop (i64.sub + (i64.const 0) + (i64.sub + (local.get $y) + (i64.const 1) + ) + )) + ;; -1 - (x + 1) + (drop (i32.sub + (i32.const -1) + (i32.add + (local.get $x) + (i32.const 1) + ) + )) + (drop (i64.sub + (i64.const -1) + (i64.add + (local.get $y) + (i64.const 1) + ) + )) + ;; 1 - (2 - x) + (drop (i32.sub + (i32.const 1) + (i32.sub + (i32.const 2) + (local.get $x) + ) + )) + (drop (i64.sub + (i64.const 1) + (i64.sub + (i64.const 2) + (local.get $y) + ) + )) + ;; 0 - (0x80000000 - x) + (drop (i32.sub + (i32.const 0) + (i32.sub + (i32.const 0x80000000) + (local.get $x) + ) + )) + ) + (func $pre-combine-or (param $x i32) (param $y i32) + (drop (i32.or + (i32.gt_s + (local.get $x) + (local.get $y) + ) + (i32.eq + (local.get $y) ;; ordering should not stop us + (local.get $x) + ) + )) + (drop (i32.or + (i32.eq ;; ordering should not stop us + (local.get $y) + (local.get $x) + ) + (i32.gt_s + (local.get $x) + (local.get $y) + ) + )) + (drop (i32.or + (i32.gt_s + (local.get $x) + (local.get $y) + ) + (i32.eq + (local.get $x) + (i32.const 1) ;; not equal + ) + )) + (drop (i32.or + (i32.gt_s + (local.get $x) + (i32.const 1) ;; not equal + ) + (i32.eq + (local.get $x) + (local.get $y) + ) + )) + (drop (i32.or + (i32.gt_s + (call $ne0) ;; side effects + (local.get $y) + ) + (i32.eq + (call $ne0) + (local.get $y) + ) + )) + (drop (i32.or + (i32.gt_s + (local.get $y) + (call $ne0) ;; side effects + ) + (i32.eq + (local.get $y) + (call $ne0) + ) + )) + ) + (func $combine-or (param $x i32) (param $y i32) + (drop (i32.or + (i32.gt_s + (local.get $x) + (local.get $y) + ) + (i32.eq + (local.get $x) + (local.get $y) + ) + )) + ;; TODO: more stuff here + ) + (func $select-into-arms (param $x i32) (param $y i32) + (if + (select + (i32.eqz (i32.eqz (local.get $x))) + (i32.eqz (i32.eqz (local.get $y))) + (local.get $y) + ) + (unreachable) + ) + ) + (func $optimize-boolean-context (param $x i32) (param $y i32) + ;; 0 - x ==> x + (if + (i32.sub + (i32.const 0) + (local.get $x) + ) + (unreachable) + ) + (drop (select + (local.get $x) + (local.get $y) + (i32.sub + (i32.const 0) + (local.get $x) + ) + )) + ) + (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64) + ;; eqz(x + 0x7FFFFFFF) -> x == -2147483647 + (drop (i32.eqz + (i32.add + (local.get $x) + (i32.const 0x7FFFFFFF) + ) + )) + ;; eqz(x + 0x80000000) -> x == -2147483648 + (drop (i32.eqz + (i32.add + (local.get $x) + (i32.const 0x80000000) + ) + )) + ;; eqz(x + 0x80000001) -> x == 2147483647 + (drop (i32.eqz + (i32.add + (local.get $x) + (i32.const 0x80000001) + ) + )) + ;; eqz(x - y) + (drop (i32.eqz + (i32.sub + (local.get $x) + (local.get $y) + ) + )) + (drop (i64.eqz + (i64.sub + (local.get $X) + (local.get $Y) + ) + )) + ;; x - y == 0 + (drop (i32.eq + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + (drop (i64.eq + (i64.sub + (local.get $X) + (local.get $Y) + ) + (i64.const 0) + )) + ;; x - y != 0 + (drop (i32.ne + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + (drop (i64.ne + (i64.sub + (local.get $X) + (local.get $Y) + ) + (i64.const 0) + )) + ;; i32(x - y) > 0 -> x > y + (drop (i32.gt_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; i32(x - y) >= 0 -> x >= y + (drop (i32.ge_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; u32(x - y) > 0 -> x != y + (drop (i32.gt_u + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; u32(x - y) >= 0 -> 1 + (drop (i32.ge_u + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; u64(x - y) >= 0 -> i32(1) + (drop (i64.ge_u + (i64.sub + (local.get $X) + (local.get $Y) + ) + (i64.const 0) + )) + ;; i32(x - y) < 0 -> x < y + (drop (i32.lt_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; i32(x - y) <= 0 -> x <= y + (drop (i32.le_s + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; u32(x - y) < 0 -> 0 + (drop (i32.lt_u + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; u64(x - y) < 0 -> i32(0) + (drop (i64.lt_u + (i64.sub + (local.get $X) + (local.get $Y) + ) + (i64.const 0) + )) + ;; u32(x - y) <= 0 -> x == y + (drop (i32.le_u + (i32.sub + (local.get $x) + (local.get $y) + ) + (i32.const 0) + )) + ;; i32(x - 0x80000000) == 0 -> x == 0x80000000 + (drop (i32.eq + (i32.sub + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 0) + )) + ;; i32(x - 0x80000000) != 0 -> x == 0x80000000 + (drop (i32.ne + (i32.sub + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 0) + )) + ;; i32(x - { 0x80000000 }) < 0 -> skip + (drop (i32.lt_s + (i32.sub + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 0) + )) + ;; i32(x - { 0x80000000 }) >= 0 -> skip + (drop (i32.ge_s + (i32.sub + (local.get $x) + (i32.const 0x80000000) + ) + (i32.const 0) + )) + ;; i32(x - { 0x80000000 }) > 0 -> skip + (drop (i32.gt_s + (i32.sub + (local.get $x) + (block (result i32) + (i32.const 0x80000000) + ) + ) + (i32.const 0) + )) + ;; i32(x - { 0x80000000 }) <= 0 -> skip + (drop (i32.gt_s + (i32.sub + (local.get $x) + (block (result i32) + (i32.const 0x80000000) + ) + ) + (i32.const 0) + )) + ) + (func $unsigned-context (param $x i32) (param $y i64) + (drop (i32.div_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const 3) + )) + (drop (i32.div_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const -3) ;; skip + )) + (drop (i32.div_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const 0x80000000) ;; skip + )) + (drop (i64.div_s + (i64.and + (local.get $y) + (i64.const 0x7fffffffffffffff) + ) + (i64.const 2) + )) + (drop (i64.div_s + (i64.and + (local.get $y) + (i64.const 0x7fffffffffffffff) + ) + (i64.const -1) ;; skip + )) + (drop (i32.rem_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const 3) + )) + (drop (i32.shr_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const 7) + )) + (drop (i32.ge_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const 7) + )) + (drop (i32.ge_s + (i32.and + (local.get $x) + (i32.const 0x7fffffff) + ) + (i32.const -7) ;; skip + )) + ) + (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32) + (drop (f64.mul + (local.get $0) + (f64.const 2) + )) + (drop (f32.mul + (local.get $1) + (f32.const 2) + )) + + (drop (f64.mul + (call $tee-with-unreachable-value) ;; side effect + (f64.const 2) + )) + (drop (f64.mul + (f64.neg (local.get $0)) ;; complex expression + (f64.const 2) + )) + ) + (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) + ;; unary + (drop (f64.abs (f64.abs (local.get $w)))) + (drop (f64.ceil (f64.ceil (local.get $w)))) + (drop (f64.floor (f64.floor (local.get $w)))) + (drop (f64.trunc (f64.trunc (local.get $w)))) + (drop (f64.nearest (f64.nearest (local.get $w)))) + + (drop (f64.nearest (f64.trunc (local.get $w)))) ;; skip + (drop (f64.trunc (f64.nearest (local.get $w)))) ;; skip + + (drop (f64.neg (f64.neg (local.get $w)))) + (drop (f64.neg (f64.neg (f64.neg (local.get $w))))) + (drop (f64.neg (f64.neg (f64.neg (f64.neg (local.get $w)))))) + + (drop (i32.eqz (i32.eqz (local.get $x)))) ;; skip + (drop (i32.eqz (i32.eqz (i32.eqz (local.get $x))))) + (drop (i32.eqz (i32.eqz (i64.eqz (i64.const 1))))) + (drop (i32.eqz (i32.eqz (i32.ne (local.get $x) (i32.const 2))))) + + (drop (i32.eqz + (i32.eqz + (i32.and + (local.get $x) + (i32.const 1) + ) + ) + )) + + ;; binary + ;; ((signed)x % y) % y + (drop (i32.rem_s + (i32.rem_s + (local.get $x) + (local.get $y) + ) + (local.get $y) + )) + ;; ((unsigned)x % y) % y + (drop (i32.rem_u + (i32.rem_u + (local.get $x) + (local.get $y) + ) + (local.get $y) + )) + ;; 0 - (0 - y) + (drop (i32.sub + (i32.const 0) + (i32.sub + (i32.const 0) + (local.get $y) + ) + )) + ;; x - (x - y) + (drop (i32.sub + (local.get $x) + (i32.sub + (local.get $x) + (local.get $y) + ) + )) + ;; y - (x - y) - skip + (drop (i32.sub + (local.get $y) + (i32.sub + (local.get $x) + (local.get $y) + ) + )) + ;; x ^ (x ^ y) + (drop (i32.xor + (local.get $x) + (i32.xor + (local.get $x) + (local.get $y) + ) + )) + ;; x ^ (y ^ x) + (drop (i32.xor + (local.get $x) + (i32.xor + (local.get $y) + (local.get $x) + ) + )) + ;; (x ^ y) ^ x + (drop (i32.xor + (i32.xor + (local.get $x) + (local.get $y) + ) + (local.get $x) + )) + ;; (y ^ x) ^ x + (drop (i32.xor + (i32.xor + (local.get $y) + (local.get $x) + ) + (local.get $x) + )) + ;; x ^ (x ^ x) + (drop (i32.xor + (local.get $x) + (i32.xor + (local.get $x) + (local.get $x) + ) + )) + ;; x & (x & y) + (drop (i32.and + (local.get $x) + (i32.and + (local.get $x) + (local.get $y) + ) + )) + ;; x & (y & x) + (drop (i32.and + (local.get $x) + (i32.and + (local.get $y) + (local.get $x) + ) + )) + ;; (x & y) & x + (drop (i32.and + (i32.and + (local.get $x) + (local.get $y) + ) + (local.get $x) + )) + ;; (y & x) & x + (drop (i32.and + (i32.and + (local.get $y) + (local.get $x) + ) + (local.get $x) + )) + ;; x | (x | y) + (drop (i32.or + (local.get $x) + (i32.or + (local.get $x) + (local.get $y) + ) + )) + ;; x | (y | x) + (drop (i32.or + (local.get $x) + (i32.or + (local.get $y) + (local.get $x) + ) + )) + ;; (x | y) | x + (drop (i32.or + (i32.or + (local.get $x) + (local.get $y) + ) + (local.get $x) + )) + ;; (y | x) | x + (drop (i32.or + (i32.or + (local.get $y) + (local.get $x) + ) + (local.get $x) + )) + ;; (y | x) | z - skip + (drop (i32.or + (i32.or + (local.get $y) + (local.get $x) + ) + (local.get $z) + )) + ;; (z | x) | y - skip + (drop (i32.or + (i32.or + (local.get $z) + (local.get $x) + ) + (local.get $y) + )) + ;; (SE() | x) | x + (drop (i32.or + (i32.or + (call $ne0) ;; side effect + (local.get $x) + ) + (local.get $x) + )) + ;; (x | SE()) | SE() - skip + (drop (i32.or + (i32.or + (local.get $x) + (call $ne0) ;; side effect + ) + (call $ne0) ;; side effect + )) + ;; x | (SE() | x) + (drop (i32.or + (local.get $x) + (i32.or + (local.get $x) + (call $ne0) ;; side effect + ) + )) + ;; SE() | (x | SE()) - skip + (drop (i32.or + (call $ne0) ;; side effect + (i32.or + (call $ne0) ;; side effect + (local.get $x) + ) + )) + ;; (y % x) % y - skip + (drop (i32.rem_s + (i32.rem_s + (local.get $y) + (local.get $x) + ) + (local.get $y) + )) + ;; y % (x % y) - skip + (drop (i32.rem_u + (local.get $y) + (i32.rem_u + (local.get $x) + (local.get $y) + ) + )) + ;; x | (y | x) where x and y cannot be reordered - skip + (drop + (i32.or + (local.get $x) + (i32.or + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.or + (i32.or + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) + ;; x ^ (y ^ x) where x and y cannot be reordered - skip + (drop + (i32.xor + (local.get $x) + (i32.xor + (local.tee $x + (i32.const 1) + ) + (local.get $x) + ) + ) + ) + (drop + (i32.xor + (i32.xor + (local.get $x) + (local.tee $x + (i32.const 1) + ) + ) + (local.get $x) + ) + ) + ) + (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64) + ;; i32 + (drop (i32.shl + (local.get $x) + (i32.const 32) + )) + (drop (i32.shr_s + (local.get $x) + (i32.const 32) + )) + (drop (i32.shr_u + (local.get $x) + (i32.const 64) + )) + (drop (i32.rotl + (local.get $x) + (i32.const 64) + )) + (drop (i32.rotr + (local.get $x) + (i32.const 64) + )) + ;; i64 + (drop (i64.shl + (local.get $z) + (i64.const 64) + )) + (drop (i64.shr_s + (local.get $z) + (i64.const 64) + )) + (drop (i64.shr_u + (local.get $z) + (i64.const 128) + )) + (drop (i64.rotl + (local.get $z) + (i64.const 128) + )) + (drop (i64.rotr + (local.get $z) + (i64.const 128) + )) + + ;; i32 + (drop (i32.shl + (local.get $x) + (i32.and + (local.get $y) + (i32.const 31) + ) + )) + (drop (i32.shl + (local.get $x) + (i32.and + (local.get $y) + (i32.const 63) + ) + )) + (drop (i32.shr_s + (local.get $x) + (i32.and + (local.get $y) + (i32.const 31) + ) + )) + (drop (i32.shr_u + (local.get $x) + (i32.and + (local.get $y) + (i32.const 31) + ) + )) + ;; i64 + (drop (i64.shl + (local.get $z) + (i64.and + (local.get $w) + (i64.const 63) + ) + )) + (drop (i64.shl + (local.get $z) + (i64.and + (local.get $w) + (i64.const 127) + ) + )) + (drop (i64.shr_s + (local.get $z) + (i64.and + (local.get $w) + (i64.const 63) + ) + )) + (drop (i64.shr_u + (local.get $z) + (i64.and + (local.get $w) + (i64.const 63) + ) + )) + ;; i32(x) >> (y & 32) -> x + (drop (i32.shr_u + (local.get $x) + (i32.and + (local.get $y) + (i32.const 32) + ) + )) + ;; i64(x) >> (y & 64) -> x + (drop (i64.shr_u + (local.get $z) + (i64.and + (local.get $w) + (i64.const 128) + ) + )) + + ;; skip + (drop (i64.shl + (local.get $z) + (i64.and + (local.get $w) + (i64.const 32) + ) + )) + ;; skip + (drop (i64.shr_u + (local.get $z) + (i64.and + (local.get $w) + (i64.const 31) + ) + )) + ) + (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32) + ;; abs(x) * abs(x) ==> x * x + (drop (f64.mul + (f64.abs (local.get $x0)) + (f64.abs (local.get $x0)) + )) + (drop (f32.mul + (f32.abs (local.get $y0)) + (f32.abs (local.get $y0)) + )) + (drop (f64.mul + (f64.abs (f64.add (local.get $x0) (local.get $x1))) + (f64.abs (f64.add (local.get $x0) (local.get $x1))) + )) + + ;; abs(x) * abs(y) ==> abs(x * y) + (drop (f64.mul + (f64.abs (local.get $x0)) + (f64.abs (local.get $x1)) + )) + (drop (f32.mul + (f32.abs (local.get $y1)) + (f32.abs (local.get $y0)) + )) + + (drop (f64.mul + (f64.abs (local.get $x0)) + (f64.abs (f64.const 0)) ;; skip + )) + (drop (f32.mul + (f32.abs (f32.const 0)) ;; skip + (f32.abs (local.get $y0)) + )) + (drop (f64.mul + (f64.abs (f64.add (local.get $x0) (local.get $x1))) + (f64.abs (f64.add (local.get $x0) (local.get $x0))) + )) + + + ;; abs(-x) ==> abs(x) + (drop (f64.abs + (f64.neg (local.get $x0)) + )) + (drop (f32.abs + (f32.neg (local.get $y0)) + )) + + ;; abs(0 - x) ==> skip for non-fast math + (drop (f64.abs + (f64.sub + (f64.const 0) + (local.get $x0) + ) + )) + (drop (f32.abs + (f32.sub + (f32.const 0) + (local.get $y0) + ) + )) + + ;; abs(x) / abs(x) ==> x / x + (drop (f64.div + (f64.abs (local.get $x0)) + (f64.abs (local.get $x0)) + )) + (drop (f32.div + (f32.abs (local.get $y0)) + (f32.abs (local.get $y0)) + )) + (drop (f64.div + (f64.abs (f64.add (local.get $x0) (local.get $x1))) + (f64.abs (f64.add (local.get $x0) (local.get $x1))) + )) + + ;; abs(x) / abs(y) ==> abs(x / y) + (drop (f64.div + (f64.abs (local.get $x0)) + (f64.abs (local.get $x1)) + )) + (drop (f32.div + (f32.abs (local.get $y1)) + (f32.abs (local.get $y0)) + )) + + ;; abs(x * x) ==> x * x + (drop (f64.abs + (f64.mul + (local.get $x0) + (local.get $x0) + ) + )) + (drop (f32.abs + (f32.mul + (local.get $y0) + (local.get $y0) + ) + )) + + ;; abs(x / x) ==> x / x + (drop (f64.abs + (f64.div + (local.get $x0) + (local.get $x0) + ) + )) + (drop (f32.abs + (f32.div + (local.get $y0) + (local.get $y0) + ) + )) + + (drop (f64.div + (f64.abs (local.get $x0)) + (f64.abs (f64.const 0)) ;; skip + )) + (drop (f32.div + (f32.abs (f32.const 0)) ;; skip + (f32.abs (local.get $y0)) + )) + (drop (f64.div + (f64.abs (f64.add (local.get $x0) (local.get $x1))) + (f64.abs (f64.add (local.get $x0) (local.get $x0))) + )) + ) +) +;; atomics +(module + (import "env" "memory" (memory $0 (shared 256 256))) + (func $x + (drop + (i32.shr_s + (i32.shl + (i32.atomic.load8_u ;; can't be signed + (i32.const 100) + ) + (i32.const 24) + ) + (i32.const 24) + ) + ) + ) +) +;; bulk memory +(module + (memory 0) + (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) + (memory.copy ;; skip + (local.get $dst) + (local.get $dst) + (local.get $sz) + ) + + (memory.copy ;; skip + (local.get $dst) + (local.get $src) + (i32.const 0) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 1) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 2) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 3) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 4) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 5) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 6) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 7) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 8) + ) + + (memory.copy + (local.get $dst) + (local.get $src) + (i32.const 16) + ) + + (memory.copy ;; skip + (local.get $dst) + (local.get $src) + (local.get $sz) + ) + + (memory.copy ;; skip + (i32.const 0) + (i32.const 0) + (i32.load + (i32.const 3) ;; side effect + ) + ) + ) +) +;; reference types +(module + ;; These functions test if an `if` with subtyped arms is correctly folded + ;; 1. if its `ifTrue` and `ifFalse` arms are identical (can fold) + (func $if-arms-subtype-fold (result anyref) + (if (result anyref) + (i32.const 0) + (ref.null extern) + (ref.null extern) + ) + ) + ;; 2. if its `ifTrue` and `ifFalse` arms are not identical (cannot fold) + (func $if-arms-subtype-nofold (result anyref) + (if (result anyref) + (i32.const 0) + (ref.null extern) + (ref.null func) + ) + ) +) +;; sign-extensions +(module + (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) + (drop (i32.extend8_s (i32.extend8_s (local.get $x)))) + (drop (i32.extend16_s (i32.extend16_s (local.get $x)))) + ) +) +;; exceptions +(module + (func $test + (if + (try (result i32) + (do + (i32.eqz + (i32.eqz + (i32.const 123) + ) + ) + ) + (catch + (drop + (pop exnref) + ) + (i32.eqz + (i32.eqz + (i32.const 456) + ) + ) + ) + ) + (nop) + ) + ) +) +;; typed function references +(module + (type $i32-i32 (func (param i32) (result i32))) + ;; this function has a reference parameter. we analyze parameters, and should + ;; not be confused by a type that has no bit size, in particular. this test + ;; just verifies that we do not crash on that. + (func $call_from-param (param $f (ref null $i32-i32)) (result i32) + (unreachable) + ) +) diff -Nru binaryen-108/test/passes/optimize-instructions_fuzz-exec.txt binaryen-99/test/passes/optimize-instructions_fuzz-exec.txt --- binaryen-108/test/passes/optimize-instructions_fuzz-exec.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/optimize-instructions_fuzz-exec.txt 2021-01-07 20:01:06.000000000 +0000 @@ -253,10 +253,6 @@ [LoggingExternalInterface logging nan:0x400000] [LoggingExternalInterface logging nan:0x400000] [LoggingExternalInterface logging nan:0x400000] -[fuzz-exec] comparing ignore -[fuzz-exec] comparing just-one-nan -[fuzz-exec] comparing test32 -[fuzz-exec] comparing test64 [fuzz-exec] calling foo [LoggingExternalInterface logging 1] [LoggingExternalInterface logging 1] @@ -270,8 +266,8 @@ (module (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (import "fuzzing-support" "log-i32" (func $log (param i32))) (export "foo" (func $1)) (export "do-shift" (func $3)) @@ -385,5 +381,3 @@ [fuzz-exec] note result: call-compare-maybe-signed-ne => 1 [fuzz-exec] comparing call-compare-maybe-signed-eq [fuzz-exec] comparing call-compare-maybe-signed-ne -[fuzz-exec] comparing do-shift -[fuzz-exec] comparing foo diff -Nru binaryen-108/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.txt binaryen-99/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.txt --- binaryen-108/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,384 @@ +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $none_=>_f64 (func (result f64))) + (memory $0 0) + (func $conditionals (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $0 + (i32.const 0) + ) + (loop $while-in + (local.set $3 + (i32.const 0) + ) + (loop $while-in6 + (local.set $6 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $0 + (if (result i32) + (if (result i32) + (i32.rem_s + (i32.add + (i32.mul + (local.get $0) + (local.tee $7 + (i32.add + (local.get $0) + (i32.const 2) + ) + ) + ) + (i32.const 17) + ) + (i32.const 5) + ) + (i32.eqz + (i32.rem_u + (i32.add + (i32.mul + (local.get $0) + (local.get $0) + ) + (i32.const 11) + ) + (i32.const 3) + ) + ) + (i32.const 1) + ) + (local.get $7) + (local.get $6) + ) + ) + (br_if $while-in6 + (i32.gt_s + (local.get $4) + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + ) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 27000) + ) + ) + ) + (return + (local.get $5) + ) + ) + (func $side-effect (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $0 + (i32.const 0) + ) + (loop $while-in + (local.set $3 + (i32.const 0) + ) + (loop $while-in6 + (local.set $6 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $0 + (if (result i32) + (i32.or + (i32.eqz + (i32.rem_s + (i32.add + (i32.mul + (local.get $0) + (local.tee $7 + (local.get $0) + ) + ) + (i32.const 17) + ) + (i32.const 5) + ) + ) + (i32.eqz + (i32.rem_u + (i32.add + (i32.mul + (local.get $0) + (local.get $0) + ) + (unreachable) + ) + (i32.const 3) + ) + ) + ) + (local.get $7) + (local.get $6) + ) + ) + (br_if $while-in6 + (i32.gt_s + (local.get $4) + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + ) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 27000) + ) + ) + ) + (return + (local.get $5) + ) + ) + (func $flip (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $0 + (i32.const 0) + ) + (loop $while-in + (local.set $3 + (i32.const 0) + ) + (loop $while-in6 + (local.set $6 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $0 + (if (result i32) + (if (result i32) + (i32.rem_u + (i32.add + (i32.mul + (local.get $0) + (local.get $0) + ) + (i32.const 100) + ) + (i32.const 3) + ) + (i32.eqz + (i32.rem_s + (i32.add + (i32.mul + (local.get $0) + (i32.eqz + (local.get $0) + ) + ) + (i32.const 17) + ) + (i32.const 5) + ) + ) + (i32.const 1) + ) + (local.get $7) + (local.get $6) + ) + ) + (br_if $while-in6 + (i32.gt_s + (local.get $4) + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + ) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 27000) + ) + ) + ) + (return + (local.get $5) + ) + ) + (func $invalidate-conditionalizeExpensiveOnBitwise (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (i32.and + (i32.lt_u + (i32.and + (i32.shr_s + (i32.shl + (i32.sub + (local.get $1) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.ne + (local.tee $1 + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (return + (local.get $0) + ) + ) + (return + (local.get $1) + ) + ) + (func $invalidate-conditionalizeExpensiveOnBitwise-ok (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (if (result i32) + (local.tee $1 + (i32.const 0) + ) + (i32.lt_u + (i32.and + (i32.shr_s + (i32.shl + (i32.sub + (local.get $0) + (i32.const 1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.const 0) + ) + ) + (return + (local.get $0) + ) + ) + (return + (local.get $1) + ) + ) + (func $conditionalize-if-type-change (result f64) + (local $0 i32) + (drop + (loop $label$1 (result f32) + (block $label$2 (result f32) + (drop + (block $label$3 (result f32) + (br_if $label$1 + (i32.or + (f32.gt + (br_if $label$3 + (f32.const 1) + (local.get $0) + ) + (br $label$2 + (f32.const 71) + ) + ) + (i64.eqz + (select + (i64.const 58) + (i64.const -982757) + (i64.eqz + (i64.const 0) + ) + ) + ) + ) + ) + ) + ) + (f32.const 1) + ) + ) + ) + (f64.const -nan:0xfffffffffffff) + ) + (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) + (block + (drop + (local.get $dst) + ) + (drop + (local.get $dst) + ) + (drop + (local.get $sz) + ) + ) + (block + (drop + (local.get $dst) + ) + (drop + (local.get $src) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.wast binaryen-99/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.wast --- binaryen-108/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/optimize-instructions_optimize-level=2_all-features_ignore-implicit-traps.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,378 @@ +(module + (type $0 (func (param i32 i32) (result i32))) + (memory $0 0) + (func $conditionals (type $0) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $0 + (i32.const 0) + ) + (loop $while-in + (local.set $3 + (i32.const 0) + ) + (loop $while-in6 + (local.set $6 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $0 + (if (result i32) + (i32.or ;; this or is very expensive. we should compute one side, then see if we even need the other + (i32.eqz + (i32.rem_s + (i32.add + (i32.mul + (local.tee $7 ;; side effect, so we can't do this one + (i32.add + (local.get $0) + (i32.const 2) + ) + ) + (local.get $0) + ) + (i32.const 17) + ) + (i32.const 5) + ) + ) + (i32.eqz + (i32.rem_u + (i32.add + (i32.mul + (local.get $0) + (local.get $0) + ) + (i32.const 11) + ) + (i32.const 3) + ) + ) + ) + (local.get $7) + (local.get $6) + ) + ) + (br_if $while-in6 + (i32.lt_s + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (local.get $4) + ) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 27000) + ) + ) + ) + (return + (local.get $5) + ) + ) + (func $side-effect (type $0) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $0 + (i32.const 0) + ) + (loop $while-in + (local.set $3 + (i32.const 0) + ) + (loop $while-in6 + (local.set $6 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $0 + (if (result i32) + (i32.or ;; this or is very expensive, but has a side effect on both sides + (i32.eqz + (i32.rem_s + (i32.add + (i32.mul + (local.tee $7 + (i32.add + (local.get $0) + (i32.const 0) + ) + ) + (local.get $0) + ) + (i32.const 17) + ) + (i32.const 5) + ) + ) + (i32.eqz + (i32.rem_u + (i32.add + (i32.mul + (local.get $0) + (local.get $0) + ) + (unreachable) + ) + (i32.const 3) + ) + ) + ) + (local.get $7) + (local.get $6) + ) + ) + (br_if $while-in6 + (i32.lt_s + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (local.get $4) + ) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 27000) + ) + ) + ) + (return + (local.get $5) + ) + ) + (func $flip (type $0) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local.set $0 + (i32.const 0) + ) + (loop $while-in + (local.set $3 + (i32.const 0) + ) + (loop $while-in6 + (local.set $6 + (i32.add + (local.get $0) + (i32.const 1) + ) + ) + (local.set $0 + (if (result i32) + (i32.or ;; this or is very expensive, and the first side has no side effect + (i32.eqz + (i32.rem_s + (i32.add + (i32.mul + (i32.eqz + (i32.add + (local.get $0) + (i32.const 0) + ) + ) + (local.get $0) + ) + (i32.const 17) + ) + (i32.const 5) + ) + ) + (i32.eqz + (i32.rem_u + (i32.add + (i32.mul + (local.get $0) + (local.get $0) + ) + (i32.const 100) + ) + (i32.const 3) + ) + ) + ) + (local.get $7) + (local.get $6) + ) + ) + (br_if $while-in6 + (i32.lt_s + (local.tee $3 + (i32.add + (local.get $3) + (i32.const 1) + ) + ) + (local.get $4) + ) + ) + ) + (br_if $while-in + (i32.ne + (local.tee $1 + (i32.add + (local.get $1) + (i32.const 1) + ) + ) + (i32.const 27000) + ) + ) + ) + (return + (local.get $5) + ) + ) + (func $invalidate-conditionalizeExpensiveOnBitwise (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (i32.and + (i32.lt_s + (i32.and + (i32.shr_s + (i32.shl + (i32.add + (local.get $1) ;; conflict with tee + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.ne + (local.tee $1 + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (return (local.get $0)) + ) + (return (local.get $1)) + ) + (func $invalidate-conditionalizeExpensiveOnBitwise-ok (param $0 i32) (param $1 i32) (result i32) + (if + (i32.eqz + (i32.and + (i32.lt_s + (i32.and + (i32.shr_s + (i32.shl + (i32.add + (local.get $0) ;; no conflict + (i32.const -1) + ) + (i32.const 24) + ) + (i32.const 24) + ) + (i32.const 255) + ) + (i32.const 3) + ) + (i32.ne + (local.tee $1 + (i32.const 0) + ) + (i32.const 0) + ) + ) + ) + (return (local.get $0)) + ) + (return (local.get $1)) + ) + + (func $conditionalize-if-type-change (result f64) + (local $0 i32) + (drop + (loop $label$1 (result f32) + (block $label$2 (result f32) + (drop + (block $label$3 (result f32) + (br_if $label$1 + (i32.or ;; this turns into an if, but then the if might not be unreachable + (f32.gt + (br_if $label$3 + (f32.const 1) + (local.get $0) + ) + (br $label$2 + (f32.const 71) + ) + ) + (i64.eqz + (select + (i64.const 58) + (i64.const -982757) + (i64.eqz + (i64.const 0) + ) + ) + ) + ) + ) + ) + ) + (f32.const 1) + ) + ) + ) + (f64.const -nan:0xfffffffffffff) + ) + (func $optimize-bulk-memory-copy (param $dst i32) (param $src i32) (param $sz i32) + (memory.copy ;; nop + (local.get $dst) + (local.get $dst) + (local.get $sz) + ) + + (memory.copy ;; nop + (local.get $dst) + (local.get $src) + (i32.const 0) + ) + ) +) + diff -Nru binaryen-108/test/passes/Os_print-stack-ir_all-features_disable-gc.txt binaryen-99/test/passes/Os_print-stack-ir_all-features_disable-gc.txt --- binaryen-108/test/passes/Os_print-stack-ir_all-features_disable-gc.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/Os_print-stack-ir_all-features_disable-gc.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) -(module - (type $i32_=>_i32 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) - (i32.add - (call $stacky-help - (i32.const 0) - ) - (block (result i32) - (local.set $0 - (call $stacky-help - (i32.const 1) - ) - ) - (drop - (call $stacky-help - (i32.const 2) - ) - ) - (i32.eqz - (local.get $0) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/passes/Os_print-stack-ir_all-features_disable-gc.wast binaryen-99/test/passes/Os_print-stack-ir_all-features_disable-gc.wast --- binaryen-108/test/passes/Os_print-stack-ir_all-features_disable-gc.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/Os_print-stack-ir_all-features_disable-gc.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -(module - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (param $x i32) (result i32) - (local $temp i32) - (i32.add - (call $stacky-help (i32.const 0)) - (i32.eqz - (block (result i32) ;; after we use the stack instead of the local, we can remove this block - (local.set $temp (call $stacky-help (i32.const 1))) - (drop (call $stacky-help (i32.const 2))) - (local.get $temp) - ) - ) - ) - ) -) diff -Nru binaryen-108/test/passes/Os_print-stack-ir_all-features.txt binaryen-99/test/passes/Os_print-stack-ir_all-features.txt --- binaryen-108/test/passes/Os_print-stack-ir_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/Os_print-stack-ir_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,41 @@ +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) + (i32.add + (call $stacky-help + (i32.const 0) + ) + (block (result i32) + (local.set $0 + (call $stacky-help + (i32.const 1) + ) + ) + (drop + (call $stacky-help + (i32.const 2) + ) + ) + (i32.eqz + (local.get $0) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/Os_print-stack-ir_all-features.wast binaryen-99/test/passes/Os_print-stack-ir_all-features.wast --- binaryen-108/test/passes/Os_print-stack-ir_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/Os_print-stack-ir_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,16 @@ +(module + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $x i32) (result i32) + (local $temp i32) + (i32.add + (call $stacky-help (i32.const 0)) + (i32.eqz + (block (result i32) ;; after we use the stack instead of the local, we can remove this block + (local.set $temp (call $stacky-help (i32.const 1))) + (drop (call $stacky-help (i32.const 2))) + (local.get $temp) + ) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/O.txt binaryen-99/test/passes/O.txt --- binaryen-108/test/passes/O.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,56 @@ +(module + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i64_=>_none (func (param i64))) + (type $none_=>_i32 (func (result i32))) + (export "ret" (func $ret)) + (export "waka" (func $if-0-unreachable-to-none)) + (export "many-selects" (func $many-selects)) + (export "end-if-else" (func $end-if-else)) + (export "end-if-else-call" (func $end-if-else-call)) + (func $ret (; has Stack IR ;) (result i32) + (drop + (call $ret) + ) + (if + (call $ret) + (return + (i32.const 1) + ) + ) + (i32.const 999) + ) + (func $if-0-unreachable-to-none (; has Stack IR ;) (param $0 i64) + (unreachable) + ) + (func $many-selects (; has Stack IR ;) (param $0 i32) (result i32) + (select + (i32.const -1073741824) + (select + (i32.const 1073741823) + (local.get $0) + (i32.gt_s + (local.get $0) + (i32.const 1073741823) + ) + ) + (i32.lt_s + (local.get $0) + (i32.const -1073741824) + ) + ) + ) + (func $end-if-else (; has Stack IR ;) (param $0 i32) (result i32) + (select + (i32.const 1) + (local.get $0) + (local.get $0) + ) + ) + (func $end-if-else-call (; has Stack IR ;) (param $0 i32) (result i32) + (if (result i32) + (local.get $0) + (call $ret) + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/O.wast binaryen-99/test/passes/O.wast --- binaryen-108/test/passes/O.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/O.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,67 @@ +(module + (func $ret (export "ret") (result i32) + (block $out (result i32) + (drop (call $ret)) + (if (call $ret) + (return + (return + (i32.const 1) + ) + ) + ) + (drop (br_if $out (i32.const 999) (i32.const 1))) + (unreachable) + ) + ) + (func $if-0-unreachable-to-none (export "waka") (param $var$0 i64) + (local $var$1 i64) + (local $var$2 i64) + (block $label$1 + (if + (i32.const 0) + (br $label$1) + (unreachable) + ) + ) + ) + (func $many-selects (export "many-selects") (param $0 i32) (result i32) + (if + (i32.lt_s + (local.get $0) + (i32.const -1073741824) + ) + (local.set $0 + (i32.const -1073741824) + ) + (if + (i32.gt_s + (local.get $0) + (i32.const 1073741823) + ) + (local.set $0 + (i32.const 1073741823) + ) + ) + ) + (local.get $0) + ) + (func $end-if-else (export "end-if-else") (param $x i32) (result i32) + (if + (local.get $x) + (local.set $x + (i32.const 1) + ) + ) + (local.get $x) + ) + (func $end-if-else-call (export "end-if-else-call") (param $x i32) (result i32) + (if + (local.get $x) + (local.set $x + (call $ret) + ) + ) + (local.get $x) + ) +) + diff -Nru binaryen-108/test/passes/Oz_fuzz-exec_all-features.txt binaryen-99/test/passes/Oz_fuzz-exec_all-features.txt --- binaryen-108/test/passes/Oz_fuzz-exec_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/Oz_fuzz-exec_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -21,449 +21,178 @@ [fuzz-exec] calling br_on_cast [LoggingExternalInterface logging 3] [trap unreachable] -[fuzz-exec] calling br_on_failed_cast-1 -[LoggingExternalInterface logging 1] -[fuzz-exec] calling br_on_failed_cast-2 -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 999] -[fuzz-exec] calling cast-null-anyref-to-gc -[LoggingExternalInterface logging 0] -[fuzz-exec] calling br_on_data -[LoggingExternalInterface logging 1] -[fuzz-exec] calling br_on_non_data-null -[fuzz-exec] calling br_on_non_data-data -[LoggingExternalInterface logging 1] -[fuzz-exec] calling br_on_non_data-other -[fuzz-exec] calling br-on_non_null -[fuzz-exec] calling br-on_non_null-2 -[LoggingExternalInterface logging 1] -[trap unreachable] -[fuzz-exec] calling ref-as-data-of-func -[trap not a data] -[fuzz-exec] calling ref-as-data-of-data -[fuzz-exec] calling ref-as-func-of-data -[trap not a func] -[fuzz-exec] calling ref-as-func-of-func -[fuzz-exec] calling rtt-and-cast-on-func -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 2] -[LoggingExternalInterface logging 1337] -[LoggingExternalInterface logging 3] -[trap cast error] -[fuzz-exec] calling array-alloc-failure -[host limit allocation failure] -[fuzz-exec] calling init-array-packed -[fuzz-exec] note result: init-array-packed => 213 -[fuzz-exec] calling cast-func-to-struct -[trap cast error] -[fuzz-exec] calling array-copy -[LoggingExternalInterface logging 10] -[LoggingExternalInterface logging 10] -[LoggingExternalInterface logging 99] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 10] -[fuzz-exec] calling rtt_Fresh -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[fuzz-exec] calling array.init -[LoggingExternalInterface logging 2] -[LoggingExternalInterface logging 42] -[LoggingExternalInterface logging 50] -[fuzz-exec] calling array.init-packed -[LoggingExternalInterface logging 8] -[fuzz-exec] calling static-casts -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 0] -[fuzz-exec] calling static-br_on_cast -[LoggingExternalInterface logging 3] -[fuzz-exec] calling static-br_on_cast_fail -[LoggingExternalInterface logging -2] (module - (type $void_func (func)) - (type $bytes (array (mut i8))) - (type $struct (struct (field (mut i32)))) - (type $extendedstruct (struct (field (mut i32)) (field f64))) + (type ${i32} (struct (field i32))) + (type $none_=>_none (func)) + (type ${i32_f64} (struct (field i32) (field f64))) + (type $[mut:i8] (array (mut i8))) (type $i32_=>_none (func (param i32))) - (type $anyref_=>_none (func (param anyref))) - (type $int_func (func (result i32))) (import "fuzzing-support" "log-i32" (func $log (param i32))) - (global $rtt (mut (rtt $extendedstruct)) (rtt.canon $extendedstruct)) (export "structs" (func $0)) (export "arrays" (func $1)) (export "rtts" (func $2)) (export "br_on_cast" (func $3)) - (export "br_on_failed_cast-1" (func $4)) - (export "br_on_failed_cast-2" (func $5)) - (export "cast-null-anyref-to-gc" (func $6)) - (export "br_on_data" (func $8)) - (export "br_on_non_data-null" (func $9)) - (export "br_on_non_data-data" (func $10)) - (export "br_on_non_data-other" (func $9)) - (export "br-on_non_null" (func $9)) - (export "br-on_non_null-2" (func $13)) - (export "ref-as-data-of-func" (func $14)) - (export "ref-as-data-of-data" (func $9)) - (export "ref-as-func-of-data" (func $14)) - (export "ref-as-func-of-func" (func $9)) - (export "rtt-and-cast-on-func" (func $19)) - (export "array-alloc-failure" (func $9)) - (export "init-array-packed" (func $21)) - (export "cast-func-to-struct" (func $14)) - (export "array-copy" (func $24)) - (export "rtt_Fresh" (func $25)) - (export "array.init" (func $26)) - (export "array.init-packed" (func $27)) - (export "static-casts" (func $28)) - (export "static-br_on_cast" (func $29)) - (export "static-br_on_cast_fail" (func $30)) (func $0 (; has Stack IR ;) - (local $0 i32) + (local $0 (ref null ${i32})) (call $log - (i32.const 0) + (struct.get ${i32} 0 + (local.tee $0 + (struct.new_default_with_rtt ${i32} + (rtt.canon ${i32}) + ) + ) + ) ) - (call $log + (struct.set ${i32} 0 + (local.get $0) (i32.const 42) ) (call $log - (local.tee $0 - (i32.const 100) + (struct.get ${i32} 0 + (local.get $0) ) ) - (call $log + (struct.set ${i32} 0 + (local.get $0) (i32.const 100) ) + (call $log + (struct.get ${i32} 0 + (local.get $0) + ) + ) + (call $log + (struct.get ${i32} 0 + (local.get $0) + ) + ) ) (func $1 (; has Stack IR ;) - (local $0 (ref null $bytes)) + (local $0 (ref null $[mut:i8])) (call $log - (array.len $bytes + (array.len $[mut:i8] (local.tee $0 - (array.new_with_rtt $bytes - (i32.const 42) + (array.new_with_rtt $[mut:i8] + (rtt.canon $[mut:i8]) (i32.const 50) - (rtt.canon $bytes) + (i32.const 42) ) ) ) ) (call $log - (array.get_u $bytes + (array.get_u $[mut:i8] (local.get $0) (i32.const 10) ) ) - (array.set $bytes + (array.set $[mut:i8] (local.get $0) (i32.const 10) - (i32.const 128) + (i32.const 65408) ) (call $log - (array.get_u $bytes + (array.get_u $[mut:i8] (local.get $0) (i32.const 10) ) ) (call $log - (array.get_s $bytes + (array.get_s $[mut:i8] (local.get $0) (i32.const 10) ) ) (call $log - (array.get_s $bytes + (array.get_s $[mut:i8] (local.get $0) (i32.const 20) ) ) ) (func $2 (; has Stack IR ;) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - ) - (func $3 (; has Stack IR ;) - (call $log - (i32.const 3) - ) - (unreachable) - ) - (func $4 (; has Stack IR ;) - (local $0 (ref null $struct)) - (local.set $0 - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - (drop - (block $any (result anyref) - (call $log - (i32.const 1) - ) - (drop - (br_on_cast_fail $any - (local.get $0) - (rtt.canon $extendedstruct) - ) - ) - (call $log - (i32.const 999) - ) - (ref.null any) - ) - ) - ) - (func $5 (; has Stack IR ;) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 999) - ) - ) - (func $6 (; has Stack IR ;) - (call $log - (i32.const 0) - ) - ) - (func $8 (; has Stack IR ;) (param $0 anyref) - (drop - (block $data (result dataref) - (drop - (br_on_data $data - (local.get $0) - ) - ) - (call $log - (i32.const 1) - ) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ) - ) - (func $9 (; has Stack IR ;) - (nop) - ) - (func $10 (; has Stack IR ;) - (call $log - (i32.const 1) - ) - ) - (func $13 (; has Stack IR ;) - (drop - (block - (call $log - (i32.const 1) - ) - (unreachable) - ) - ) - ) - (func $14 (; has Stack IR ;) - (drop - (unreachable) - ) - ) - (func $19 (; has Stack IR ;) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 2) - ) - (call $log - (i32.const 1337) - ) - (call $log - (i32.const 3) - ) - (unreachable) - ) - (func $21 (; has Stack IR ;) (result i32) - (array.get_u $bytes - (array.new_with_rtt $bytes - (i32.const -43) - (i32.const 50) - (rtt.canon $bytes) - ) - (i32.const 10) - ) - ) - (func $24 (; has Stack IR ;) - (local $0 (ref null $bytes)) - (local $1 (ref null $bytes)) - (array.set $bytes - (local.tee $1 - (array.new_default_with_rtt $bytes - (i32.const 200) - (rtt.canon $bytes) - ) - ) - (i32.const 42) - (i32.const 99) - ) - (call $log - (array.get_u $bytes + (local $0 (rtt ${i32})) + (local $1 (rtt ${i32_f64})) + (local $2 (rtt ${i32_f64})) + (local $3 anyref) + (local.set $1 + (rtt.sub ${i32_f64} (local.tee $0 - (array.new_with_rtt $bytes - (i32.const 10) - (i32.const 100) - (rtt.canon $bytes) - ) + (rtt.canon ${i32}) ) - (i32.const 10) ) ) - (array.copy $bytes $bytes - (local.get $0) - (i32.const 10) - (local.get $1) - (i32.const 42) - (i32.const 2) + (local.set $2 + (rtt.canon ${i32_f64}) ) (call $log - (array.get_u $bytes - (local.get $0) - (i32.const 9) + (ref.is_null + (ref.cast ${i32} + (ref.null ${i32}) + (local.get $0) + ) ) ) (call $log - (array.get_u $bytes + (ref.test ${i32} + (ref.null ${i32}) (local.get $0) - (i32.const 10) ) ) (call $log - (array.get_u $bytes + (ref.test ${i32} + (array.new_with_rtt $[mut:i8] + (rtt.canon $[mut:i8]) + (i32.const 10) + (i32.const 20) + ) (local.get $0) - (i32.const 11) ) ) (call $log - (array.get_u $bytes + (ref.test ${i32} + (struct.new_default_with_rtt ${i32} + (local.get $0) + ) (local.get $0) - (i32.const 12) - ) - ) - ) - (func $25 (; has Stack IR ;) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (global.set $rtt - (rtt.fresh_sub $extendedstruct - (rtt.canon $struct) ) ) (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (global.get $rtt) + (ref.test ${i32_f64} + (struct.new_default_with_rtt ${i32} + (local.get $0) ) - (global.get $rtt) + (local.get $2) ) ) - ) - (func $26 (; has Stack IR ;) - (local $0 (ref null $bytes)) (call $log - (array.len $bytes - (local.tee $0 - (array.init $bytes - (i32.const 42) - (i32.const 50) - (rtt.canon $bytes) + (ref.test ${i32_f64} + (local.tee $3 + (struct.new_default_with_rtt ${i32_f64} + (local.get $1) ) ) + (local.get $1) ) ) (call $log - (array.get_u $bytes - (local.get $0) - (i32.const 0) + (ref.test ${i32_f64} + (local.get $3) + (local.get $2) ) ) (call $log - (array.get_u $bytes + (ref.test ${i32} + (local.get $3) (local.get $0) - (i32.const 1) - ) - ) - ) - (func $27 (; has Stack IR ;) - (call $log - (array.get_u $bytes - (array.init $bytes - (i32.const -11512) - (rtt.canon $bytes) - ) - (i32.const 0) ) ) ) - (func $28 (; has Stack IR ;) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - (call $log - (i32.const 0) - ) - (call $log - (i32.const 1) - ) - ) - (func $29 (; has Stack IR ;) + (func $3 (; has Stack IR ;) (call $log (i32.const 3) ) - ) - (func $30 (; has Stack IR ;) - (call $log - (i32.const -2) - ) + (unreachable) ) ) [fuzz-exec] calling structs @@ -489,78 +218,3 @@ [fuzz-exec] calling br_on_cast [LoggingExternalInterface logging 3] [trap unreachable] -[fuzz-exec] calling br_on_failed_cast-1 -[LoggingExternalInterface logging 1] -[fuzz-exec] calling br_on_failed_cast-2 -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 999] -[fuzz-exec] calling cast-null-anyref-to-gc -[LoggingExternalInterface logging 0] -[fuzz-exec] calling br_on_data -[LoggingExternalInterface logging 1] -[fuzz-exec] calling br_on_non_data-null -[fuzz-exec] calling br_on_non_data-data -[LoggingExternalInterface logging 1] -[fuzz-exec] calling br_on_non_data-other -[fuzz-exec] calling br-on_non_null -[fuzz-exec] calling br-on_non_null-2 -[LoggingExternalInterface logging 1] -[trap unreachable] -[fuzz-exec] calling ref-as-data-of-func -[trap unreachable] -[fuzz-exec] calling ref-as-data-of-data -[fuzz-exec] calling ref-as-func-of-data -[trap unreachable] -[fuzz-exec] calling ref-as-func-of-func -[fuzz-exec] calling rtt-and-cast-on-func -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 2] -[LoggingExternalInterface logging 1337] -[LoggingExternalInterface logging 3] -[trap unreachable] -[fuzz-exec] calling array-alloc-failure -[fuzz-exec] calling init-array-packed -[fuzz-exec] note result: init-array-packed => 213 -[fuzz-exec] calling cast-func-to-struct -[trap unreachable] -[fuzz-exec] calling array-copy -[LoggingExternalInterface logging 10] -[LoggingExternalInterface logging 10] -[LoggingExternalInterface logging 99] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 10] -[fuzz-exec] calling rtt_Fresh -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[fuzz-exec] calling array.init -[LoggingExternalInterface logging 2] -[LoggingExternalInterface logging 42] -[LoggingExternalInterface logging 50] -[fuzz-exec] calling array.init-packed -[LoggingExternalInterface logging 8] -[fuzz-exec] calling static-casts -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[LoggingExternalInterface logging 0] -[LoggingExternalInterface logging 1] -[fuzz-exec] calling static-br_on_cast -[LoggingExternalInterface logging 3] -[fuzz-exec] calling static-br_on_cast_fail -[LoggingExternalInterface logging -2] -ignoring comparison of ExecutionResults! -[fuzz-exec] calling foo -[host limit allocation failure] -(module - (type $none_=>_i32 (func (result i32))) - (export "foo" (func $0)) - (func $0 (; has Stack IR ;) (result i32) - (i32.const 0) - ) -) -[fuzz-exec] calling foo -[fuzz-exec] note result: foo => 0 -ignoring comparison of ExecutionResults! diff -Nru binaryen-108/test/passes/Oz_fuzz-exec_all-features.wast binaryen-99/test/passes/Oz_fuzz-exec_all-features.wast --- binaryen-108/test/passes/Oz_fuzz-exec_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/Oz_fuzz-exec_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,8 @@ (module - (type $struct (struct (mut i32))) - (type $extendedstruct (struct (mut i32) f64)) + (type $struct (struct i32)) + (type $extendedstruct (struct i32 f64)) (type $bytes (array (mut i8))) - - (type $void_func (func)) - (type $int_func (func (result i32))) - (import "fuzzing-support" "log-i32" (func $log (param i32))) - - (global $rtt (mut (rtt $extendedstruct)) (rtt.canon $extendedstruct)) - (func "structs" (local $x (ref null $struct)) (local $y (ref null $struct)) @@ -19,9 +12,7 @@ ) ) ;; The value is initialized to 0 - ;; Note: We cannot optimize these to constants without either immutability or - ;; some kind of escape analysis (to verify that the GC data referred to is not - ;; written to elsewhere). + ;; Note: -Oz will optimize all these to constants thanks to Precompute (call $log (struct.get $struct 0 (local.get $x)) ) @@ -50,9 +41,9 @@ (local $x (ref null $bytes)) (local.set $x (array.new_with_rtt $bytes - (i32.const 42) ;; value to splat into the array - (i32.const 50) ;; size (rtt.canon $bytes) + (i32.const 50) ;; size + (i32.const 42) ;; value to splat into the array ) ) ;; The length should be 50 @@ -78,69 +69,75 @@ ) ) (func "rtts" - (local $any anyref) + (local $x (rtt $struct)) + (local $y (rtt $extendedstruct)) + (local $z (rtt $extendedstruct)) + (local $any anyref) + (local.set $x (rtt.canon $struct)) + (local.set $y (rtt.sub $extendedstruct (local.get $x))) + (local.set $z (rtt.canon $extendedstruct)) ;; Casting null returns null. (call $log (ref.is_null - (ref.cast (ref.null $struct) (rtt.canon $struct)) + (ref.cast $struct (ref.null $struct) (local.get $x)) )) ;; Testing null returns 0. (call $log - (ref.test (ref.null $struct) (rtt.canon $struct)) + (ref.test $struct (ref.null $struct) (local.get $x)) ) ;; Testing something completely wrong (struct vs array) returns 0. (call $log - (ref.test + (ref.test $struct (array.new_with_rtt $bytes - (i32.const 20) - (i32.const 10) (rtt.canon $bytes) + (i32.const 10) + (i32.const 20) ) - (rtt.canon $struct) + (local.get $x) ) ) ;; Testing a thing with the same RTT returns 1. (call $log - (ref.test + (ref.test $struct (struct.new_default_with_rtt $struct - (rtt.canon $struct) + (local.get $x) ) - (rtt.canon $struct) + (local.get $x) ) ) ;; A bad downcast returns 0: we create a struct, which is not a extendedstruct. (call $log - (ref.test + (ref.test $extendedstruct (struct.new_default_with_rtt $struct - (rtt.canon $struct) + (local.get $x) ) - (rtt.canon $extendedstruct) + (local.get $z) ) ) ;; Create a extendedstruct with RTT y, and upcast statically to anyref. (local.set $any (struct.new_default_with_rtt $extendedstruct - (rtt.sub $extendedstruct (rtt.canon $struct)) + (local.get $y) ) ) ;; Casting to y, the exact same RTT, works. (call $log - (ref.test + (ref.test $extendedstruct (local.get $any) - (rtt.sub $extendedstruct (rtt.canon $struct)) + (local.get $y) ) ) ;; Casting to z, another RTT of the same data type, fails. (call $log - (ref.test + (ref.test $extendedstruct (local.get $any) - (rtt.canon $extendedstruct) + (local.get $z) ) ) ;; Casting to x, the parent of y, works. (call $log - (ref.test + (ref.test $struct (local.get $any) - (rtt.canon $struct) + (local.get $x) ) ) ) @@ -156,9 +153,9 @@ (block $extendedblock (result (ref $extendedstruct)) (drop ;; second, try to cast our simple $struct to what it is, which will work - (br_on_cast $block + (br_on_cast $block $struct ;; first, try to cast our simple $struct to an extended, which will fail - (br_on_cast $extendedblock + (br_on_cast $extendedblock $extendedstruct (local.get $any) (rtt.canon $extendedstruct) ) (rtt.canon $struct) @@ -177,475 +174,9 @@ (block $never (result (ref $extendedstruct)) ;; an untaken br_on_cast, with unreachable rtt - so we cannot use the ;; RTT in binaryen IR to find the cast type. - (br_on_cast $never (ref.null $struct) (unreachable)) - (unreachable) - ) - ) - ) - (func "br_on_failed_cast-1" - (local $any anyref) - ;; create a simple $struct, store it in an anyref - (local.set $any - (struct.new_default_with_rtt $struct (rtt.canon $struct)) - ) - (drop - (block $any (result (ref null any)) - (call $log (i32.const 1)) - (drop - ;; try to cast our simple $struct to an extended, which will fail, and - ;; so we will branch, skipping the next logging. - (br_on_cast_fail $any - (local.get $any) - (rtt.canon $extendedstruct) - ) - ) - (call $log (i32.const 999)) ;; we should skip this - (ref.null any) - ) - ) - ) - (func "br_on_failed_cast-2" - (local $any anyref) - ;; create an $extendedstruct, store it in an anyref - (local.set $any - (struct.new_default_with_rtt $extendedstruct (rtt.canon $extendedstruct)) - ) - (drop - (block $any (result (ref null any)) - (call $log (i32.const 1)) - (drop - ;; try to cast our simple $struct to an extended, which will succeed, and - ;; so we will continue to the next logging. - (br_on_cast_fail $any - (local.get $any) - (rtt.canon $extendedstruct) - ) - ) - (call $log (i32.const 999)) - (ref.null any) - ) - ) - ) - (func "cast-null-anyref-to-gc" - ;; a null anyref is a literal which is not even of GC data, as it's not an - ;; array or a struct, so our casting code should not assume it is. it is ok - ;; to try to cast it, and the result should be 0. - (call $log - (ref.test - (ref.null any) - (rtt.canon $struct) - ) - ) - ) - (func $get_data (result dataref) - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - (func "br_on_data" (param $x anyref) - (local $y anyref) - (drop - (block $data (result dataref) - (local.set $y - (br_on_data $data (local.get $x)) - ) - (call $log (i32.const 1)) - (call $get_data) - ) - ) - ) - (func "br_on_non_data-null" - (local $x anyref) - (drop - (block $any (result anyref) - (drop - (br_on_non_data $any (local.get $x)) - ) - ;; $x is a null, and so it is not data, and the branch will be taken, and no - ;; logging will occur. - (call $log (i32.const 1)) - (ref.null any) - ) - ) - ) - (func "br_on_non_data-data" - (local $x anyref) - ;; set x to valid data - (local.set $x - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - (drop - (block $any (result anyref) - (drop - (br_on_non_data $any (local.get $x)) - ) - ;; $x refers to valid data, and so we will not branch, and will log. - (call $log (i32.const 1)) - (ref.null any) - ) - ) - ) - (func "br_on_non_data-other" - (local $x anyref) - ;; set x to something that is not null, but also not data - (local.set $x - (ref.func $a-void-func) - ) - (drop - (block $any (result anyref) - (drop - (br_on_non_data $any (local.get $x)) - ) - ;; $x refers to a function, so we will branch, and not log - (call $log (i32.const 1)) - (ref.null any) - ) - ) - ) - (func "br-on_non_null" - (drop - (block $non-null (result (ref any)) - (br_on_non_null $non-null (ref.func $a-void-func)) - ;; $x refers to a function, which is not null, so we will branch, and not - ;; log - (call $log (i32.const 1)) - (unreachable) - ) - ) - ) - (func "br-on_non_null-2" - (drop - (block $non-null (result (ref any)) - (br_on_non_null $non-null (ref.null any)) - ;; $x is null, and so we will not branch, and log and then trap - (call $log (i32.const 1)) + (br_on_cast $never $extendedstruct (ref.null $struct) (unreachable)) (unreachable) ) ) ) - (func "ref-as-data-of-func" - (drop - ;; This should trap. - (ref.as_data - (ref.func $0) - ) - ) - ) - (func "ref-as-data-of-data" - (drop - (ref.as_data - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ) - ) - (func "ref-as-func-of-data" - (drop - ;; This should trap. - (ref.as_func - (struct.new_default_with_rtt $struct - (rtt.canon $struct) - ) - ) - ) - ) - (func "ref-as-func-of-func" - (drop - (ref.as_func - (ref.func $0) - ) - ) - ) - (func $a-void-func - (call $log (i32.const 1337)) - ) - (func "rtt-and-cast-on-func" - (call $log (i32.const 0)) - (drop - (rtt.canon $void_func) - ) - (call $log (i32.const 1)) - (drop - (rtt.canon $int_func) - ) - (call $log (i32.const 2)) - ;; a valid cast - (call_ref - (ref.cast (ref.func $a-void-func) (rtt.canon $void_func)) - ) - (call $log (i32.const 3)) - ;; an invalid cast - (drop (call_ref - (ref.cast (ref.func $a-void-func) (rtt.canon $int_func)) - )) - ;; will never be reached - (call $log (i32.const 4)) - ) - (func "array-alloc-failure" - (drop - (array.new_default_with_rtt $bytes - (i32.const -1) ;; un-allocatable size (4GB * sizeof(Literal)) - (rtt.canon $bytes) - ) - ) - ) - (func "init-array-packed" (result i32) - (local $x (ref null $bytes)) - (local.set $x - (array.new_with_rtt $bytes - (i32.const -43) ;; initialize the i8 values with a negative i32 - (i32.const 50) - (rtt.canon $bytes) - ) - ) - ;; read the value, which should be -43 & 255 ==> 213 - (array.get_u $bytes - (local.get $x) - (i32.const 10) - ) - ) - (func $call-target (param $0 eqref) - (nop) - ) - (func "cast-func-to-struct" - (drop - ;; An impossible cast of a function to a struct, which should fail. - (ref.cast - (ref.func $call-target) - (rtt.canon $struct) - ) - ) - ) - (func "array-copy" - (local $x (ref null $bytes)) - (local $y (ref null $bytes)) - ;; Create an array of 10's, of size 100. - (local.set $x - (array.new_with_rtt $bytes - (i32.const 10) - (i32.const 100) - (rtt.canon $bytes) - ) - ) - ;; Create an array of zeros of size 200, and also set one index there. - (local.set $y - (array.new_default_with_rtt $bytes - (i32.const 200) - (rtt.canon $bytes) - ) - ) - (array.set $bytes - (local.get $y) - (i32.const 42) - (i32.const 99) - ) - ;; Log out a value from $x before. - (call $log - (array.get_u $bytes (local.get $x) (i32.const 10)) - ) - (array.copy $bytes $bytes - (local.get $x) - (i32.const 10) - (local.get $y) - (i32.const 42) - (i32.const 2) - ) - ;; Log out some value from $x after. Indexes 10 and 11 should be modified. - (call $log - (array.get_u $bytes (local.get $x) (i32.const 9)) - ) - (call $log - (array.get_u $bytes (local.get $x) (i32.const 10)) - ) - (call $log - (array.get_u $bytes (local.get $x) (i32.const 11)) - ) - (call $log - (array.get_u $bytes (local.get $x) (i32.const 12)) - ) - ) - (func "rtt_Fresh" - ;; Casting to the same sequence of rtt.subs works. - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (rtt.sub $extendedstruct - (rtt.canon $struct) - ) - ) - (rtt.sub $extendedstruct - (rtt.canon $struct) - ) - ) - ) - ;; But not with fresh! - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (rtt.sub $extendedstruct - (rtt.canon $struct) - ) - ) - (rtt.fresh_sub $extendedstruct - (rtt.canon $struct) - ) - ) - ) - ;; Casts with fresh succeed, if we use the same fresh rtt. - (global.set $rtt - (rtt.fresh_sub $extendedstruct - (rtt.canon $struct) - ) - ) - (call $log - (ref.test - (struct.new_default_with_rtt $extendedstruct - (global.get $rtt) - ) - (global.get $rtt) - ) - ) - ) - (func "array.init" - (local $x (ref null $bytes)) - (local.set $x - (array.init $bytes - (i32.const 42) ;; first value - (i32.const 50) ;; second value - (rtt.canon $bytes) - ) - ) - ;; The length should be 2 - (call $log - (array.len $bytes (local.get $x)) - ) - ;; The first value should be 42 - (call $log - (array.get_u $bytes (local.get $x) (i32.const 0)) - ) - ;; The second value should be 50 - (call $log - (array.get_u $bytes (local.get $x) (i32.const 1)) - ) - ) - (func "array.init-packed" - (local $x (ref null $bytes)) - (local.set $x - (array.init $bytes - (i32.const -11512) - (rtt.canon $bytes) - ) - ) - ;; The value should be be -11512 & 255 => 8 - (call $log - (array.get_u $bytes (local.get $x) (i32.const 0)) - ) - ) - (func "static-casts" - ;; Casting null returns null. - (call $log (ref.is_null - (ref.cast_static $struct (ref.null $struct)) - )) - ;; Testing null returns 0. - (call $log - (ref.test_static $struct (ref.null $struct)) - ) - ;; Testing something completely wrong (struct vs array) returns 0. - (call $log - (ref.test_static $struct - (array.new $bytes - (i32.const 20) - (i32.const 10) - ) - ) - ) - ;; Testing a thing with the same type returns 1. - (call $log - (ref.test_static $struct - (struct.new_default $struct) - ) - ) - ;; A bad downcast returns 0: we create a struct, which is not a extendedstruct. - (call $log - (ref.test_static $extendedstruct - (struct.new_default $struct) - ) - ) - ;; Casting to a supertype does not work because the canonical RTT for the - ;; subtype is not a sub-rtt of the canonical RTT of the supertype in - ;; structural mode. - (call $log - (ref.test_static $struct - (struct.new_default $extendedstruct) - ) - ) - ) - (func "static-br_on_cast" - (local $any anyref) - ;; create a simple $struct, store it in an anyref - (local.set $any - (struct.new_default $struct) - ) - (drop - (block $block (result ($ref $struct)) - (drop - (block $extendedblock (result (ref $extendedstruct)) - (drop - ;; second, try to cast our simple $struct to what it is, which will work - (br_on_cast_static $block $struct - ;; first, try to cast our simple $struct to an extended, which will fail - (br_on_cast_static $extendedblock $extendedstruct - (local.get $any) - ) - ) - ) - (call $log (i32.const -1)) ;; we should never get here - (return) - ) - ) - (call $log (i32.const -2)) ;; we should never get here either - (return) - ) - ) - (call $log (i32.const 3)) ;; we should get here - ) - (func "static-br_on_cast_fail" - (local $any anyref) - ;; create a simple $struct, store it in an anyref - (local.set $any - (struct.new_default $struct) - ) - (drop - (block $failblock (result anyref) - (drop - ;; try to cast our simple $struct to an extended, which will fail - (br_on_cast_static_fail $failblock $extendedstruct - (local.get $any) - ) - ) - (call $log (i32.const -1)) ;; we should never get here - (return) - ) - ) - (call $log (i32.const -2)) ;; we should get here. - (return) - ) -) -(module - (type $[mut:i8] (array (mut i8))) - (func "foo" (result i32) - ;; before opts this will trap on failing to allocate -1 >>> 0 bytes. after - ;; opts the unused value is removed so there is no trap, and a value is - ;; returned, which should not confuse the fuzzer. - (drop - (array.new_default_with_rtt $[mut:i8] - (i32.const -1) - (rtt.canon $[mut:i8]) - ) - ) - (i32.const 0) - ) ) diff -Nru binaryen-108/test/passes/Oz.txt binaryen-99/test/passes/Oz.txt --- binaryen-108/test/passes/Oz.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/Oz.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,50 @@ +(module + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (memory $0 100 100) + (export "localcse" (func $basics)) + (export "localcse-2" (func $8)) + (func $basics (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (i32.add + (local.get $0) + (local.get $1) + ) + (i32.add + (local.get $0) + (local.get $1) + ) + ) + ) + (func $8 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + (i32.store + (local.tee $0 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.and + (i32.load + (local.get $0) + ) + (i32.const -75) + ) + ) + (i32.store + (local.tee $0 + (i32.add + (local.get $1) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.const 0) + ) +) diff -Nru binaryen-108/test/passes/Oz.wast binaryen-99/test/passes/Oz.wast --- binaryen-108/test/passes/Oz.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/Oz.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,59 @@ +(module + (memory 100 100) + (func $basics (export "localcse") (param $x i32) ($param $y i32) (result i32) ;; -O3 does localcse + (local $x2 i32) + (local $y2 i32) + (local.set $x2 + (i32.add (local.get $x) (local.get $y)) + ) + (local.set $y2 + (i32.add (local.get $x) (local.get $y)) + ) + (i32.add (local.get $x2) (local.get $y2)) + ) + (func $8 (export "localcse-2") (param $var$0 i32) + (param $var$1 i32) + (param $var$2 i32) + (param $var$3 i32) + (result i32) + (block $label$0 (result i32) + (i32.store + (local.tee $var$2 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (i32.and + (i32.load + (local.get $var$2) + ) + (i32.xor + (local.tee $var$2 + (i32.const 74) + ) + (i32.const -1) + ) + ) + ) + (i32.store + (local.tee $var$1 + (i32.add + (local.get $var$1) + (i32.const 4) + ) + ) + (i32.or + (i32.load + (local.get $var$1) + ) + (i32.and + (local.get $var$2) + (i32.const 8) + ) + ) + ) + (i32.const 0) + ) + ) +) diff -Nru binaryen-108/test/passes/post-assemblyscript-finalize.txt binaryen-99/test/passes/post-assemblyscript-finalize.txt --- binaryen-108/test/passes/post-assemblyscript-finalize.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/post-assemblyscript-finalize.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,40 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (import "rt" "retain" (func $~lib/rt/pure/__retain (param i32) (result i32))) + (import "rt" "release" (func $~lib/rt/pure/__release (param i32))) + (import "rt" "alloc" (func $~lib/rt/tlsf/__alloc (param i32 i32) (result i32))) + (func $eliminates.unnecessaryAllocation + (nop) + ) + (func $eliminates.unnecessaryPair (param $0 i32) + (drop + (local.get $0) + ) + ) + (func $eliminates.unnecessaryStaticPair + (nop) + ) + (func $eliminates.unnecessaryStaticRetain + (drop + (i32.const 272) + ) + ) + (func $eliminates.unnecessaryStaticRelease + (nop) + ) + (func $keeps.dynamicRetain (param $0 i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (func $keeps.dynamicRelease (param $0 i32) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/post-assemblyscript-finalize.wast binaryen-99/test/passes/post-assemblyscript-finalize.wast --- binaryen-108/test/passes/post-assemblyscript-finalize.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/post-assemblyscript-finalize.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,54 @@ +;; FinalizeARC part of assemblyscript/tests/compiler/rc/optimize +(module + (import "rt" "retain" (func $~lib/rt/pure/__retain (param i32) (result i32))) + (import "rt" "release" (func $~lib/rt/pure/__release (param i32))) + (import "rt" "alloc" (func $~lib/rt/tlsf/__alloc (param i32) (param i32) (result i32))) + (func $eliminates.unnecessaryAllocation + (call $~lib/rt/pure/__release + (call $~lib/rt/pure/__retain + (call $~lib/rt/tlsf/__alloc + (i32.const 1) + (i32.const 0) + ) + ) + ) + ) + (func $eliminates.unnecessaryPair (param $0 i32) + (call $~lib/rt/pure/__release + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (func $eliminates.unnecessaryStaticPair + (call $~lib/rt/pure/__release + (call $~lib/rt/pure/__retain + (i32.const 272) + ) + ) + ) + (func $eliminates.unnecessaryStaticRetain + (drop + (call $~lib/rt/pure/__retain + (i32.const 272) + ) + ) + ) + (func $eliminates.unnecessaryStaticRelease + (call $~lib/rt/pure/__release + (i32.const 272) + ) + ) + (func $keeps.dynamicRetain (param $0 i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (func $keeps.dynamicRelease (param $0 i32) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) +) diff -Nru binaryen-108/test/passes/post-assemblyscript.txt binaryen-99/test/passes/post-assemblyscript.txt --- binaryen-108/test/passes/post-assemblyscript.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/post-assemblyscript.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,263 @@ +(module + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (import "rt" "retain" (func $~lib/rt/pure/__retain (param i32) (result i32))) + (import "rt" "release" (func $~lib/rt/pure/__release (param i32))) + (import "rc" "getRetainedRef" (func $getRetainedRef (result i32))) + (func $eliminates.linearArgument (param $0 i32) + (local.set $0 + (local.get $0) + ) + (nop) + ) + (func $eliminates.linearLocal (param $0 i32) + (local $1 i32) + (local.set $1 + (local.get $0) + ) + (nop) + ) + (func $eliminates.linearChain (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local.set $1 + (local.get $0) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $2) + ) + (nop) + (nop) + (nop) + ) + (func $eliminates.balancedReleases (param $0 i32) (param $cond i32) + (local $2 i32) + (local.set $2 + (local.get $0) + ) + (if + (local.get $cond) + (nop) + (nop) + ) + ) + (func $eliminates.partialReleases (param $0 i32) (param $cond i32) + (local $2 i32) + (local.set $2 + (local.get $0) + ) + (if + (local.get $cond) + (nop) + ) + ) + (func $eliminates.balancedRetains (param $0 i32) (param $cond1 i32) (param $cond2 i32) + (local $3 i32) + (if + (local.get $cond1) + (if + (local.get $cond2) + (local.set $3 + (local.get $0) + ) + (local.set $3 + (local.get $0) + ) + ) + (local.set $3 + (local.get $0) + ) + ) + (nop) + ) + (func $eliminates.balancedInsideLoop (param $0 i32) (param $cond i32) + (local $flat i32) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (local.set $0 + (local.get $0) + ) + (nop) + (br $continue|0) + ) + (unreachable) + ) + ) + (func $eliminates.balancedOutsideLoop (param $0 i32) (param $cond i32) + (local $flat i32) + (local.set $0 + (local.get $0) + ) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (br $continue|0) + ) + (unreachable) + ) + (nop) + ) + (func $eliminates.balancedInsideOutsideLoop (param $0 i32) (param $cond i32) + (local $flat i32) + (local.set $0 + (local.get $0) + ) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (nop) + (local.set $0 + (local.get $0) + ) + (br $continue|0) + ) + (unreachable) + ) + (nop) + ) + (func $eliminates.balancedInsideOutsideLoopWithBranch (param $0 i32) (param $cond1 i32) (param $cond2 i32) + (local $flat i32) + (local.set $0 + (local.get $0) + ) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond1) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (if + (local.get $cond2) + (block $block + (nop) + (return) + ) + ) + (nop) + (local.set $0 + (local.get $0) + ) + (br $continue|0) + ) + (unreachable) + ) + (nop) + ) + (func $eliminates.replace (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local.set $0 + (local.get $0) + ) + (local.set $1 + (local.get $1) + ) + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + (if + (i32.ne + (local.get $2) + (local.get $3) + ) + (local.set $2 + (local.get $2) + ) + (nop) + ) + (local.set $0 + (local.get $2) + ) + (nop) + (nop) + ) + (func $eliminates.replaceAlreadyRetained (param $0 i32) (result i32) + (local $1 i32) + (block $block + (local.set $0 + (local.get $0) + ) + (local.set $1 + (call $getRetainedRef) + ) + (nop) + (local.set $0 + (local.get $1) + ) + (return + (local.get $0) + ) + ) + ) + (func $keeps.partialRetains (param $0 i32) (param $cond i32) + (if + (local.get $cond) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) + (func $keeps.reachesReturn (param $0 i32) (param $cond i32) (result i32) + (block $block + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (if + (local.get $cond) + (return + (local.get $0) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (return + (i32.const 0) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/post-assemblyscript.wast binaryen-99/test/passes/post-assemblyscript.wast --- binaryen-108/test/passes/post-assemblyscript.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/post-assemblyscript.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,342 @@ +;; OptimizeARC part of assemblyscript/tests/compiler/rc/optimize +;; with flattening applied manually +(module + (import "rt" "retain" (func $~lib/rt/pure/__retain (param i32) (result i32))) + (import "rt" "release" (func $~lib/rt/pure/__release (param i32))) + (func $eliminates.linearArgument (param $0 i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) + (func $eliminates.linearLocal (param $0 i32) + (local $1 i32) + (local.set $1 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (call $~lib/rt/pure/__release + (local.get $1) + ) + ) + (func $eliminates.linearChain (param $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local.set $1 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (local.set $2 + (call $~lib/rt/pure/__retain + (local.get $1) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $2) + ) + ) + (call $~lib/rt/pure/__release + (local.get $3) + ) + (call $~lib/rt/pure/__release + (local.get $2) + ) + (call $~lib/rt/pure/__release + (local.get $1) + ) + ) + (func $eliminates.balancedReleases (param $0 i32) (param $cond i32) + (local $2 i32) + (local.set $2 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (if + (local.get $cond) + (call $~lib/rt/pure/__release + (local.get $2) + ) + (call $~lib/rt/pure/__release + (local.get $2) + ) + ) + ) + (func $eliminates.partialReleases (param $0 i32) (param $cond i32) + ;; technically invalid but assumed to be never emitted + (local $2 i32) + (local.set $2 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (if + (local.get $cond) + (call $~lib/rt/pure/__release + (local.get $2) + ) + ) + ) + (func $eliminates.balancedRetains (param $0 i32) (param $cond1 i32) (param $cond2 i32) + (local $3 i32) + (if + (local.get $cond1) + (if + (local.get $cond2) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (call $~lib/rt/pure/__release + (local.get $3) + ) + ) + (func $eliminates.balancedInsideLoop (param $0 i32) (param $cond i32) + (local $flat i32) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (br $continue|0) + ) + (unreachable) + ) + ) + (func $eliminates.balancedOutsideLoop (param $0 i32) (param $cond i32) + (local $flat i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (br $continue|0) + ) + (unreachable) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) + (func $eliminates.balancedInsideOutsideLoop (param $0 i32) (param $cond i32) + (local $flat i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (br $continue|0) + ) + (unreachable) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) + (func $eliminates.balancedInsideOutsideLoopWithBranch (param $0 i32) (param $cond1 i32) (param $cond2 i32) + (local $flat i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (block $break|0 + (loop $continue|0 + (local.set $flat + (i32.eqz + (local.get $cond1) + ) + ) + (br_if $break|0 + (local.get $flat) + ) + (if + (local.get $cond2) + (block + (call $~lib/rt/pure/__release + (local.get $0) + ) + (return) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (br $continue|0) + ) + (unreachable) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) + (func $eliminates.replace (param $0 i32) (param $1 i32) + (local $2 i32) + (local $3 i32) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (local.set $1 + (call $~lib/rt/pure/__retain + (local.get $1) + ) + ) + ;; flat + (local.set $2 + (local.get $1) + ) + (local.set $3 + (local.get $0) + ) + ;; /flat + (if + (i32.ne + (local.get $2) ;; flat (local.tee $2 (local.get $1)) + (local.get $3) ;; flat (local.tee $3 (local.get $0)) + ) + (local.set $2 + (call $~lib/rt/pure/__retain + (local.get $2) + ) + ) + (call $~lib/rt/pure/__release + (local.get $3) + ) + ) + (local.set $0 + (local.get $2) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (call $~lib/rt/pure/__release + (local.get $1) + ) + ) + (import "rc" "getRetainedRef" (func $getRetainedRef (result i32))) + (func $eliminates.replaceAlreadyRetained (param $0 i32) (result i32) + (local $1 i32) + (block + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (local.set $1 + (call $getRetainedRef) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (local.set $0 + (local.get $1) + ) + (return + (local.get $0) + ) + ) + ) + (func $keeps.partialRetains (param $0 i32) (param $cond i32) + (if + (local.get $cond) + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + ) + (func $keeps.reachesReturn (param $0 i32) (param $cond i32) (result i32) + (block + (local.set $0 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (if + (local.get $cond) + (return + (local.get $0) + ) + ) + (call $~lib/rt/pure/__release + (local.get $0) + ) + (return + (i32.const 0) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/post-emscripten.txt binaryen-99/test/passes/post-emscripten.txt --- binaryen-108/test/passes/post-emscripten.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/post-emscripten.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,11 +1,14 @@ (module (type $i32_f32_=>_none (func (param i32 f32))) - (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) (type $none_=>_none (func)) + (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) (import "env" "invoke_vif" (func $invoke_vif (param i32 i32 f32))) (memory $0 256 256) (table $0 7 7 funcref) - (elem (i32.const 1) $exc $other_safe $other_unsafe $deep_safe $deep_unsafe) + (elem (i32.const 0) $f1 $exc $other_safe $other_unsafe $deep_safe $deep_unsafe) + (func $f1 + (nop) + ) (func $exc (call $other_safe (i32.const 42) @@ -31,16 +34,6 @@ (i32.const 42) (f32.const 3.141590118408203) ) - (call $invoke_vif - (i32.const 0) - (i32.const 42) - (f32.const 3.141590118408203) - ) - (call $invoke_vif - (i32.const 1337) - (i32.const 42) - (f32.const 3.141590118408203) - ) ) (func $other_safe (param $0 i32) (param $1 f32) (nop) @@ -68,8 +61,8 @@ ) ) (module - (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) (type $none_=>_none (func)) + (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) (type $i32_f32_=>_none (func (param i32 f32))) (import "env" "glob" (global $glob i32)) (import "env" "invoke_vif" (func $invoke_vif (param i32 i32 f32))) diff -Nru binaryen-108/test/passes/post-emscripten.wast binaryen-99/test/passes/post-emscripten.wast --- binaryen-108/test/passes/post-emscripten.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/post-emscripten.wast 2021-01-07 20:01:06.000000000 +0000 @@ -3,7 +3,8 @@ (import "env" "invoke_vif" (func $invoke_vif (param i32 i32 f32))) (memory 256 256) (table 7 7 funcref) - (elem (i32.const 1) $exc $other_safe $other_unsafe $deep_safe $deep_unsafe) + (elem (i32.const 0) $f1 $exc $other_safe $other_unsafe $deep_safe $deep_unsafe) + (func $f1) (func $exc (call $invoke_vif (i32.const 2) ;; other_safe() @@ -30,18 +31,6 @@ (i32.const 42) (f32.const 3.14159) ) - ;; there is no function at index 0, so this cannot be optimized - (call $invoke_vif - (i32.const 0) - (i32.const 42) - (f32.const 3.14159) - ) - ;; there is no function at index 1337, so this cannot be optimized - (call $invoke_vif - (i32.const 1337) - (i32.const 42) - (f32.const 3.14159) - ) ) (func $other_safe (param i32) (param f32) ) diff -Nru binaryen-108/test/passes/precompute_all-features.txt binaryen-99/test/passes/precompute_all-features.txt --- binaryen-108/test/passes/precompute_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/precompute_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -2,15 +2,15 @@ (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (type $none_=>_f64 (func (result f64))) - (type $0 (func (param i32))) (type $none_=>_v128 (func (result v128))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_externref (func (result externref))) (type $none_=>_i32_i64 (func (result i32 i64))) - (type $none_=>_anyref (func (result anyref))) + (memory $0 512 512) + (data (i32.const 0) "passive") (global $global i32 (i32.const 1)) (global $global-mut (mut i32) (i32.const 2)) - (memory $0 512 512) - (data (i32.const 0) "hello!") - (elem declare func $dummy) + (event $event$0 (attr 0) (param)) (func $x (param $x i32) (call $x (i32.const 2300) @@ -217,8 +217,17 @@ (i32.const 2) ) ) - (func $simd-precompute (result v128) - (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) + (func $no-simd-precompute (result v128) + (i32x4.splat + (i32.const 0) + ) + ) + (func $no-simd-precompute-if (result v128) + (return + (i32x4.splat + (i32.const 0) + ) + ) ) (func $no-memory-init-precompute (memory.init 0 @@ -253,8 +262,8 @@ (func $loop-precompute (result i32) (i32.const 1) ) - (func $reftype-test (result anyref) - (ref.null any) + (func $reftype-test (result externref) + (ref.null extern) ) (func $dummy (nop) @@ -276,18 +285,18 @@ ) ) (drop - (block $l2 (result anyref) + (block $l2 (result externref) (drop (block $l3 (global.set $global-mut (i32.const 1) ) (br $l2 - (ref.null any) + (ref.null extern) ) ) ) - (ref.null any) + (ref.null extern) ) ) (drop @@ -306,4 +315,13 @@ ) ) ) + (func $unreachable-br_on_exn + (block $label$1 + (drop + (loop $label$2 + (br $label$2) + ) + ) + ) + ) ) diff -Nru binaryen-108/test/passes/precompute_all-features.wast binaryen-99/test/passes/precompute_all-features.wast --- binaryen-108/test/passes/precompute_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/precompute_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module (memory 512 512 - (data "hello!") + (data passive "hello!") ) (type $0 (func (param i32))) (global $global i32 (i32.const 1)) @@ -324,11 +324,18 @@ ) ) ) - (func $simd-precompute (result v128) + (func $no-simd-precompute (result v128) (i32x4.splat (i32.const 0) ) ) + (func $no-simd-precompute-if (result v128) + (return + (i32x4.splat + (i32.const 0) + ) + ) + ) (func $no-memory-init-precompute (memory.init 0 (i32.const 512) @@ -454,4 +461,19 @@ ) ) ) + + ;; br_on_exn's argument becomes unreachable, so br_on_exn itself is replaced + ;; with its argument in ReFinalize process after precompute. + (event $event$0 (attr 0) (param)) + (func $unreachable-br_on_exn + (block $label$1 + (drop + (br_on_exn $label$1 $event$0 + (loop $label$2 (result exnref) + (br $label$2) + ) + ) + ) + ) + ) ) diff -Nru binaryen-108/test/passes/precompute-propagate_all-features.txt binaryen-99/test/passes/precompute-propagate_all-features.txt --- binaryen-108/test/passes/precompute-propagate_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/precompute-propagate_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -240,12 +240,7 @@ (func $multipass (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (local $3 i32) (nop) - (if - (local.get $3) - (local.set $2 - (i32.const 0) - ) - ) + (nop) (local.get $2) ) (func $through-fallthrough (param $x i32) (param $y i32) (result i32) @@ -264,7 +259,7 @@ (func $simd-load (result v128) (local $x v128) (local.set $x - (v128.load8_splat + (v8x16.load_splat (i32.const 0) ) ) diff -Nru binaryen-108/test/passes/precompute-propagate_all-features.wast binaryen-99/test/passes/precompute-propagate_all-features.wast --- binaryen-108/test/passes/precompute-propagate_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/precompute-propagate_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -141,12 +141,7 @@ (func $multipass (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (local $3 i32) (if - (local.get $3) ;; this will be precomputed to 0. after that, the if will be - ;; precomputed to not exist at all. removing the set in the - ;; if body then allows us to optimize the value of $3 in the - ;; if lower down, but we do not do an additional cycle of - ;; this pass automatically as such things are fairly rare, - ;; so that opportunity remains unoptimized in this test. + (local.get $3) (local.set $3 ;; this set is completely removed, allowing later opts (i32.const 24) ) @@ -177,7 +172,7 @@ ) (func $simd-load (result v128) (local $x v128) - (local.set $x (v128.load8_splat (i32.const 0))) + (local.set $x (v8x16.load_splat (i32.const 0))) (local.get $x) ) (func $tuple-local (result i32 i64) diff -Nru binaryen-108/test/passes/print.bin.txt binaryen-99/test/passes/print.bin.txt --- binaryen-108/test/passes/print.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/print.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (global $global$0 (mut i32) (i32.const 5243904)) (global $global$1 i32 (i32.const 1024)) @@ -92,9 +92,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (global $global$0 (mut i32) (i32.const 5243904)) (global $global$1 i32 (i32.const 1024)) diff -Nru binaryen-108/test/passes/print-call-graph.txt binaryen-99/test/passes/print-call-graph.txt --- binaryen-108/test/passes/print-call-graph.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/print-call-graph.txt 2021-01-07 20:01:06.000000000 +0000 @@ -112,17 +112,18 @@ "b3" [style="filled, rounded"]; } (module - (type $FUNCSIG$vi (func (param i32))) - (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) - (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$v (func)) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) (import "env" "memory" (memory $0 256 256)) (data (global.get $memoryBase) "\05\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00\b0\04\00\00\00\04\00\00\00\00\00\00\00\00\00\00\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\n\ff\ff\ff\ff\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\04") (import "env" "table" (table $timport$0 9 9 funcref)) + (elem (i32.const 0) $b0 $___stdio_close $b1 $___stdout_write $___stdio_seek $___stdio_write $b2 $_cleanup_387 $b3) (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) (import "env" "STACK_MAX" (global $STACK_MAX$asm2wasm$import i32)) (import "env" "ABORT" (global $ABORT$asm2wasm$import i32)) @@ -161,7 +162,6 @@ (global $tempRet0 (mut i32) (i32.const 0)) (global $tempFloat (mut f32) (f32.const 0)) (global $f0 (mut f32) (f32.const 0)) - (elem (i32.const 0) $b0 $___stdio_close $b1 $___stdout_write $___stdio_seek $___stdio_write $b2 $_cleanup_387 $b3) (export "_fflush" (func $_fflush)) (export "_main" (func $_main)) (export "_pthread_self" (func $_pthread_self)) @@ -979,7 +979,7 @@ ) ) (drop - (call_indirect (type $FUNCSIG$iiii) + (call_indirect (type $i32_i32_i32_=>_i32) (local.get $0) (i32.const 0) (i32.const 0) @@ -1027,7 +1027,7 @@ ) ) (drop - (call_indirect (type $FUNCSIG$iiii) + (call_indirect (type $i32_i32_i32_=>_i32) (local.get $0) (i32.sub (local.get $4) @@ -1092,7 +1092,7 @@ (call $__ZSt15get_new_handlerv) ) (block $block - (call_indirect (type $FUNCSIG$v) + (call_indirect (type $none_=>_none) (i32.add (i32.and (local.get $0) @@ -1420,7 +1420,7 @@ (i32.const 0) ) (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - (call_indirect (type $FUNCSIG$ii) + (call_indirect (type $i32_=>_i32) (local.get $1) (i32.add (i32.and @@ -1432,7 +1432,7 @@ ) ) (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect (type $FUNCSIG$iiii) + (call_indirect (type $i32_i32_i32_=>_i32) (local.get $1) (local.get $2) (local.get $3) @@ -1446,7 +1446,7 @@ ) ) (func $dynCall_vi (param $0 i32) (param $1 i32) - (call_indirect (type $FUNCSIG$vi) + (call_indirect (type $i32_=>_none) (local.get $1) (i32.add (i32.and @@ -1458,7 +1458,7 @@ ) ) (func $dynCall_v (param $0 i32) - (call_indirect (type $FUNCSIG$v) + (call_indirect (type $none_=>_none) (i32.add (i32.and (local.get $0) diff -Nru binaryen-108/test/passes/print_g.bin.txt binaryen-99/test/passes/print_g.bin.txt --- binaryen-108/test/passes/print_g.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/print_g.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (global $global$0 (mut i32) (i32.const 5243904)) (global $global$1 i32 (i32.const 1024)) @@ -131,9 +131,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (global $global$0 (mut i32) (i32.const 5243904)) (global $global$1 i32 (i32.const 1024)) diff -Nru binaryen-108/test/passes/print_g_metrics.bin.txt binaryen-99/test/passes/print_g_metrics.bin.txt --- binaryen-108/test/passes/print_g_metrics.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/print_g_metrics.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module + (type $none_=>_none (func)) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_none (func)) (global $global$0 (mut i32) (i32.const 5243904)) (export "a" (func $__wasm_call_ctors)) (export "b" (func $main)) @@ -65,29 +65,28 @@ ) ) total + [events] : 0 [exports] : 3 [funcs] : 3 [globals] : 1 [imports] : 0 - [tables] : 0 - [tags] : 0 [total] : 37 [vars] : 0 - Binary : 11 - Block : 2 - Break : 1 - Const : 8 - GlobalGet : 1 - GlobalSet : 1 - If : 1 - LocalGet : 8 - LocalSet : 2 - Loop : 1 - Nop : 1 + binary : 11 + block : 2 + break : 1 + const : 8 + global.get : 1 + global.set : 1 + if : 1 + local.get : 8 + local.set : 2 + loop : 1 + nop : 1 (module + (type $none_=>_none (func)) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_none (func)) (global $global$0 (mut i32) (i32.const 5243904)) (export "a" (func $__wasm_call_ctors)) (export "b" (func $main)) diff -Nru binaryen-108/test/passes/print_g_strip-dwarf.bin.txt binaryen-99/test/passes/print_g_strip-dwarf.bin.txt --- binaryen-108/test/passes/print_g_strip-dwarf.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/print_g_strip-dwarf.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (global $global$0 (mut i32) (i32.const 5243904)) (global $global$1 i32 (i32.const 1024)) @@ -92,9 +92,9 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "memory" (memory $mimport$0 256 256)) (global $global$0 (mut i32) (i32.const 5243904)) (global $global$1 i32 (i32.const 1024)) diff -Nru binaryen-108/test/passes/remove-imports.txt binaryen-99/test/passes/remove-imports.txt --- binaryen-108/test/passes/remove-imports.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-imports.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,10 +1,10 @@ (module - (type $FUNCSIG$v (func)) + (type $none_=>_none (func)) (import "env" "table" (table $table 1 1 funcref)) + (elem (i32.const 0) $waka-sneaky) (import "env" "memBase" (global $gimport$0 i32)) (import "somewhere" "waka-sneaky" (func $waka-sneaky)) (memory $0 1024 1024) - (elem (i32.const 0) $waka-sneaky) (func $nada (nop) (drop @@ -13,7 +13,7 @@ (drop (f64.const 0) ) - (call_indirect (type $FUNCSIG$v) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) diff -Nru binaryen-108/test/passes/remove-non-js-ops.txt binaryen-99/test/passes/remove-non-js-ops.txt --- binaryen-108/test/passes/remove-non-js-ops.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-non-js-ops.txt 2021-01-07 20:01:06.000000000 +0000 @@ -2,21 +2,21 @@ (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $f64_=>_f64 (func (param f64) (result f64))) (type $f32_=>_f32 (func (param f32) (result f32))) + (type $f64_=>_f64 (func (param f64) (result f64))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $f64_f64_=>_f64 (func (param f64 f64) (result f64))) - (type $f32_f32_=>_f32 (func (param f32 f32) (result f32))) - (type $i32_i32_=>_none (func (param i32 i32))) - (type $none_=>_f32 (func (result f32))) + (type $i32_=>_none (func (param i32))) (type $f32_=>_none (func (param f32))) - (type $none_=>_f64 (func (result f64))) (type $f64_=>_none (func (param f64))) + (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) - (type $i32_=>_none (func (param i32))) + (type $none_=>_i32 (func (result i32))) (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) (type $i32_i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32 i32) (result i32))) - (type $none_=>_i32 (func (result i32))) + (type $none_=>_f32 (func (result f32))) + (type $f32_f32_=>_f32 (func (param f32 f32) (result f32))) + (type $none_=>_f64 (func (result f64))) + (type $f64_f64_=>_f64 (func (param f64 f64) (result f64))) (import "env" "wasm2js_scratch_load_i32" (func $wasm2js_scratch_load_i32 (param i32) (result i32))) (import "env" "wasm2js_scratch_store_i32" (func $wasm2js_scratch_store_i32 (param i32 i32))) (import "env" "wasm2js_scratch_load_f32" (func $wasm2js_scratch_load_f32 (result f32))) @@ -30,8 +30,8 @@ (import "env" "wasm2js_atomic_wait_i32" (func $wasm2js_atomic_wait_i32 (param i32 i32 i32 i32) (result i32))) (import "env" "wasm2js_atomic_rmw_i64" (func $wasm2js_atomic_rmw_i64 (param i32 i32 i32 i32 i32 i32) (result i32))) (import "env" "wasm2js_get_stashed_bits" (func $wasm2js_get_stashed_bits (result i32))) - (global $__wasm-intrinsics-temp-i64 (mut i64) (i64.const 0)) (memory $0 1) + (global $__wasm-intrinsics-temp-i64 (mut i64) (i64.const 0)) (func $copysign64 (param $0 f64) (param $1 f64) (result f64) (f64.reinterpret_i64 (i64.or diff -Nru binaryen-108/test/passes/remove-unused-brs_all-features.txt binaryen-99/test/passes/remove-unused-brs_all-features.txt --- binaryen-108/test/passes/remove-unused-brs_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_all-features.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ -(module - (type $vector (array (mut i32))) - (type $struct (struct (field (ref null $vector)))) - (type $ref|func|_=>_none (func (param (ref func)))) - (type $i32_=>_none (func (param i32))) - (type $none_=>_ref?|$struct| (func (result (ref null $struct)))) - (type $none_=>_f64 (func (result f64))) - (type $none_=>_i32 (func (result i32))) - (type $i32_=>_funcref (func (param i32) (result funcref))) - (type $none_=>_none (func)) - (import "out" "log" (func $log (param i32))) - (elem declare func $br_on-to-br $br_on-to-flow $i32_=>_none $none_=>_i32) - (func $foo (result (ref null $struct)) - (if (result (ref null $struct)) - (i32.const 1) - (struct.new_with_rtt $struct - (array.new_default_with_rtt $vector - (i32.const 1) - (rtt.canon $vector) - ) - (rtt.canon $struct) - ) - (ref.null $struct) - ) - ) - (func $test-prefinalize (result f64) - (loop $loop (result f64) - (if (result f64) - (i32.const 1) - (f64.const 0) - (block $block (result f64) - (nop) - (br_if $loop - (i32.eqz - (i32.const 0) - ) - ) - (unreachable) - ) - ) - ) - ) - (func $none_=>_i32 (result i32) - (unreachable) - ) - (func $i32_=>_none (param $0 i32) - (nop) - ) - (func $selectify (param $x i32) (result funcref) - (select (result funcref) - (ref.func $none_=>_i32) - (ref.func $i32_=>_none) - (local.get $x) - ) - ) - (func $br_on-to-br (param $func (ref func)) - (call $log - (i32.const 0) - ) - (block $null - (drop - (ref.func $br_on-to-br) - ) - (call $log - (i32.const 1) - ) - ) - (call $log - (i32.const 2) - ) - (drop - (block $func (result (ref $ref|func|_=>_none)) - (drop - (br $func - (ref.func $br_on-to-br) - ) - ) - (call $log - (i32.const 3) - ) - (ref.func $br_on-to-br) - ) - ) - (call $log - (i32.const 4) - ) - (drop - (block $data (result (ref $vector)) - (drop - (br $data - (array.new_default_with_rtt $vector - (i32.const 1) - (rtt.canon $vector) - ) - ) - ) - (call $log - (i32.const 5) - ) - (array.new_default_with_rtt $vector - (i32.const 2) - (rtt.canon $vector) - ) - ) - ) - (call $log - (i32.const 6) - ) - (drop - (block $i31 (result i31ref) - (drop - (br $i31 - (i31.new - (i32.const 42) - ) - ) - ) - (call $log - (i32.const 7) - ) - (i31.new - (i32.const 1337) - ) - ) - ) - (call $log - (i32.const 8) - ) - (drop - (block $non-null (result (ref $ref|func|_=>_none)) - (br $non-null - (ref.func $br_on-to-br) - ) - (call $log - (i32.const 9) - ) - (ref.func $br_on-to-br) - ) - ) - ) - (func $br_on-to-flow - (drop - (block $data (result (ref null data)) - (drop - (ref.func $br_on-to-flow) - ) - (ref.null data) - ) - ) - (drop - (block $datab (result (ref null data)) - (drop - (i31.new - (i32.const 1337) - ) - ) - (ref.null data) - ) - ) - (drop - (block $func (result funcref) - (drop - (array.new_default_with_rtt $vector - (i32.const 2) - (rtt.canon $vector) - ) - ) - (ref.null func) - ) - ) - (drop - (block $funcb (result funcref) - (drop - (i31.new - (i32.const 1337) - ) - ) - (ref.null func) - ) - ) - (drop - (block $i31 (result (ref null i31)) - (drop - (array.new_default_with_rtt $vector - (i32.const 2) - (rtt.canon $vector) - ) - ) - (ref.null i31) - ) - ) - (drop - (block $i31b (result (ref null i31)) - (drop - (ref.func $br_on-to-flow) - ) - (ref.null i31) - ) - ) - ) -) diff -Nru binaryen-108/test/passes/remove-unused-brs_all-features.wast binaryen-99/test/passes/remove-unused-brs_all-features.wast --- binaryen-108/test/passes/remove-unused-brs_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_all-features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -(module - (type $vector (array (mut i32))) - (type $struct (struct (field (ref null $vector)))) - (import "out" "log" (func $log (param i32))) - (func $foo (result (ref null $struct)) - (if (result (ref null $struct)) - (i32.const 1) - (struct.new_with_rtt $struct - ;; regression test for computing the cost of an array.new_default, which - ;; lacks the optional field "init" - (array.new_default_with_rtt $vector - (i32.const 1) - (rtt.canon $vector) - ) - (rtt.canon $struct) - ) - (ref.null $struct) - ) - ) - - (func $test-prefinalize (result f64) - (loop $loop (result f64) - (block $block (result f64) - (drop - (br_if $block - (f64.const 0) - (i32.const 1) - ) - ) - (if - (i32.const 0) - (unreachable) - ) - ;; this will be moved from $block into the if right before it. we must be - ;; careful to properly finalize() things, as if we finalize the block too - ;; early - before the if - then the block ends in a none type, which is - ;; invalid. - (br $loop) - ) - ) - ) - - (func $none_=>_i32 (result i32) - (unreachable) - ) - (func $i32_=>_none (param i32) - ) - (func $selectify (param $x i32) (result funcref) - ;; this if has arms with different function types, for which funcref is the - ;; LUB - (if (result funcref) - (local.get $x) - (ref.func $none_=>_i32) - (ref.func $i32_=>_none) - ) - ) - - (func $br_on-to-br (param $func (ref func)) - (call $log (i32.const 0)) - (block $null - ;; a non-null reference is not null, and the br is never taken - (drop - (br_on_null $null (ref.func $br_on-to-br)) - ) - (call $log (i32.const 1)) - ) - (call $log (i32.const 2)) - (drop - (block $func (result funcref) - ;; a non-null function reference means we always take the br - (drop - (br_on_func $func (ref.func $br_on-to-br)) - ) - (call $log (i32.const 3)) - (ref.func $br_on-to-br) - ) - ) - (call $log (i32.const 4)) - (drop - (block $data (result dataref) - ;; a non-null data reference means we always take the br - (drop - (br_on_data $data - (array.new_default_with_rtt $vector - (i32.const 1) - (rtt.canon $vector) - ) - ) - ) - (call $log (i32.const 5)) - (array.new_default_with_rtt $vector - (i32.const 2) - (rtt.canon $vector) - ) - ) - ) - (call $log (i32.const 6)) - (drop - (block $i31 (result i31ref) - ;; a non-null i31 reference means we always take the br - (drop - (br_on_i31 $i31 - (i31.new (i32.const 42)) - ) - ) - (call $log (i32.const 7)) - (i31.new (i32.const 1337)) - ) - ) - (call $log (i32.const 8)) - (drop - (block $non-null (result (ref func)) - ;; a non-null reference is not null, and the br is always taken - (br_on_non_null $non-null (ref.func $br_on-to-br)) - (call $log (i32.const 9)) - (ref.func $br_on-to-br) - ) - ) - ) - - ;; a br_on of the obviously incorrect kind can just flow out the value as the - ;; break is never taken - (func $br_on-to-flow - ;; brs to data - (drop - (block $data (result (ref null data)) - (drop - (br_on_data $data - (ref.func $br_on-to-flow) - ) - ) - (ref.null data) - ) - ) - (drop - (block $datab (result (ref null data)) - (drop - (br_on_data $datab - (i31.new (i32.const 1337)) - ) - ) - (ref.null data) - ) - ) - ;; brs to func - (drop - (block $func (result (ref null func)) - (drop - (br_on_func $func - (array.new_default_with_rtt $vector - (i32.const 2) - (rtt.canon $vector) - ) - ) - ) - (ref.null func) - ) - ) - (drop - (block $funcb (result (ref null func)) - (drop - (br_on_func $funcb - (i31.new (i32.const 1337)) - ) - ) - (ref.null func) - ) - ) - ;; brs to i31 - (drop - (block $i31 (result (ref null i31)) - (drop - (br_on_i31 $i31 - (array.new_default_with_rtt $vector - (i32.const 2) - (rtt.canon $vector) - ) - ) - ) - (ref.null i31) - ) - ) - (drop - (block $i31b (result (ref null i31)) - (drop - (br_on_i31 $i31b - (ref.func $br_on-to-flow) - ) - ) - (ref.null i31) - ) - ) - ) -) diff -Nru binaryen-108/test/passes/remove-unused-brs_enable-multivalue.txt binaryen-99/test/passes/remove-unused-brs_enable-multivalue.txt --- binaryen-108/test/passes/remove-unused-brs_enable-multivalue.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_enable-multivalue.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,17 +1,17 @@ (module - (type $0 (func (param i32))) - (type $1 (func)) - (type $2 (func (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32_i64 (func (result i32 i64))) (type $none_=>_i64 (func (result i64))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_f64_i32_f64_f32_f32_=>_i32 (func (param i32 f64 i32 f64 f32 f32) (result i32))) (type $f32_i32_f32_i32_i32_f64_f32_=>_i32 (func (param f32 i32 f32 i32 i32 f64 f32) (result i32))) (type $i32_=>_i64 (func (param i32) (result i64))) (type $none_=>_f32 (func (result f32))) (type $i32_=>_f32 (func (param i32) (result f32))) - (type $i32_f64_i32_f64_f32_f32_=>_i32 (func (param i32 f64 i32 f64 f32 f32) (result i32))) (memory $0 256 256) (func $b0-yes (param $i1 i32) (block $topmost @@ -1669,109 +1669,6 @@ ) (unreachable) ) - (func $br-to-table-initial-tee (param $a i32) - (block $x - (block $y - (block $z - (nop) - (nop) - (block $tablify|0 - (br_table $x $y $z $tablify|0 - (i32.sub - (local.tee $a - (i32.add - (i32.const 10) - (i32.const 1) - ) - ) - (i32.const 10) - ) - ) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (func $br-to-table-initial-tee-wrong-index (param $a i32) - (local $b i32) - (block $x - (block $y - (block $z - (br_if $x - (i32.eq - (local.tee $a - (i32.const 99) - ) - (i32.const 10) - ) - ) - (br_if $y - (i32.eq - (local.get $b) - (i32.const 11) - ) - ) - (br_if $z - (i32.eq - (local.get $b) - (i32.const 12) - ) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (func $br-to-table-eqz (param $a i32) - (block $x - (block $y - (block $z - (nop) - (nop) - (block $tablify|0 - (br_table $x $y $z $tablify|0 - (local.get $a) - ) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (func $br-to-table-tee-eqz (param $a i32) - (block $x - (block $y - (block $z - (nop) - (nop) - (block $tablify|0 - (br_table $x $y $z $tablify|0 - (local.tee $a - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - ) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) (func $tiny-switch (if (i32.const 0) @@ -2091,16 +1988,17 @@ ) ) ) - (func $drop-restructure-select (param $x i32) (param $y i32) (result i32) - (select - (local.tee $y - (local.get $x) - ) - (block $label$2 (result i32) - (nop) - (i32.const 0) + (func $drop-restructure-if-bad (param $x i32) (param $y i32) (result i32) + (block $label$2 (result i32) + (drop + (br_if $label$2 + (local.tee $y + (local.get $x) + ) + (local.get $y) + ) ) - (local.get $y) + (i32.const 0) ) ) (func $drop-restructure-if-bad-2 (param $x i32) (param $y i32) (result i32) @@ -2355,7 +2253,11 @@ ) (func $selectify (param $x i32) (drop - (select + (if (result i32) + (i32.eq + (local.get $x) + (i32.const 1) + ) (i32.mul (i32.const 2) (i32.const 3) @@ -2364,10 +2266,6 @@ (i32.const 2) (i32.const 3) ) - (i32.eq - (local.get $x) - (i32.const 1) - ) ) ) (drop diff -Nru binaryen-108/test/passes/remove-unused-brs_enable-multivalue.wast binaryen-99/test/passes/remove-unused-brs_enable-multivalue.wast --- binaryen-108/test/passes/remove-unused-brs_enable-multivalue.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_enable-multivalue.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1353,93 +1353,6 @@ ) (unreachable) ) - (func $br-to-table-initial-tee (param $a i32) - (block $x - (block $y - (block $z - (br_if $x - (i32.eq - (local.tee $a - (i32.add - (i32.const 10) - (i32.const 1) - ) - ) - (i32.const 10) - ) - ) - (br_if $y (i32.eq (local.get $a) (i32.const 11))) - (br_if $z (i32.eq (local.get $a) (i32.const 12))) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (func $br-to-table-initial-tee-wrong-index (param $a i32) - (local $b i32) - (block $x - (block $y - (block $z - (br_if $x - (i32.eq - (local.tee $a (i32.const 99)) - (i32.const 10) - ) - ) - ;; The subsequent conditions use a different local, $b, so we cannot - ;; optimize here. - (br_if $y (i32.eq (local.get $b) (i32.const 11))) - (br_if $z (i32.eq (local.get $b) (i32.const 12))) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (func $br-to-table-eqz (param $a i32) - (block $x - (block $y - (block $z - (br_if $x (i32.eqz (local.get $a))) - (br_if $y (i32.eq (local.get $a) (i32.const 1))) - (br_if $z (i32.eq (local.get $a) (i32.const 2))) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (func $br-to-table-tee-eqz (param $a i32) - (block $x - (block $y - (block $z - (br_if $x - (i32.eqz - (local.tee $a - (i32.add - (i32.const 0) - (i32.const 1) - ) - ) - ) - ) - (br_if $y (i32.eq (local.get $a) (i32.const 1))) - (br_if $z (i32.eq (local.get $a) (i32.const 2))) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) - (unreachable) - ) (func $tiny-switch (block $x (block $y @@ -1702,7 +1615,7 @@ (i32.const 0) ) ) - (func $drop-restructure-select (param $x i32) (param $y i32) (result i32) + (func $drop-restructure-if-bad (param $x i32) (param $y i32) (result i32) (block $label$2 (result i32) (drop (br_if $label$2 diff -Nru binaryen-108/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt binaryen-99/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt --- binaryen-108/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func (param i64))) + (type $i64_=>_none (func (param i64))) (func $0 (param $var$0 i64) block $label$1 block $label$2 @@ -16,7 +16,7 @@ ) ) (module - (type $0 (func (param i64))) + (type $i64_=>_none (func (param i64))) (func $0 (; has Stack IR ;) (param $var$0 i64) (block $label$1 (br_if $label$1 diff -Nru binaryen-108/test/passes/remove-unused-brs_shrink-level=1_ignore-implicit-traps.txt binaryen-99/test/passes/remove-unused-brs_shrink-level=1_ignore-implicit-traps.txt --- binaryen-108/test/passes/remove-unused-brs_shrink-level=1_ignore-implicit-traps.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_shrink-level=1_ignore-implicit-traps.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $2 (func (result i32))) - (type $1 (func)) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) (memory $0 256 256) (func $b14 (result i32) (drop diff -Nru binaryen-108/test/passes/remove-unused-brs_shrink-level=1.txt binaryen-99/test/passes/remove-unused-brs_shrink-level=1.txt --- binaryen-108/test/passes/remove-unused-brs_shrink-level=1.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-brs_shrink-level=1.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $2 (func (result i32))) - (type $1 (func)) + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) (memory $0 256 256) (func $b14 (result i32) (drop diff -Nru binaryen-108/test/passes/remove-unused-module-elements_all-features.txt binaryen-99/test/passes/remove-unused-module-elements_all-features.txt --- binaryen-108/test/passes/remove-unused-module-elements_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-module-elements_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $0 (func)) - (type $1 (func (param i32))) - (type $2 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 0) (table $0 1 1 funcref) (elem (i32.const 0) $called_indirect) @@ -36,40 +36,40 @@ (call $called3) ) (func $other1 (param $0 i32) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $1) + (call_indirect (type $i32_=>_none) (i32.const 0) (i32.const 0) ) - (call_indirect $0 (type $1) + (call_indirect (type $i32_=>_none) (i32.const 0) (i32.const 0) ) (drop - (call_indirect $0 (type $2) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 0) ) ) (drop - (call_indirect $0 (type $2) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 0) ) ) (drop - (call_indirect $0 (type $2) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 0) ) @@ -84,22 +84,10 @@ (module ) (module - (type $none_=>_none (func)) - (import "env" "table2" (table $1 1 1 funcref)) - (elem (i32.const 0) $f) - (func $f - (nop) - ) -) -(module -) -(module -) -(module (import "env" "memory" (memory $0 256)) (import "env" "table" (table $timport$0 1 funcref)) (export "mem" (memory $0)) - (export "tab" (table $timport$0)) + (export "tab" (table $0)) ) (module (type $none_=>_none (func)) @@ -112,7 +100,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (import "env" "memory" (memory $0 256)) (import "env" "table" (table $timport$0 0 funcref)) (export "user" (func $user)) @@ -122,7 +110,7 @@ (i32.const 0) ) ) - (call_indirect $timport$0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) @@ -221,16 +209,16 @@ (import "env" "memory" (memory $0 256)) (data (global.get $memoryBase) "hello, world!") (import "env" "table" (table $timport$0 0 funcref)) + (elem (global.get $tableBase) $waka) (import "env" "memoryBase" (global $memoryBase i32)) (import "env" "tableBase" (global $tableBase i32)) - (elem (global.get $tableBase) $waka) (func $waka (nop) ) ) (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) (type $i32_=>_i32 (func (param i32) (result i32))) (import "env" "imported" (global $imported i32)) (import "env" "_puts" (func $_puts (param i32) (result i32))) @@ -272,16 +260,11 @@ ) ) (module - (type $none_=>_none (func)) - (import "env" "start" (func $start)) - (start $start) ) (module ) (module -) -(module - (type $0 (func (param f64) (result f64))) + (type $f64_=>_f64 (func (param f64) (result f64))) (import "env" "table" (table $timport$0 6 6 funcref)) (elem (i32.const 0) $0) (func $0 (param $var$0 f64) (result f64) @@ -295,3 +278,49 @@ ) ) ) +(module + (type $i32_=>_none (func (param i32))) + (type $none_=>_none (func)) + (type $i64_=>_none (func (param i64))) + (event $e-export (attr 0) (param i64)) + (event $e-throw (attr 0) (param i32)) + (event $e-bronexn (attr 0) (param i32)) + (export "e-export" (event $e-export)) + (start $start) + (func $start + (local $exn exnref) + (try + (do + (throw $e-throw + (i32.const 0) + ) + ) + (catch + (local.set $exn + (pop exnref) + ) + (drop + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e-bronexn + (local.get $exn) + ) + ) + ) + ) + ) + ) + ) +) +(module + (type $none_=>_none (func)) + (export "test" (func $test)) + (func $foo + (nop) + ) + (func $test + (drop + (ref.func $foo) + ) + ) +) diff -Nru binaryen-108/test/passes/remove-unused-module-elements_all-features.wast binaryen-99/test/passes/remove-unused-module-elements_all-features.wast --- binaryen-108/test/passes/remove-unused-module-elements_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-module-elements_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -73,31 +73,10 @@ (import "env" "memory" (memory $0 256)) (import "env" "table" (table 0 funcref)) ) -(module ;; remove all tables and the memory - (import "env" "memory" (memory $0 256)) - (import "env" "table" (table 0 funcref)) - (import "env" "table2" (table $1 1 2 funcref)) - (elem (table $1) (offset (i32.const 0)) func) - (elem (table $1) (offset (i32.const 1)) func) -) -(module ;; remove the first table and memory, but not the second one - (import "env" "memory" (memory $0 256)) - (import "env" "table" (table 0 funcref)) - (import "env" "table2" (table $1 1 1 funcref)) - (elem (table $1) (offset (i32.const 0)) func) - (elem (table $1) (offset (i32.const 0)) func $f) - (func $f) -) (module ;; also when not imported (memory 256) (table 1 funcref) ) -(module ;; also with multiple tables - (memory 256) - (table $0 1 funcref) - (table $1 1 funcref) - (elem (table $1) (i32.const 0) func) -) (module ;; but not when exported (import "env" "memory" (memory $0 256)) (import "env" "table" (table 1 funcref)) @@ -239,10 +218,6 @@ (drop (i32.const 0)) ) ) -(module ;; imported start cannot be removed - (import "env" "start" (func $start)) - (start $start) -) (module ;; the function and the table can be removed (type $0 (func (param f64) (result f64))) (table 6 6 funcref) @@ -286,3 +261,39 @@ ) ) ) +(module ;; non-exported and unused events can be removed + (type $0 (func (param i32))) + (event $e-remove (attr 0) (type $0)) ;; can be removed + (event $e-export (attr 0) (param i64)) ;; cannot be removed (exported) + (event $e-throw (attr 0) (type $0)) ;; cannot be removed (used in throw) + (event $e-bronexn (attr 0) (type $0)) ;; cannot be removed (used in br_on_exn) + (export "e-export" (event $e-export)) + (import "env" "e" (event $e-import (attr 0) (param i32))) + (start $start) + (func $start (local $exn exnref) (; 0 ;) + (try + (do + (throw $e-throw (i32.const 0)) + ) + (catch + (local.set $exn (pop exnref)) + (drop + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e-bronexn (local.get $exn)) + ) + ) + ) + ) + ) + ) +) +(module ;; functions referenced by ref.func cannot be removed + (export "test" $test) + (func $foo) + (func $test + (drop + (ref.func $foo) + ) + ) +) diff -Nru binaryen-108/test/passes/remove-unused-names_code-folding_all-features.txt binaryen-99/test/passes/remove-unused-names_code-folding_all-features.txt --- binaryen-108/test/passes/remove-unused-names_code-folding_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_code-folding_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1843 @@ +(module + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_exnref (func (result exnref))) + (event $e (attr 0) (param)) + (func $ifs + (if + (i32.const 0) + (nop) + ) + (block + (drop + (i32.const 0) + ) + (nop) + ) + (if + (i32.const 0) + (nop) + (unreachable) + ) + (drop + (block (result i32) + (drop + (i32.const 0) + ) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (drop + (if (result i32) + (i32.const 0) + (i32.add + (i32.const 1) + (i32.const 2) + ) + (i32.add + (i32.const 1) + (i32.const 333333333) + ) + ) + ) + ) + (func $ifs-blocks + (block + (drop + (i32.const 0) + ) + (block + (nop) + ) + ) + (block + (if + (i32.const 0) + (unreachable) + (block + ) + ) + (nop) + ) + (block + (if + (i32.const 0) + (block + ) + (unreachable) + ) + (nop) + ) + (if + (i32.const 0) + (block + (nop) + (unreachable) + ) + (nop) + ) + (if + (i32.const 0) + (nop) + (block + (nop) + (unreachable) + ) + ) + ) + (func $ifs-blocks-big + (block + (drop + (i32.const 0) + ) + (block + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + ) + (block + (if + (i32.const 0) + (unreachable) + (block + ) + ) + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (block + (if + (i32.const 0) + (block + ) + (unreachable) + ) + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (if + (i32.const 0) + (block + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (unreachable) + ) + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (if + (i32.const 0) + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (block + (drop + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (unreachable) + ) + ) + ) + (func $ifs-blocks-long + (block + (if + (i32.const 1) + (block + (drop + (i32.const -1234) + ) + (drop + (i32.const -1000) + ) + ) + (drop + (i32.const 999) + ) + ) + (drop + (i32.const 1) + ) + (nop) + (unreachable) + ) + (drop + (block (result i32) + (if + (i32.const 2) + (block + (drop + (i32.const -1234) + ) + (drop + (i32.const -1000) + ) + ) + (drop + (i32.const 999) + ) + ) + (drop + (i32.const 1) + ) + (nop) + (unreachable) + (i32.const 2) + ) + ) + (drop + (block (result i32) + (if + (i32.const 3) + (block + (drop + (i32.const -1234) + ) + (drop + (i32.const -1000) + ) + ) + (drop + (i32.const 999) + ) + ) + (drop + (i32.const 1) + ) + (nop) + (i32.const 2) + ) + ) + ) + (func $if-worth-it-i-dunno + (block $folding-inner0 + (block + (if + (i32.const 0) + (if + (i32.const 0) + (block + (drop + (i32.const -1234) + ) + (drop + (i32.const -1000) + ) + (br $folding-inner0) + ) + (block + (drop + (i32.const 999) + ) + (drop + (i32.const 1) + ) + (br $folding-inner0) + ) + ) + ) + (if + (i32.const 0) + (block + (if + (i32.const 0) + (block + (drop + (i32.const -1234) + ) + (drop + (i32.const -1000) + ) + ) + (block + (drop + (i32.const 999) + ) + (drop + (i32.const 1) + ) + ) + ) + (unreachable) + (br $folding-inner0) + ) + ) + (if + (i32.const 0) + (block + (if + (i32.const 0) + (block + ) + (block + (drop + (i32.const 999) + ) + (drop + (i32.const 1) + ) + ) + ) + (br $folding-inner0) + ) + ) + (if + (i32.const 0) + (block + (if + (i32.const 0) + (block + (drop + (i32.const -1234) + ) + (drop + (i32.const -1000) + ) + ) + (block + ) + ) + (br $folding-inner0) + ) + ) + (block + (block + (if + (i32.const 9999) + (block + (drop + (i32.const -51234) + ) + (drop + (i32.const -51000) + ) + ) + (block + (drop + (i32.const 5999) + ) + (drop + (i32.const 51) + ) + ) + ) + (br $folding-inner0) + ) + ) + (drop + (block (result i32) + (block (result i32) + (if + (i32.const 9999) + (block + (drop + (i32.const -51234) + ) + (drop + (i32.const -51000) + ) + ) + (block + (drop + (i32.const 5999) + ) + (drop + (i32.const 51) + ) + ) + ) + (unreachable) + (i32.const 10) + ) + ) + ) + (block + (drop + (if (result i32) + (i32.const 9999) + (block (result i32) + (drop + (i32.const -51234) + ) + (drop + (i32.const -51000) + ) + (unreachable) + (i32.const 10) + ) + (block (result i32) + (drop + (i32.const 5999) + ) + (drop + (i32.const 51) + ) + (unreachable) + (i32.const 10) + ) + ) + ) + ) + ) + ) + (unreachable) + (unreachable) + ) + (func $no-grandparent + (if + (i32.const 9999) + (block + (drop + (i32.const -51234) + ) + (drop + (i32.const -51000) + ) + (unreachable) + (unreachable) + ) + (block + (drop + (i32.const 5999) + ) + (drop + (i32.const 51) + ) + (unreachable) + (unreachable) + ) + ) + ) + (func $yes-grandparent + (block + (if + (i32.const 9999) + (block + (drop + (i32.const -51234) + ) + (drop + (i32.const -51000) + ) + ) + (block + (drop + (i32.const 5999) + ) + (drop + (i32.const 51) + ) + ) + ) + (unreachable) + (unreachable) + ) + ) + (func $ifs-named-block (param $x i32) (param $y i32) (result i32) + (block $out + (block $out2 + (block + (drop + (local.get $x) + ) + (block + (br_if $out + (local.get $y) + ) + (nop) + ) + ) + (block + (if + (local.get $x) + (br_if $out + (local.get $y) + ) + (br_if $out2 + (local.get $y) + ) + ) + (nop) + ) + (if + (i32.const 1234) + (if + (local.get $x) + (block + (nop) + (br_if $out + (local.get $y) + ) + (nop) + ) + (block + (nop) + (br_if $out2 + (local.get $y) + ) + (nop) + ) + ) + ) + (if + (local.get $x) + (block $left + (br_if $left + (local.get $y) + ) + (nop) + ) + (block + (br_if $out + (local.get $y) + ) + (nop) + ) + ) + (if + (local.get $x) + (block + (br_if $out + (local.get $y) + ) + (nop) + ) + (block $right + (br_if $right + (local.get $y) + ) + (nop) + ) + ) + ) + (return + (i32.const 10) + ) + ) + (return + (i32.const 20) + ) + ) + (func $block + (block $x + (if + (i32.const 0) + (br $x) + ) + (if + (i32.const 0) + (br $x) + ) + (br $x) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (func $block2 + (block $x + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 333333) + ) + (br $x) + ) + ) + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x) + ) + ) + (func $block3 + (block $x + (if + (i32.const 0) + (block + (drop + (i32.const 1000) + ) + (br $x) + ) + ) + (if + (i32.const 0) + (block + (drop + (i32.const 2000) + ) + (drop + (i32.const 3000) + ) + (br $x) + ) + ) + (drop + (i32.const 4000) + ) + (drop + (i32.const 5000) + ) + (drop + (i32.const 6000) + ) + (br $x) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (func $mixture + (block $out + (block + (drop + (i32.const 1) + ) + (block + (drop + (i32.const 2) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (br $out) + ) + ) + ) + (block $out2 + (block + (if + (i32.const 1) + (drop + (i32.const 3) + ) + (block + (drop + (i32.const 4) + ) + (drop + (i32.const 5) + ) + ) + ) + (drop + (i32.const 2) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (br $out2) + ) + ) + (block + (block $out3 + (block + (drop + (i32.const 1) + ) + (block + (br $out3) + ) + ) + (block + (drop + (i32.const 1) + ) + (block + (br $out3) + ) + ) + (br $out3) + ) + (drop + (i32.const 2) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + ) + ) + (func $block-corners + (block + (block $x + (if + (i32.const 0) + (br $x) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (block $y (result i32) + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $y + (i32.const 3) + ) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $y + (i32.const 3) + ) + ) + ) + (drop + (block $z (result i32) + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $z + (i32.const 2) + ) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (i32.const 3) + ) + ) + (block $w + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br_if $w + (i32.const 3) + ) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (block $x1 + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x1) + (nop) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (block $side + (block $x2 + (br_table $x2 $side + (i32.const 0) + ) + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x2) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (block $x3 + (br_table $side $x3 + (i32.const 0) + ) + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x3) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + ) + ) + (func $terminating + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + ) + (return) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (unreachable) + ) + (func $terminating-unreachable + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + (unreachable) + ) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (unreachable) + ) + (func $terminating-value (result i32) + (block $folding-inner0 + (return + (block (result i32) + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + (i32.const 4) + ) + ) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (unreachable) + ) + (func $terminating-just-2 + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (block + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (drop + (i32.const 10) + ) + (unreachable) + ) + ) + ) + (return) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (unreachable) + ) + (func $terminating-shortness + (block $folding-inner1 + (block + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner1) + ) + (if + (i32.const 3) + (block + (drop + (i32.const 10) + ) + (br $folding-inner0) + ) + ) + ) + (return) + ) + (nop) + (br $folding-inner1) + ) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (unreachable) + ) + (func $terminating-multiple-separate + (block $folding-inner1 + (block + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 1) + (br $folding-inner1) + ) + (if + (i32.const 1) + (br $folding-inner1) + ) + ) + (return) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (drop + (i32.const 1) + ) + (unreachable) + ) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (drop + (i32.const 2) + ) + (unreachable) + ) + (func $terminating-just-worth-it + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + ) + (return) + ) + (nop) + (nop) + (nop) + (unreachable) + ) + (func $terminating-not-worth-it + (if + (i32.const 1) + (block + (nop) + (nop) + (unreachable) + ) + ) + (if + (i32.const 2) + (block + (nop) + (nop) + (unreachable) + ) + ) + (if + (i32.const 3) + (block + (nop) + (nop) + (unreachable) + ) + ) + ) + (func $terminating-return + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + ) + (return) + ) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (nop) + (return) + ) + (func $terminating-return-value (result i32) + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + (if + (i32.const 3) + (block + (nop) + (return + (i32.add + (i32.const 111111111) + (i32.const 2222222) + ) + ) + ) + ) + (return + (i32.const 1234) + ) + ) + ) + (nop) + (return + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (func $terminating-fallthrough-value (result i32) + (block $folding-inner0 + (return + (block (result i32) + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + (if + (i32.const 3) + (block + (nop) + (return + (i32.add + (i32.const 111111111) + (i32.const 2222222) + ) + ) + ) + ) + (i32.const 1234) + ) + ) + ) + (nop) + (return + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (func $big-return (result i32) + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + (if + (i32.const 4) + (br $folding-inner0) + ) + (if + (i32.const 5) + (br $folding-inner0) + ) + (if + (i32.const 6) + (br $folding-inner0) + ) + (unreachable) + ) + ) + (return + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (func $return-mix (result i32) + (block $folding-inner0 + (block + (if + (i32.const 1) + (br $folding-inner0) + ) + (if + (i32.const 2) + (br $folding-inner0) + ) + (if + (i32.const 3) + (br $folding-inner0) + ) + (if + (i32.const 4) + (br $folding-inner0) + ) + (if + (i32.const 3) + (return + (i32.add + (i32.const 1) + (i32.const 234567) + ) + ) + ) + (br $folding-inner0) + ) + ) + (return + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (func $just-unreachable + (unreachable) + ) + (func $just-return (result i32) + (return + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + (func $drop-if-with-value-but-unreachable + (if + (i32.const 0) + (nop) + ) + (block + (drop + (i32.const 0) + ) + (block + (nop) + ) + ) + (if + (i32.const 0) + (nop) + (unreachable) + ) + (nop) + (drop + (block (result i32) + (drop + (unreachable) + ) + (block (result i32) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + ) + (drop + (if (result i32) + (i32.const 0) + (i32.add + (i32.const 1) + (i32.const 2) + ) + (i32.add + (i32.const 1) + (i32.const 333333333) + ) + ) + ) + ) + (func $nested-control-flow + (block $out + (block + (block $x + (if + (i32.const 0) + (br $x) + ) + (if + (i32.const 0) + (br $x) + ) + (br $x) + ) + (if + (i32.const 1) + (br $out) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (i32.const 3) + ) + ) + ) + (func $nested-control-flow-dangerous + (block $folding-inner0 + (block $out + (block + (if + (i32.const 0) + (block + (if + (i32.const 1) + (br $out) + ) + (br $folding-inner0) + ) + ) + (if + (i32.const 0) + (block + (if + (i32.const 1) + (br $out) + ) + (br $folding-inner0) + ) + ) + (if + (i32.const 1) + (br $out) + ) + (br $folding-inner0) + ) + (drop + (i32.const 3) + ) + ) + (return) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (return) + ) + (func $nested-control-flow-dangerous-but-ok + (block $folding-inner0 + (block + (block $middle + (block + (if + (i32.const 0) + (block + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $middle) + ) + (br $folding-inner0) + ) + ) + (if + (i32.const 0) + (block + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $middle) + ) + (br $folding-inner0) + ) + ) + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $middle) + ) + (br $folding-inner0) + ) + ) + (drop + (i32.const 3) + ) + ) + (return) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (return) + ) + (func $nested-control-flow-dangerous-but-ok-b + (block $out + (block $middle + (block + (if + (i32.const 0) + (block + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $middle) + ) + (br $out) + ) + ) + (if + (i32.const 0) + (block + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $middle) + ) + (br $out) + ) + ) + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $middle) + ) + ) + ) + (unreachable) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (drop + (i32.const 3) + ) + (drop + (i32.const 4) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (drop + (i32.const 3) + ) + (drop + (i32.const 4) + ) + ) + (func $nested-control-flow-dangerous-but-ok-c + (block $x + (block + (block $out + (block + (if + (i32.const 0) + (br $out) + ) + (if + (i32.const 0) + (br $out) + ) + (br $out) + ) + (unreachable) + ) + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $x) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (unreachable) + ) + (drop + (i32.const 5) + ) + ) + (func $nested-control-flow-dangerous-but-ok-d + (block + (block $out + (block + (if + (i32.const 0) + (br $out) + ) + (if + (i32.const 0) + (br $out) + ) + (br $out) + ) + ) + (block $x + (if + (i32.add + (i32.const 0) + (i32.const 1) + ) + (br $x) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + ) + (drop + (i32.const 3) + ) + ) + (func $if-suffix (param $x i32) (result i32) + (block + (if + (local.get $x) + (block + ) + (drop + (call $if-suffix + (i32.const -1) + ) + ) + ) + (local.set $x + (i32.const 1) + ) + ) + (block (result i32) + (if + (local.get $x) + (block + ) + (drop + (call $if-suffix + (i32.const -2) + ) + ) + ) + (i32.const 2) + ) + ) + (func $exnref_pop-test + (local $exn exnref) + (block $folding-inner0 + (try + (do + (try + (do + (nop) + ) + (catch + (local.set $exn + (pop exnref) + ) + (br $folding-inner0) + ) + ) + ) + (catch + (local.set $exn + (pop exnref) + ) + (br $folding-inner0) + ) + ) + (return) + ) + (drop + (i32.const 111) + ) + (drop + (i32.const 222) + ) + (drop + (i32.const 333) + ) + (unreachable) + ) + (func $br_on_exn-target-block + (local $exn exnref) + (block $x + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x) + ) + ) + (if + (i32.const 0) + (block + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x) + ) + ) + (drop + (br_on_exn $x $e + (local.get $exn) + ) + ) + (drop + (i32.const 1) + ) + (drop + (i32.const 2) + ) + (br $x) + ) + ) + (func $foo + (nop) + ) + (func $try-call-optimize-terminating-tails (result exnref) + (try + (do + (call $foo) + (call $foo) + (call $foo) + (call $foo) + (return + (ref.null exn) + ) + ) + (catch + (drop + (pop exnref) + ) + (call $foo) + (call $foo) + (call $foo) + (call $foo) + (return + (ref.null exn) + ) + ) + ) + (ref.null exn) + ) + (func $try-call-optimize-expression-tails + (local $exn exnref) + (block $x + (try + (do + (call $foo) + (call $foo) + (call $foo) + (br $x) + ) + (catch + (local.set $exn + (pop exnref) + ) + (call $foo) + (call $foo) + (call $foo) + (br $x) + ) + ) + (unreachable) + ) + ) +) diff -Nru binaryen-108/test/passes/remove-unused-names_code-folding_all-features.wast binaryen-99/test/passes/remove-unused-names_code-folding_all-features.wast --- binaryen-108/test/passes/remove-unused-names_code-folding_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_code-folding_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1292 @@ +(module + (func $ifs + (if (i32.const 0) (nop)) + (if (i32.const 0) (nop) (nop)) + (if (i32.const 0) (nop) (unreachable)) + (drop + (if (result i32) (i32.const 0) + (i32.add (i32.const 1) (i32.const 2)) + (i32.add (i32.const 1) (i32.const 2)) + ) + ) + (drop + (if (result i32) (i32.const 0) + (i32.add (i32.const 1) (i32.const 2)) + (i32.add (i32.const 1) (i32.const 333333333)) + ) + ) + ) + (func $ifs-blocks + (if (i32.const 0) + (block + (nop) + ) + (block + (nop) + ) + ) + (if (i32.const 0) + (block + (unreachable) + (nop) + ) + (block + (nop) + ) + ) + (if (i32.const 0) + (block + (nop) + ) + (block + (unreachable) + (nop) + ) + ) + (if (i32.const 0) + (block + (nop) + (unreachable) + ) + (block + (nop) + ) + ) + (if (i32.const 0) + (block + (nop) + ) + (block + (nop) + (unreachable) + ) + ) + ) + (func $ifs-blocks-big + (if (i32.const 0) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 0) + (block + (unreachable) + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 0) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + (block + (unreachable) + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 0) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + (unreachable) + ) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 0) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + ) + (block + (drop (i32.add (i32.const 1) (i32.const 2))) + (unreachable) + ) + ) + ) + (func $ifs-blocks-long + (if (i32.const 1) + (block + (drop (i32.const -1234)) + (drop (i32.const -1000)) + (drop (i32.const 1)) + (nop) + (unreachable) + ) + (block + (drop (i32.const 999)) + (drop (i32.const 1)) + (nop) + (unreachable) + ) + ) + (drop + (if (result i32) (i32.const 2) + (block (result i32) + (drop (i32.const -1234)) + (drop (i32.const -1000)) + (drop (i32.const 1)) + (nop) + (unreachable) + (i32.const 2) + ) + (block (result i32) + (drop (i32.const 999)) + (drop (i32.const 1)) + (nop) + (unreachable) + (i32.const 2) + ) + ) + ) + (drop + (if (result i32) (i32.const 3) + (block (result i32) + (drop (i32.const -1234)) + (drop (i32.const -1000)) + (drop (i32.const 1)) + (nop) + (i32.const 2) + ) + (block (result i32) + (drop (i32.const 999)) + (drop (i32.const 1)) + (nop) + (i32.const 2) + ) + ) + ) + ) + (func $if-worth-it-i-dunno + ;; just 2, so not worth it + (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) + (if (i32.const 0) + (block + (drop (i32.const -1234)) + (drop (i32.const -1000)) + (unreachable) + (unreachable) + ) + (block + (drop (i32.const 999)) + (drop (i32.const 1)) + (unreachable) + (unreachable) + ) + ) + ) + ;; 3, so why not + (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) + (if (i32.const 0) + (block + (drop (i32.const -1234)) + (drop (i32.const -1000)) + (unreachable) + (unreachable) + (unreachable) + ) + (block + (drop (i32.const 999)) + (drop (i32.const 1)) + (unreachable) + (unreachable) + (unreachable) + ) + ) + ) + ;; just 2, but we'll empty out a block + (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) + (if (i32.const 0) + (block + (unreachable) + (unreachable) + ) + (block + (drop (i32.const 999)) + (drop (i32.const 1)) + (unreachable) + (unreachable) + ) + ) + ) + ;; just 2, but we'll empty out a block + (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) + (if (i32.const 0) + (block + (drop (i32.const -1234)) + (drop (i32.const -1000)) + (unreachable) + (unreachable) + ) + (block + (unreachable) + (unreachable) + ) + ) + ) + ;; just two, but on a block, so we hope to merge, and can optimize here + (block $a-holding-block + (if (i32.const 9999) + (block + (drop (i32.const -51234)) + (drop (i32.const -51000)) + (unreachable) + (unreachable) + ) + (block + (drop (i32.const 5999)) + (drop (i32.const 51)) + (unreachable) + (unreachable) + ) + ) + ) + ;; with value + (drop + (block $b-holding-block (result i32) + (if (result i32) (i32.const 9999) + (block (result i32) + (drop (i32.const -51234)) + (drop (i32.const -51000)) + (unreachable) + (i32.const 10) + ) + (block (result i32) + (drop (i32.const 5999)) + (drop (i32.const 51)) + (unreachable) + (i32.const 10) + ) + ) + ) + ) + ;; oops, something in between + (block $c-holding-block + (drop + (if (result i32) (i32.const 9999) + (block (result i32) + (drop (i32.const -51234)) + (drop (i32.const -51000)) + (unreachable) + (i32.const 10) + ) + (block (result i32) + (drop (i32.const 5999)) + (drop (i32.const 51)) + (unreachable) + (i32.const 10) + ) + ) + ) + ) + ) + (func $no-grandparent + ;; if we had a parent block, we might optimize this + (if (i32.const 9999) + (block + (drop (i32.const -51234)) + (drop (i32.const -51000)) + (unreachable) + (unreachable) + ) + (block + (drop (i32.const 5999)) + (drop (i32.const 51)) + (unreachable) + (unreachable) + ) + ) + ) + (func $yes-grandparent + (block + (if (i32.const 9999) + (block + (drop (i32.const -51234)) + (drop (i32.const -51000)) + (unreachable) + (unreachable) + ) + (block + (drop (i32.const 5999)) + (drop (i32.const 51)) + (unreachable) + (unreachable) + ) + ) + ) + ) + (func $ifs-named-block (param $x i32) (param $y i32) (result i32) + (block $out + (block $out2 + (if (local.get $x) + (block + (br_if $out (local.get $y i32)) + (nop) + ) + (block + (br_if $out (local.get $y i32)) + (nop) + ) + ) + (if (local.get $x) + (block + (br_if $out (local.get $y i32)) + (nop) + ) + (block + (br_if $out2 (local.get $y i32)) + (nop) + ) + ) + (if (i32.const 1234) + (if (local.get $x) + (block + (nop) + (br_if $out (local.get $y i32)) + (nop) + ) + (block + (nop) + (br_if $out2 (local.get $y i32)) + (nop) + ) + ) + ) + (if (local.get $x) + (block $left + (br_if $left (local.get $y i32)) + (nop) + ) + (block + (br_if $out (local.get $y i32)) + (nop) + ) + ) + (if (local.get $x) + (block + (br_if $out (local.get $y i32)) + (nop) + ) + (block $right + (br_if $right (local.get $y i32)) + (nop) + ) + ) + ) + (return (i32.const 10)) + ) + (return (i32.const 20)) + ) + (func $block + (block $x + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + ;; no fallthrough, another thing to merge + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (func $block2 + (block $x + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 333333)) + (br $x) + ) + ) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + ;; no fallthrough, another thing to merge + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (func $block3 + (block $x + (if (i32.const 0) + (block + (drop (i32.const 1000)) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (if (i32.const 0) + (block + (drop (i32.const 2000)) + (drop (i32.const 3000)) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (drop (i32.const 4000)) + (drop (i32.const 5000)) + (drop (i32.const 6000)) + ;; no fallthrough, another thing to merge + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (func $mixture + (block $out ;; then we reach the block, and the tail infos are stale, should ignore + (if (i32.const 1) ;; then we optimize the if, pushing those brs outside! + (block + (drop (i32.const 2)) ;; first we note the block tails for $out + (nop) (nop) (nop) (nop) (nop) (nop) ;; totally worth it + (br $out) + ) + (block + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out) + ) + ) + ) + (block $out2 + (if (i32.const 1) + (block + (drop (i32.const 3)) ;; leave something + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out2) + ) + (block + (drop (i32.const 4)) ;; leave something + (drop (i32.const 5)) ;; leave something + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out2) + ) + ) + ) + ;; now a case where do **do** want to fold for the block (which we can only do in a later pass) + (block $out3 + (if (i32.const 1) + (block + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out3) + ) + (block + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out3) + ) + ) + (if (i32.const 1) + (block + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out3) + ) + (block + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out3) + ) + ) + (drop (i32.const 2)) + (nop) (nop) (nop) (nop) (nop) (nop) + (br $out3) + ) + ) + (func $block-corners + ;; these should be merged + (block $x + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + ) + ;; these should not + ;; values + (drop + (block $y (result i32) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $y (i32.const 3)) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $y (i32.const 3)) + ) + ) + (drop + (block $z (result i32) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $z (i32.const 2)) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (i32.const 3) + ) + ) + ;; condition + (block $w + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br_if $w (i32.const 3)) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + ) + ;; not at the end + (block $x1 + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x1) + (nop) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + ) + ;; switches + (block $side + (block $x2 + (br_table $x2 $side (i32.const 0)) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x2) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + ) + (block $x3 + (br_table $side $x3 (i32.const 0)) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x3) + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + ) + ) + ) + (func $terminating + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + ) + (func $terminating-unreachable + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (unreachable) + ) + (func $terminating-value (result i32) + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (i32.const 4) + ) + (func $terminating-just-2 + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (drop (i32.const 10)) + (unreachable) + ) + ) + ) + (func $terminating-shortness + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) ;; shorter. we do the two long ones greedily, then the merged one and this can also be opted + (unreachable) + ) + ) + (if (i32.const 3) + (block + (drop (i32.const 10)) + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (unreachable) + ) + ) + ) + (func $terminating-multiple-separate + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (drop (i32.const 1)) + (unreachable) + ) + ) + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (drop (i32.const 1)) + (unreachable) + ) + ) + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (drop (i32.const 2)) + (unreachable) + ) + ) + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (drop (i32.const 2)) + (unreachable) + ) + ) + ) + (func $terminating-just-worth-it + (if (i32.const 1) + (block + (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) (nop) + (unreachable) + ) + ) + ) + (func $terminating-not-worth-it + (if (i32.const 1) + (block + (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) + (unreachable) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) + (unreachable) + ) + ) + ) + (func $terminating-return + (if (i32.const 1) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (return) + ) + ) + (if (i32.const 2) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (return) + ) + ) + (if (i32.const 3) + (block + (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) + (return) + ) + ) + ) + (func $terminating-return-value (result i32) + (if (i32.const 1) + (block + (nop) + (return (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 2) + (block + (nop) + (return (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 3) + (block + (nop) + (return (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 3) + (block + (nop) + (return (i32.add (i32.const 111111111) (i32.const 2222222))) + ) + ) + (return (i32.const 1234)) + ) + (func $terminating-fallthrough-value (result i32) + (if (i32.const 1) + (block + (nop) + (return (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 2) + (block + (nop) + (return (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 3) + (block + (nop) + (return (i32.add (i32.const 1) (i32.const 2))) + ) + ) + (if (i32.const 3) + (block + (nop) + (return (i32.add (i32.const 111111111) (i32.const 2222222))) + ) + ) + (i32.const 1234) + ) + (func $big-return (result i32) + (if (i32.const 1) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 2) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 4) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 5) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 6) (return (i32.add (i32.const 1) (i32.const 2)))) + (unreachable) + ) + (func $return-mix (result i32) + (if (i32.const 1) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 2) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 4) (return (i32.add (i32.const 1) (i32.const 2)))) + (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 234567)))) + (return (i32.add (i32.const 1) (i32.const 2))) ;; on a block, and the toplevel in fact + ) + (func $just-unreachable + (unreachable) + ) + (func $just-return (result i32) + (return (i32.add (i32.const 1) (i32.const 2))) ;; on a block, and the toplevel in fact + ) + (func $drop-if-with-value-but-unreachable + (block $label$0 + (if + (i32.const 0) + (block $label$1 + (nop) + ) + ) + (if + (i32.const 0) + (block $label$2 + (nop) + ) + (block $label$3 + (nop) + ) + ) + (if + (i32.const 0) + (block $label$4 + (nop) + ) + (block $label$5 + (unreachable) + ) + ) + (nop) + (drop + (if (result i32) ;; we replace this if, must replace with same type! + (unreachable) + (block $label$6 (result i32) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (block $label$7 (result i32) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + ) + ) + (drop + (if (result i32) + (i32.const 0) + (block $label$8 (result i32) + (i32.add + (i32.const 1) + (i32.const 2) + ) + ) + (block $label$9 (result i32) + (i32.add + (i32.const 1) + (i32.const 333333333) + ) + ) + ) + ) + ) + ) + (func $nested-control-flow + (block $out + (block $x + (if (i32.const 0) + (block + (if (i32.const 1) + (br $out) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (if (i32.const 0) + (block + (if (i32.const 1) + (br $out) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + ;; no fallthrough, another thing to merge + (if (i32.const 1) + (br $out) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + (drop (i32.const 3)) + ) + ) + (func $nested-control-flow-dangerous + (block $out + (block $x + (if (i32.const 0) + (block + (if (i32.const 1) + (br $out) ;; this br cannot be moved out of the $out block! + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (return) + ) + ) + (if (i32.const 0) + (block + (if (i32.const 1) + (br $out) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (return) + ) + ) + ;; no fallthrough, another thing to merge + (if (i32.const 1) + (br $out) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (return) + ) + (drop (i32.const 3)) + ) + ) + (func $nested-control-flow-dangerous-but-ok + (block $out + (block $middle + (block $x + (if (i32.const 0) + (block + (if (i32.add (i32.const 0) (i32.const 1)) + (br $middle) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (return) + ) + ) + (if (i32.const 0) + (block + (if (i32.add (i32.const 0) (i32.const 1)) + (br $middle) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (return) + ) + ) + ;; no fallthrough, another thing to merge + (if (i32.add (i32.const 0) (i32.const 1)) + (br $middle) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (return) + ) + ) + (drop (i32.const 3)) + ) + ) + (func $nested-control-flow-dangerous-but-ok-b + (block $out + (block $middle + (block $x + (if (i32.const 0) + (block + (if (i32.add (i32.const 0) (i32.const 1)) + (br $middle) ;; this is dangerous - we branch to middle with is inside out, so we can't move this out of out + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (drop (i32.const 3)) + (drop (i32.const 4)) + (drop (i32.const 1)) + (drop (i32.const 2)) + (drop (i32.const 3)) + (drop (i32.const 4)) + (br $out) + ) + ) + (if (i32.const 0) + (block + (if (i32.add (i32.const 0) (i32.const 1)) + (br $middle) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (drop (i32.const 3)) + (drop (i32.const 4)) + (drop (i32.const 1)) + (drop (i32.const 2)) + (drop (i32.const 3)) + (drop (i32.const 4)) + (br $out) + ) + ) + ;; no fallthrough, another thing to merge + (if (i32.add (i32.const 0) (i32.const 1)) + (br $middle) + ) + ) + ) + (unreachable) ;; no fallthrough + ) + ) + (func $nested-control-flow-dangerous-but-ok-c + (block $x + (block $out + (block $middle + (if (i32.const 0) + (block + (if (i32.add (i32.const 0) (i32.const 1)) + (br $x) ;; this is ok - we branch to x which is outside of out + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $out) + ) + ) + (if (i32.const 0) + (block + (if (i32.add (i32.const 0) (i32.const 1)) + (br $x) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $out) + ) + ) + ;; no fallthrough, another thing to merge + (if (i32.add (i32.const 0) (i32.const 1)) + (br $x) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $out) + ) + (unreachable) ;; no fallthrough + ) + (unreachable) ;; no fallthrough + ) + (drop (i32.const 5)) + ) + (func $nested-control-flow-dangerous-but-ok-d + (block $out + (block $middle + (if (i32.const 0) + (block + (block $x + (if (i32.add (i32.const 0) (i32.const 1)) + (br $x) ;; this is ok - we branch to x which is nested in us + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $out) + ) + ) + (if (i32.const 0) + (block + (block $x + (if (i32.add (i32.const 0) (i32.const 1)) + (br $x) ;; this is ok - we branch to x which is nested in us + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $out) + ) + ) + ;; no fallthrough, another thing to merge + (block $x + (if (i32.add (i32.const 0) (i32.const 1)) + (br $x) ;; this is ok - we branch to x which is nested in us + ) + ) + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $out) + ) + ) + (drop (i32.const 3)) + ) + (func $if-suffix (param $x i32) (result i32) + (if + (local.get $x) + (local.set $x (i32.const 1)) + (block + (drop (call $if-suffix (i32.const -1))) + (local.set $x (i32.const 1)) + ) + ) + (if (result i32) + (local.get $x) + (i32.const 2) + (block (result i32) + (drop (call $if-suffix (i32.const -2))) + (i32.const 2) + ) + ) + ) + + (func $exnref_pop-test (local $exn exnref) + (try + (do + (try + (do) + (catch + ;; Expressions containing (pop exnref) should NOT be taken out and + ;; folded. + (local.set $exn (pop exnref)) + (drop (i32.const 111)) + (drop (i32.const 222)) + (drop (i32.const 333)) + (unreachable) + ) + ) + ) + (catch + (local.set $exn (pop exnref)) + (drop (i32.const 111)) + (drop (i32.const 222)) + (drop (i32.const 333)) + (unreachable) + ) + ) + ) + + (event $e (attr 0)) ;; exception with no param + (func $br_on_exn-target-block (local $exn exnref) + ;; Here this block $x is targeted by br_on_exn, so code folding out of this + ;; block should NOT happen. + (block $x + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (if (i32.const 0) + (block + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + (drop (br_on_exn $x $e (local.get $exn))) + ;; no fallthrough, another thing to merge + (drop (i32.const 1)) + (drop (i32.const 2)) + (br $x) + ) + ) + + (func $foo) + (func $try-call-optimize-terminating-tails (result exnref) + (try + (do + ;; Expressions that can throw should NOT be taken out of 'try' scope. + (call $foo) + (call $foo) + (call $foo) + (call $foo) + (return (ref.null exn)) + ) + (catch + (drop (pop exnref)) + (call $foo) + (call $foo) + (call $foo) + (call $foo) + (return (ref.null exn)) + ) + ) + (ref.null exn) + ) + + (func $try-call-optimize-expression-tails (local $exn exnref) + (block $x + (try + (do + ;; Expressions that can throw should NOT be taken out of 'try' scope. + (call $foo) + (call $foo) + (call $foo) + (br $x) + ) + (catch + (local.set $exn (pop exnref)) + (call $foo) + (call $foo) + (call $foo) + (br $x) + ) + ) + (unreachable) + ) + ) +) diff -Nru binaryen-108/test/passes/remove-unused-names_code-folding.txt binaryen-99/test/passes/remove-unused-names_code-folding.txt --- binaryen-108/test/passes/remove-unused-names_code-folding.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_code-folding.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,1711 +0,0 @@ -(module - (type $none_=>_none (func)) - (type $none_=>_i32 (func (result i32))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (func $ifs - (if - (i32.const 0) - (nop) - ) - (block - (drop - (i32.const 0) - ) - (nop) - ) - (if - (i32.const 0) - (nop) - (unreachable) - ) - (drop - (block (result i32) - (drop - (i32.const 0) - ) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (drop - (if (result i32) - (i32.const 0) - (i32.add - (i32.const 1) - (i32.const 2) - ) - (i32.add - (i32.const 1) - (i32.const 333333333) - ) - ) - ) - ) - (func $ifs-blocks - (block - (drop - (i32.const 0) - ) - (block - (nop) - ) - ) - (block - (if - (i32.const 0) - (unreachable) - (block - ) - ) - (nop) - ) - (block - (if - (i32.const 0) - (block - ) - (unreachable) - ) - (nop) - ) - (if - (i32.const 0) - (block - (nop) - (unreachable) - ) - (nop) - ) - (if - (i32.const 0) - (nop) - (block - (nop) - (unreachable) - ) - ) - ) - (func $ifs-blocks-big - (block - (drop - (i32.const 0) - ) - (block - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - ) - (block - (if - (i32.const 0) - (unreachable) - (block - ) - ) - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (block - (if - (i32.const 0) - (block - ) - (unreachable) - ) - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (if - (i32.const 0) - (block - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - (unreachable) - ) - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (if - (i32.const 0) - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - (block - (drop - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - (unreachable) - ) - ) - ) - (func $ifs-blocks-long - (block - (if - (i32.const 1) - (block - (drop - (i32.const -1234) - ) - (drop - (i32.const -1000) - ) - ) - (drop - (i32.const 999) - ) - ) - (drop - (i32.const 1) - ) - (nop) - (unreachable) - ) - (drop - (block (result i32) - (if - (i32.const 2) - (block - (drop - (i32.const -1234) - ) - (drop - (i32.const -1000) - ) - ) - (drop - (i32.const 999) - ) - ) - (drop - (i32.const 1) - ) - (nop) - (unreachable) - (i32.const 2) - ) - ) - (drop - (block (result i32) - (if - (i32.const 3) - (block - (drop - (i32.const -1234) - ) - (drop - (i32.const -1000) - ) - ) - (drop - (i32.const 999) - ) - ) - (drop - (i32.const 1) - ) - (nop) - (i32.const 2) - ) - ) - ) - (func $if-worth-it-i-dunno - (block $folding-inner0 - (block - (if - (i32.const 0) - (if - (i32.const 0) - (block - (drop - (i32.const -1234) - ) - (drop - (i32.const -1000) - ) - (br $folding-inner0) - ) - (block - (drop - (i32.const 999) - ) - (drop - (i32.const 1) - ) - (br $folding-inner0) - ) - ) - ) - (if - (i32.const 0) - (block - (if - (i32.const 0) - (block - (drop - (i32.const -1234) - ) - (drop - (i32.const -1000) - ) - ) - (block - (drop - (i32.const 999) - ) - (drop - (i32.const 1) - ) - ) - ) - (unreachable) - (br $folding-inner0) - ) - ) - (if - (i32.const 0) - (block - (if - (i32.const 0) - (block - ) - (block - (drop - (i32.const 999) - ) - (drop - (i32.const 1) - ) - ) - ) - (br $folding-inner0) - ) - ) - (if - (i32.const 0) - (block - (if - (i32.const 0) - (block - (drop - (i32.const -1234) - ) - (drop - (i32.const -1000) - ) - ) - (block - ) - ) - (br $folding-inner0) - ) - ) - (block - (block - (if - (i32.const 9999) - (block - (drop - (i32.const -51234) - ) - (drop - (i32.const -51000) - ) - ) - (block - (drop - (i32.const 5999) - ) - (drop - (i32.const 51) - ) - ) - ) - (br $folding-inner0) - ) - ) - (drop - (block (result i32) - (block (result i32) - (if - (i32.const 9999) - (block - (drop - (i32.const -51234) - ) - (drop - (i32.const -51000) - ) - ) - (block - (drop - (i32.const 5999) - ) - (drop - (i32.const 51) - ) - ) - ) - (unreachable) - (i32.const 10) - ) - ) - ) - (block - (drop - (if (result i32) - (i32.const 9999) - (block (result i32) - (drop - (i32.const -51234) - ) - (drop - (i32.const -51000) - ) - (unreachable) - (i32.const 10) - ) - (block (result i32) - (drop - (i32.const 5999) - ) - (drop - (i32.const 51) - ) - (unreachable) - (i32.const 10) - ) - ) - ) - ) - ) - ) - (unreachable) - (unreachable) - ) - (func $no-grandparent - (if - (i32.const 9999) - (block - (drop - (i32.const -51234) - ) - (drop - (i32.const -51000) - ) - (unreachable) - (unreachable) - ) - (block - (drop - (i32.const 5999) - ) - (drop - (i32.const 51) - ) - (unreachable) - (unreachable) - ) - ) - ) - (func $yes-grandparent - (block - (if - (i32.const 9999) - (block - (drop - (i32.const -51234) - ) - (drop - (i32.const -51000) - ) - ) - (block - (drop - (i32.const 5999) - ) - (drop - (i32.const 51) - ) - ) - ) - (unreachable) - (unreachable) - ) - ) - (func $ifs-named-block (param $x i32) (param $y i32) (result i32) - (block $out - (block $out2 - (block - (drop - (local.get $x) - ) - (block - (br_if $out - (local.get $y) - ) - (nop) - ) - ) - (block - (if - (local.get $x) - (br_if $out - (local.get $y) - ) - (br_if $out2 - (local.get $y) - ) - ) - (nop) - ) - (if - (i32.const 1234) - (if - (local.get $x) - (block - (nop) - (br_if $out - (local.get $y) - ) - (nop) - ) - (block - (nop) - (br_if $out2 - (local.get $y) - ) - (nop) - ) - ) - ) - (if - (local.get $x) - (block $left - (br_if $left - (local.get $y) - ) - (nop) - ) - (block - (br_if $out - (local.get $y) - ) - (nop) - ) - ) - (if - (local.get $x) - (block - (br_if $out - (local.get $y) - ) - (nop) - ) - (block $right - (br_if $right - (local.get $y) - ) - (nop) - ) - ) - ) - (return - (i32.const 10) - ) - ) - (return - (i32.const 20) - ) - ) - (func $block - (block $x - (if - (i32.const 0) - (br $x) - ) - (if - (i32.const 0) - (br $x) - ) - (br $x) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (func $block2 - (block $x - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 333333) - ) - (br $x) - ) - ) - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $x) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $x) - ) - ) - (func $block3 - (block $x - (if - (i32.const 0) - (block - (drop - (i32.const 1000) - ) - (br $x) - ) - ) - (if - (i32.const 0) - (block - (drop - (i32.const 2000) - ) - (drop - (i32.const 3000) - ) - (br $x) - ) - ) - (drop - (i32.const 4000) - ) - (drop - (i32.const 5000) - ) - (drop - (i32.const 6000) - ) - (br $x) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (func $mixture - (block $out - (block - (drop - (i32.const 1) - ) - (block - (drop - (i32.const 2) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (br $out) - ) - ) - ) - (block $out2 - (block - (if - (i32.const 1) - (drop - (i32.const 3) - ) - (block - (drop - (i32.const 4) - ) - (drop - (i32.const 5) - ) - ) - ) - (drop - (i32.const 2) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (br $out2) - ) - ) - (block - (block $out3 - (block - (drop - (i32.const 1) - ) - (block - (br $out3) - ) - ) - (block - (drop - (i32.const 1) - ) - (block - (br $out3) - ) - ) - (br $out3) - ) - (drop - (i32.const 2) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - ) - ) - (func $block-corners - (block - (block $x - (if - (i32.const 0) - (br $x) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (drop - (block $y (result i32) - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $y - (i32.const 3) - ) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $y - (i32.const 3) - ) - ) - ) - (drop - (block $z (result i32) - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $z - (i32.const 2) - ) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (i32.const 3) - ) - ) - (block $w - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br_if $w - (i32.const 3) - ) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (block $x1 - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $x1) - (nop) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (block $side - (block $x2 - (br_table $x2 $side - (i32.const 0) - ) - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $x2) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (block $x3 - (br_table $side $x3 - (i32.const 0) - ) - (if - (i32.const 0) - (block - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (br $x3) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - ) - ) - (func $terminating - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - ) - (return) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (unreachable) - ) - (func $terminating-unreachable - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - (unreachable) - ) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (unreachable) - ) - (func $terminating-value (result i32) - (block $folding-inner0 - (return - (block (result i32) - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - (i32.const 4) - ) - ) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (unreachable) - ) - (func $terminating-just-2 - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (block - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (drop - (i32.const 10) - ) - (unreachable) - ) - ) - ) - (return) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (unreachable) - ) - (func $terminating-shortness - (block $folding-inner1 - (block - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner1) - ) - (if - (i32.const 3) - (block - (drop - (i32.const 10) - ) - (br $folding-inner0) - ) - ) - ) - (return) - ) - (nop) - (br $folding-inner1) - ) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (unreachable) - ) - (func $terminating-multiple-separate - (block $folding-inner1 - (block - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 1) - (br $folding-inner1) - ) - (if - (i32.const 1) - (br $folding-inner1) - ) - ) - (return) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (drop - (i32.const 1) - ) - (unreachable) - ) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (drop - (i32.const 2) - ) - (unreachable) - ) - (func $terminating-just-worth-it - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - ) - (return) - ) - (nop) - (nop) - (nop) - (unreachable) - ) - (func $terminating-not-worth-it - (if - (i32.const 1) - (block - (nop) - (nop) - (unreachable) - ) - ) - (if - (i32.const 2) - (block - (nop) - (nop) - (unreachable) - ) - ) - (if - (i32.const 3) - (block - (nop) - (nop) - (unreachable) - ) - ) - ) - (func $terminating-return - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - ) - (return) - ) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (nop) - (return) - ) - (func $terminating-return-value (result i32) - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - (if - (i32.const 3) - (block - (nop) - (return - (i32.add - (i32.const 111111111) - (i32.const 2222222) - ) - ) - ) - ) - (return - (i32.const 1234) - ) - ) - ) - (nop) - (return - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (func $terminating-fallthrough-value (result i32) - (block $folding-inner0 - (return - (block (result i32) - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - (if - (i32.const 3) - (block - (nop) - (return - (i32.add - (i32.const 111111111) - (i32.const 2222222) - ) - ) - ) - ) - (i32.const 1234) - ) - ) - ) - (nop) - (return - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (func $big-return (result i32) - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - (if - (i32.const 4) - (br $folding-inner0) - ) - (if - (i32.const 5) - (br $folding-inner0) - ) - (if - (i32.const 6) - (br $folding-inner0) - ) - (unreachable) - ) - ) - (return - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (func $return-mix (result i32) - (block $folding-inner0 - (block - (if - (i32.const 1) - (br $folding-inner0) - ) - (if - (i32.const 2) - (br $folding-inner0) - ) - (if - (i32.const 3) - (br $folding-inner0) - ) - (if - (i32.const 4) - (br $folding-inner0) - ) - (if - (i32.const 3) - (return - (i32.add - (i32.const 1) - (i32.const 234567) - ) - ) - ) - (br $folding-inner0) - ) - ) - (return - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (func $just-unreachable - (unreachable) - ) - (func $just-return (result i32) - (return - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - (func $drop-if-with-value-but-unreachable - (if - (i32.const 0) - (nop) - ) - (block - (drop - (i32.const 0) - ) - (block - (nop) - ) - ) - (if - (i32.const 0) - (nop) - (unreachable) - ) - (nop) - (drop - (block (result i32) - (drop - (unreachable) - ) - (block (result i32) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - ) - (drop - (if (result i32) - (i32.const 0) - (i32.add - (i32.const 1) - (i32.const 2) - ) - (i32.add - (i32.const 1) - (i32.const 333333333) - ) - ) - ) - ) - (func $nested-control-flow - (block $out - (block - (block $x - (if - (i32.const 0) - (br $x) - ) - (if - (i32.const 0) - (br $x) - ) - (br $x) - ) - (if - (i32.const 1) - (br $out) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (drop - (i32.const 3) - ) - ) - ) - (func $nested-control-flow-dangerous - (block $folding-inner0 - (block $out - (block - (if - (i32.const 0) - (block - (if - (i32.const 1) - (br $out) - ) - (br $folding-inner0) - ) - ) - (if - (i32.const 0) - (block - (if - (i32.const 1) - (br $out) - ) - (br $folding-inner0) - ) - ) - (if - (i32.const 1) - (br $out) - ) - (br $folding-inner0) - ) - (drop - (i32.const 3) - ) - ) - (return) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (return) - ) - (func $nested-control-flow-dangerous-but-ok - (block $folding-inner0 - (block - (block $middle - (block - (if - (i32.const 0) - (block - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $middle) - ) - (br $folding-inner0) - ) - ) - (if - (i32.const 0) - (block - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $middle) - ) - (br $folding-inner0) - ) - ) - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $middle) - ) - (br $folding-inner0) - ) - ) - (drop - (i32.const 3) - ) - ) - (return) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (return) - ) - (func $nested-control-flow-dangerous-but-ok-b - (block $out - (block $middle - (block - (if - (i32.const 0) - (block - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $middle) - ) - (br $out) - ) - ) - (if - (i32.const 0) - (block - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $middle) - ) - (br $out) - ) - ) - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $middle) - ) - ) - ) - (unreachable) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (drop - (i32.const 3) - ) - (drop - (i32.const 4) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - (drop - (i32.const 3) - ) - (drop - (i32.const 4) - ) - ) - (func $nested-control-flow-dangerous-but-ok-c - (block $x - (block - (block $out - (block - (if - (i32.const 0) - (br $out) - ) - (if - (i32.const 0) - (br $out) - ) - (br $out) - ) - (unreachable) - ) - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $x) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (unreachable) - ) - (drop - (i32.const 5) - ) - ) - (func $nested-control-flow-dangerous-but-ok-d - (block - (block $out - (block - (if - (i32.const 0) - (br $out) - ) - (if - (i32.const 0) - (br $out) - ) - (br $out) - ) - ) - (block $x - (if - (i32.add - (i32.const 0) - (i32.const 1) - ) - (br $x) - ) - ) - (drop - (i32.const 1) - ) - (drop - (i32.const 2) - ) - ) - (drop - (i32.const 3) - ) - ) - (func $if-suffix (param $x i32) (result i32) - (block - (if - (local.get $x) - (block - ) - (drop - (call $if-suffix - (i32.const -1) - ) - ) - ) - (local.set $x - (i32.const 1) - ) - ) - (block (result i32) - (if - (local.get $x) - (block - ) - (drop - (call $if-suffix - (i32.const -2) - ) - ) - ) - (i32.const 2) - ) - ) -) diff -Nru binaryen-108/test/passes/remove-unused-names_code-folding.wast binaryen-99/test/passes/remove-unused-names_code-folding.wast --- binaryen-108/test/passes/remove-unused-names_code-folding.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_code-folding.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,1194 +0,0 @@ -(module - (func $ifs - (if (i32.const 0) (nop)) - (if (i32.const 0) (nop) (nop)) - (if (i32.const 0) (nop) (unreachable)) - (drop - (if (result i32) (i32.const 0) - (i32.add (i32.const 1) (i32.const 2)) - (i32.add (i32.const 1) (i32.const 2)) - ) - ) - (drop - (if (result i32) (i32.const 0) - (i32.add (i32.const 1) (i32.const 2)) - (i32.add (i32.const 1) (i32.const 333333333)) - ) - ) - ) - (func $ifs-blocks - (if (i32.const 0) - (block - (nop) - ) - (block - (nop) - ) - ) - (if (i32.const 0) - (block - (unreachable) - (nop) - ) - (block - (nop) - ) - ) - (if (i32.const 0) - (block - (nop) - ) - (block - (unreachable) - (nop) - ) - ) - (if (i32.const 0) - (block - (nop) - (unreachable) - ) - (block - (nop) - ) - ) - (if (i32.const 0) - (block - (nop) - ) - (block - (nop) - (unreachable) - ) - ) - ) - (func $ifs-blocks-big - (if (i32.const 0) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 0) - (block - (unreachable) - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 0) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - (block - (unreachable) - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 0) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - (unreachable) - ) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 0) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - ) - (block - (drop (i32.add (i32.const 1) (i32.const 2))) - (unreachable) - ) - ) - ) - (func $ifs-blocks-long - (if (i32.const 1) - (block - (drop (i32.const -1234)) - (drop (i32.const -1000)) - (drop (i32.const 1)) - (nop) - (unreachable) - ) - (block - (drop (i32.const 999)) - (drop (i32.const 1)) - (nop) - (unreachable) - ) - ) - (drop - (if (result i32) (i32.const 2) - (block (result i32) - (drop (i32.const -1234)) - (drop (i32.const -1000)) - (drop (i32.const 1)) - (nop) - (unreachable) - (i32.const 2) - ) - (block (result i32) - (drop (i32.const 999)) - (drop (i32.const 1)) - (nop) - (unreachable) - (i32.const 2) - ) - ) - ) - (drop - (if (result i32) (i32.const 3) - (block (result i32) - (drop (i32.const -1234)) - (drop (i32.const -1000)) - (drop (i32.const 1)) - (nop) - (i32.const 2) - ) - (block (result i32) - (drop (i32.const 999)) - (drop (i32.const 1)) - (nop) - (i32.const 2) - ) - ) - ) - ) - (func $if-worth-it-i-dunno - ;; just 2, so not worth it - (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) - (if (i32.const 0) - (block - (drop (i32.const -1234)) - (drop (i32.const -1000)) - (unreachable) - (unreachable) - ) - (block - (drop (i32.const 999)) - (drop (i32.const 1)) - (unreachable) - (unreachable) - ) - ) - ) - ;; 3, so why not - (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) - (if (i32.const 0) - (block - (drop (i32.const -1234)) - (drop (i32.const -1000)) - (unreachable) - (unreachable) - (unreachable) - ) - (block - (drop (i32.const 999)) - (drop (i32.const 1)) - (unreachable) - (unreachable) - (unreachable) - ) - ) - ) - ;; just 2, but we'll empty out a block - (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) - (if (i32.const 0) - (block - (unreachable) - (unreachable) - ) - (block - (drop (i32.const 999)) - (drop (i32.const 1)) - (unreachable) - (unreachable) - ) - ) - ) - ;; just 2, but we'll empty out a block - (if (i32.const 0) ;; (put them in ifs, so no block outside which would make us more confident in creating a block in hopes it would vanish) - (if (i32.const 0) - (block - (drop (i32.const -1234)) - (drop (i32.const -1000)) - (unreachable) - (unreachable) - ) - (block - (unreachable) - (unreachable) - ) - ) - ) - ;; just two, but on a block, so we hope to merge, and can optimize here - (block $a-holding-block - (if (i32.const 9999) - (block - (drop (i32.const -51234)) - (drop (i32.const -51000)) - (unreachable) - (unreachable) - ) - (block - (drop (i32.const 5999)) - (drop (i32.const 51)) - (unreachable) - (unreachable) - ) - ) - ) - ;; with value - (drop - (block $b-holding-block (result i32) - (if (result i32) (i32.const 9999) - (block (result i32) - (drop (i32.const -51234)) - (drop (i32.const -51000)) - (unreachable) - (i32.const 10) - ) - (block (result i32) - (drop (i32.const 5999)) - (drop (i32.const 51)) - (unreachable) - (i32.const 10) - ) - ) - ) - ) - ;; oops, something in between - (block $c-holding-block - (drop - (if (result i32) (i32.const 9999) - (block (result i32) - (drop (i32.const -51234)) - (drop (i32.const -51000)) - (unreachable) - (i32.const 10) - ) - (block (result i32) - (drop (i32.const 5999)) - (drop (i32.const 51)) - (unreachable) - (i32.const 10) - ) - ) - ) - ) - ) - (func $no-grandparent - ;; if we had a parent block, we might optimize this - (if (i32.const 9999) - (block - (drop (i32.const -51234)) - (drop (i32.const -51000)) - (unreachable) - (unreachable) - ) - (block - (drop (i32.const 5999)) - (drop (i32.const 51)) - (unreachable) - (unreachable) - ) - ) - ) - (func $yes-grandparent - (block - (if (i32.const 9999) - (block - (drop (i32.const -51234)) - (drop (i32.const -51000)) - (unreachable) - (unreachable) - ) - (block - (drop (i32.const 5999)) - (drop (i32.const 51)) - (unreachable) - (unreachable) - ) - ) - ) - ) - (func $ifs-named-block (param $x i32) (param $y i32) (result i32) - (block $out - (block $out2 - (if (local.get $x) - (block - (br_if $out (local.get $y i32)) - (nop) - ) - (block - (br_if $out (local.get $y i32)) - (nop) - ) - ) - (if (local.get $x) - (block - (br_if $out (local.get $y i32)) - (nop) - ) - (block - (br_if $out2 (local.get $y i32)) - (nop) - ) - ) - (if (i32.const 1234) - (if (local.get $x) - (block - (nop) - (br_if $out (local.get $y i32)) - (nop) - ) - (block - (nop) - (br_if $out2 (local.get $y i32)) - (nop) - ) - ) - ) - (if (local.get $x) - (block $left - (br_if $left (local.get $y i32)) - (nop) - ) - (block - (br_if $out (local.get $y i32)) - (nop) - ) - ) - (if (local.get $x) - (block - (br_if $out (local.get $y i32)) - (nop) - ) - (block $right - (br_if $right (local.get $y i32)) - (nop) - ) - ) - ) - (return (i32.const 10)) - ) - (return (i32.const 20)) - ) - (func $block - (block $x - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - ;; no fallthrough, another thing to merge - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (func $block2 - (block $x - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 333333)) - (br $x) - ) - ) - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - ;; no fallthrough, another thing to merge - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (func $block3 - (block $x - (if (i32.const 0) - (block - (drop (i32.const 1000)) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (if (i32.const 0) - (block - (drop (i32.const 2000)) - (drop (i32.const 3000)) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (drop (i32.const 4000)) - (drop (i32.const 5000)) - (drop (i32.const 6000)) - ;; no fallthrough, another thing to merge - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (func $mixture - (block $out ;; then we reach the block, and the tail infos are stale, should ignore - (if (i32.const 1) ;; then we optimize the if, pushing those brs outside! - (block - (drop (i32.const 2)) ;; first we note the block tails for $out - (nop) (nop) (nop) (nop) (nop) (nop) ;; totally worth it - (br $out) - ) - (block - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out) - ) - ) - ) - (block $out2 - (if (i32.const 1) - (block - (drop (i32.const 3)) ;; leave something - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out2) - ) - (block - (drop (i32.const 4)) ;; leave something - (drop (i32.const 5)) ;; leave something - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out2) - ) - ) - ) - ;; now a case where do **do** want to fold for the block (which we can only do in a later pass) - (block $out3 - (if (i32.const 1) - (block - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out3) - ) - (block - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out3) - ) - ) - (if (i32.const 1) - (block - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out3) - ) - (block - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out3) - ) - ) - (drop (i32.const 2)) - (nop) (nop) (nop) (nop) (nop) (nop) - (br $out3) - ) - ) - (func $block-corners - ;; these should be merged - (block $x - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - ) - ;; these should not - ;; values - (drop - (block $y (result i32) - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $y (i32.const 3)) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $y (i32.const 3)) - ) - ) - (drop - (block $z (result i32) - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $z (i32.const 2)) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (i32.const 3) - ) - ) - ;; condition - (block $w - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br_if $w (i32.const 3)) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - ) - ;; not at the end - (block $x1 - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x1) - (nop) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - ) - ;; switches - (block $side - (block $x2 - (br_table $x2 $side (i32.const 0)) - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x2) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - ) - (block $x3 - (br_table $side $x3 (i32.const 0)) - (if (i32.const 0) - (block - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x3) - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - ) - ) - ) - (func $terminating - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - ) - (func $terminating-unreachable - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (unreachable) - ) - (func $terminating-value (result i32) - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (i32.const 4) - ) - (func $terminating-just-2 - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (drop (i32.const 10)) - (unreachable) - ) - ) - ) - (func $terminating-shortness - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) ;; shorter. we do the two long ones greedily, then the merged one and this can also be opted - (unreachable) - ) - ) - (if (i32.const 3) - (block - (drop (i32.const 10)) - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (unreachable) - ) - ) - ) - (func $terminating-multiple-separate - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (drop (i32.const 1)) - (unreachable) - ) - ) - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (drop (i32.const 1)) - (unreachable) - ) - ) - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (drop (i32.const 2)) - (unreachable) - ) - ) - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (drop (i32.const 2)) - (unreachable) - ) - ) - ) - (func $terminating-just-worth-it - (if (i32.const 1) - (block - (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) (nop) - (unreachable) - ) - ) - ) - (func $terminating-not-worth-it - (if (i32.const 1) - (block - (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) - (unreachable) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) - (unreachable) - ) - ) - ) - (func $terminating-return - (if (i32.const 1) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (return) - ) - ) - (if (i32.const 2) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (return) - ) - ) - (if (i32.const 3) - (block - (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) (nop) - (return) - ) - ) - ) - (func $terminating-return-value (result i32) - (if (i32.const 1) - (block - (nop) - (return (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 2) - (block - (nop) - (return (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 3) - (block - (nop) - (return (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 3) - (block - (nop) - (return (i32.add (i32.const 111111111) (i32.const 2222222))) - ) - ) - (return (i32.const 1234)) - ) - (func $terminating-fallthrough-value (result i32) - (if (i32.const 1) - (block - (nop) - (return (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 2) - (block - (nop) - (return (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 3) - (block - (nop) - (return (i32.add (i32.const 1) (i32.const 2))) - ) - ) - (if (i32.const 3) - (block - (nop) - (return (i32.add (i32.const 111111111) (i32.const 2222222))) - ) - ) - (i32.const 1234) - ) - (func $big-return (result i32) - (if (i32.const 1) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 2) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 4) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 5) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 6) (return (i32.add (i32.const 1) (i32.const 2)))) - (unreachable) - ) - (func $return-mix (result i32) - (if (i32.const 1) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 2) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 4) (return (i32.add (i32.const 1) (i32.const 2)))) - (if (i32.const 3) (return (i32.add (i32.const 1) (i32.const 234567)))) - (return (i32.add (i32.const 1) (i32.const 2))) ;; on a block, and the toplevel in fact - ) - (func $just-unreachable - (unreachable) - ) - (func $just-return (result i32) - (return (i32.add (i32.const 1) (i32.const 2))) ;; on a block, and the toplevel in fact - ) - (func $drop-if-with-value-but-unreachable - (block $label$0 - (if - (i32.const 0) - (block $label$1 - (nop) - ) - ) - (if - (i32.const 0) - (block $label$2 - (nop) - ) - (block $label$3 - (nop) - ) - ) - (if - (i32.const 0) - (block $label$4 - (nop) - ) - (block $label$5 - (unreachable) - ) - ) - (nop) - (drop - (if (result i32) ;; we replace this if, must replace with same type! - (unreachable) - (block $label$6 (result i32) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - (block $label$7 (result i32) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - ) - ) - (drop - (if (result i32) - (i32.const 0) - (block $label$8 (result i32) - (i32.add - (i32.const 1) - (i32.const 2) - ) - ) - (block $label$9 (result i32) - (i32.add - (i32.const 1) - (i32.const 333333333) - ) - ) - ) - ) - ) - ) - (func $nested-control-flow - (block $out - (block $x - (if (i32.const 0) - (block - (if (i32.const 1) - (br $out) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - (if (i32.const 0) - (block - (if (i32.const 1) - (br $out) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - ) - ;; no fallthrough, another thing to merge - (if (i32.const 1) - (br $out) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $x) - ) - (drop (i32.const 3)) - ) - ) - (func $nested-control-flow-dangerous - (block $out - (block $x - (if (i32.const 0) - (block - (if (i32.const 1) - (br $out) ;; this br cannot be moved out of the $out block! - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (return) - ) - ) - (if (i32.const 0) - (block - (if (i32.const 1) - (br $out) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (return) - ) - ) - ;; no fallthrough, another thing to merge - (if (i32.const 1) - (br $out) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (return) - ) - (drop (i32.const 3)) - ) - ) - (func $nested-control-flow-dangerous-but-ok - (block $out - (block $middle - (block $x - (if (i32.const 0) - (block - (if (i32.add (i32.const 0) (i32.const 1)) - (br $middle) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (return) - ) - ) - (if (i32.const 0) - (block - (if (i32.add (i32.const 0) (i32.const 1)) - (br $middle) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (return) - ) - ) - ;; no fallthrough, another thing to merge - (if (i32.add (i32.const 0) (i32.const 1)) - (br $middle) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (return) - ) - ) - (drop (i32.const 3)) - ) - ) - (func $nested-control-flow-dangerous-but-ok-b - (block $out - (block $middle - (block $x - (if (i32.const 0) - (block - (if (i32.add (i32.const 0) (i32.const 1)) - (br $middle) ;; this is dangerous - we branch to middle with is inside out, so we can't move this out of out - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (drop (i32.const 3)) - (drop (i32.const 4)) - (drop (i32.const 1)) - (drop (i32.const 2)) - (drop (i32.const 3)) - (drop (i32.const 4)) - (br $out) - ) - ) - (if (i32.const 0) - (block - (if (i32.add (i32.const 0) (i32.const 1)) - (br $middle) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (drop (i32.const 3)) - (drop (i32.const 4)) - (drop (i32.const 1)) - (drop (i32.const 2)) - (drop (i32.const 3)) - (drop (i32.const 4)) - (br $out) - ) - ) - ;; no fallthrough, another thing to merge - (if (i32.add (i32.const 0) (i32.const 1)) - (br $middle) - ) - ) - ) - (unreachable) ;; no fallthrough - ) - ) - (func $nested-control-flow-dangerous-but-ok-c - (block $x - (block $out - (block $middle - (if (i32.const 0) - (block - (if (i32.add (i32.const 0) (i32.const 1)) - (br $x) ;; this is ok - we branch to x which is outside of out - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $out) - ) - ) - (if (i32.const 0) - (block - (if (i32.add (i32.const 0) (i32.const 1)) - (br $x) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $out) - ) - ) - ;; no fallthrough, another thing to merge - (if (i32.add (i32.const 0) (i32.const 1)) - (br $x) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $out) - ) - (unreachable) ;; no fallthrough - ) - (unreachable) ;; no fallthrough - ) - (drop (i32.const 5)) - ) - (func $nested-control-flow-dangerous-but-ok-d - (block $out - (block $middle - (if (i32.const 0) - (block - (block $x - (if (i32.add (i32.const 0) (i32.const 1)) - (br $x) ;; this is ok - we branch to x which is nested in us - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $out) - ) - ) - (if (i32.const 0) - (block - (block $x - (if (i32.add (i32.const 0) (i32.const 1)) - (br $x) ;; this is ok - we branch to x which is nested in us - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $out) - ) - ) - ;; no fallthrough, another thing to merge - (block $x - (if (i32.add (i32.const 0) (i32.const 1)) - (br $x) ;; this is ok - we branch to x which is nested in us - ) - ) - (drop (i32.const 1)) - (drop (i32.const 2)) - (br $out) - ) - ) - (drop (i32.const 3)) - ) - (func $if-suffix (param $x i32) (result i32) - (if - (local.get $x) - (local.set $x (i32.const 1)) - (block - (drop (call $if-suffix (i32.const -1))) - (local.set $x (i32.const 1)) - ) - ) - (if (result i32) - (local.get $x) - (i32.const 2) - (block (result i32) - (drop (call $if-suffix (i32.const -2))) - (i32.const 2) - ) - ) - ) -) diff -Nru binaryen-108/test/passes/remove-unused-names_merge-blocks_all-features.txt binaryen-99/test/passes/remove-unused-names_merge-blocks_all-features.txt --- binaryen-108/test/passes/remove-unused-names_merge-blocks_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_merge-blocks_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module - (type $3 (func)) - (type $i (func (param i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) (type $none_=>_i32 (func (result i32))) - (type $ii (func (param i32 i32))) - (type $iii (func (param i32 i32 i32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $none_=>_f64 (func (result f64))) (memory $0 (shared 256 256)) (table $0 1 1 funcref) @@ -300,15 +300,15 @@ ) ) (drop - (i32.const 20) - ) - (drop - (i32.add - (block (result i32) - (unreachable) + (block (result i32) + (unreachable) + (drop + (i32.const 20) + ) + (i32.add (i32.const 10) + (i32.const 30) ) - (i32.const 30) ) ) ) @@ -417,28 +417,26 @@ ) ) (drop - (i32.const 30) - ) - (drop - (i32.const 50) - ) - (drop (select (block (result i32) (unreachable) (i32.const 20) ) - (i32.const 40) - (i32.const 60) + (block (result i32) + (drop + (i32.const 30) + ) + (i32.const 40) + ) + (block (result i32) + (drop + (i32.const 50) + ) + (i32.const 60) + ) ) ) (drop - (i32.const 30) - ) - (drop - (i32.const 50) - ) - (drop (select (block (result i32) (drop @@ -446,33 +444,42 @@ ) (unreachable) ) - (i32.const 40) - (i32.const 60) + (block (result i32) + (drop + (i32.const 30) + ) + (i32.const 40) + ) + (block (result i32) + (drop + (i32.const 50) + ) + (i32.const 60) + ) ) ) (drop (i32.const 10) ) (drop - (i32.const 50) - ) - (drop (select (i32.const 20) (block (result i32) (unreachable) (i32.const 40) ) - (i32.const 60) + (block (result i32) + (drop + (i32.const 50) + ) + (i32.const 60) + ) ) ) (drop (i32.const 10) ) (drop - (i32.const 50) - ) - (drop (select (i32.const 20) (block (result i32) @@ -481,7 +488,12 @@ ) (unreachable) ) - (i32.const 60) + (block (result i32) + (drop + (i32.const 50) + ) + (i32.const 60) + ) ) ) (drop @@ -600,18 +612,17 @@ (i32.const 20) (i32.const 40) ) - (drop - (i32.const 20) - ) (call $call-ii (block (result i32) (unreachable) (i32.const 10) ) - (i32.const 30) - ) - (drop - (i32.const 20) + (block (result i32) + (drop + (i32.const 20) + ) + (i32.const 30) + ) ) (call $call-ii (block (result i32) @@ -620,7 +631,12 @@ ) (unreachable) ) - (i32.const 30) + (block (result i32) + (drop + (i32.const 20) + ) + (i32.const 30) + ) ) (drop (i32.const 10) @@ -678,32 +694,38 @@ (drop (i32.const 50) ) - (call_indirect $0 (type $ii) + (call_indirect (type $i32_i32_=>_none) (i32.const 20) (i32.const 40) (i32.const 60) ) - (drop - (i32.const 30) - ) - (drop - (i32.const 50) - ) - (call_indirect $0 (type $ii) + (call_indirect (type $i32_i32_=>_none) (unreachable) - (i32.const 40) - (i32.const 60) + (block (result i32) + (drop + (i32.const 30) + ) + (i32.const 40) + ) + (block (result i32) + (drop + (i32.const 50) + ) + (i32.const 60) + ) ) (drop (i32.const 31) ) - (drop - (i32.const 51) - ) - (call_indirect $0 (type $ii) + (call_indirect (type $i32_i32_=>_none) (i32.const 41) (unreachable) - (i32.const 61) + (block (result i32) + (drop + (i32.const 51) + ) + (i32.const 61) + ) ) (drop (i32.const 32) @@ -711,7 +733,7 @@ (drop (i32.const 52) ) - (call_indirect $0 (type $ii) + (call_indirect (type $i32_i32_=>_none) (i32.const 42) (i32.const 62) (unreachable) @@ -761,11 +783,13 @@ (func $block-type-change (local $0 f64) (local $1 f64) - (nop) (if - (f64.gt - (local.get $0) - (local.get $1) + (block (result i32) + (nop) + (f64.gt + (local.get $0) + (local.get $1) + ) ) (nop) ) @@ -1676,7 +1700,8 @@ (module (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) - (tag $e (param i32)) + (type $none_=>_i32 (func (result i32))) + (event $e (attr 0) (param i32)) (func $foo (nop) ) @@ -1686,4 +1711,36 @@ (i32.const 3) ) ) + (func $rethrow + (local $0 exnref) + (call $foo) + (rethrow + (local.get $0) + ) + ) + (func $br_on_exn (result i32) + (local $0 exnref) + (block $label$0 (result i32) + (call $foo) + (drop + (br_on_exn $label$0 $e + (local.get $0) + ) + ) + (i32.const 3) + ) + ) + (func $cannot_extract_br_on_exn_exnref + (local $0 exnref) + (drop + (block $label$0 (result i32) + (drop + (br_on_exn $label$0 $e + (local.get $0) + ) + ) + (i32.const 5) + ) + ) + ) ) diff -Nru binaryen-108/test/passes/remove-unused-names_merge-blocks_all-features.wast binaryen-99/test/passes/remove-unused-names_merge-blocks_all-features.wast --- binaryen-108/test/passes/remove-unused-names_merge-blocks_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_merge-blocks_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1558,7 +1558,7 @@ ) (module - (tag $e (param i32)) + (event $e (attr 0) (param i32)) (func $foo) ;; 'nop' within 'block' of `throw' can be hoisted @@ -1570,4 +1570,46 @@ ) ) ) + + ;; 'call $foo' within 'block' of `rethrow' can be hoisted + (func $rethrow (local $0 exnref) + (rethrow + (block (result exnref) + (call $foo) + (local.get $0) + ) + ) + ) + + ;; 'call $foo' within 'block' of `br_on_exn' can be hoisted + (func $br_on_exn (result i32) (local $0 exnref) + (block $label$0 (result i32) + (drop + (br_on_exn $label$0 $e + (block (result exnref) + (call $foo) + (local.get $0) + ) + ) + ) + (i32.const 3) + ) + ) + + ;; Unlike br_if, br_on_exn's exnref argument itself cannot be extracted. + ;; Without proper handling for br_on_exn in ProblemFinder, this crashes. + (func $cannot_extract_br_on_exn_exnref (local $0 exnref) + (block + (drop + (block $label$0 (result i32) + (drop + (br_on_exn $label$0 $e + (local.get $0) + ) + ) + (i32.const 5) + ) + ) + ) + ) ) diff -Nru binaryen-108/test/passes/remove-unused-names_optimize-instructions_all-features.txt binaryen-99/test/passes/remove-unused-names_optimize-instructions_all-features.txt --- binaryen-108/test/passes/remove-unused-names_optimize-instructions_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_optimize-instructions_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,110 @@ +(module + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (event $e (attr 0) (param i32)) + (func $dummy + (nop) + ) + (func $getFallthrough + (local $x0 i32) + (local $x1 i32) + (local $x2 i32) + (local $x3 i32) + (local.set $x0 + (try (result i32) + (do + (i32.const 1) + ) + (catch + (drop + (pop exnref) + ) + (i32.const 3) + ) + ) + ) + (drop + (local.get $x0) + ) + (local.set $x1 + (try (result i32) + (do + (call $dummy) + (i32.const 1) + ) + (catch + (drop + (pop exnref) + ) + (i32.const 3) + ) + ) + ) + (drop + (i32.and + (local.get $x1) + (i32.const 7) + ) + ) + (local.set $x2 + (try (result i32) + (do + (try + (do + (throw $e + (i32.const 0) + ) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (i32.const 1) + ) + (catch + (drop + (pop exnref) + ) + (i32.const 3) + ) + ) + ) + (drop + (local.get $x2) + ) + (local.set $x3 + (try (result i32) + (do + (try + (do + (nop) + ) + (catch + (drop + (pop exnref) + ) + (throw $e + (i32.const 0) + ) + ) + ) + (i32.const 1) + ) + (catch + (drop + (pop exnref) + ) + (i32.const 3) + ) + ) + ) + (drop + (i32.and + (local.get $x3) + (i32.const 7) + ) + ) + ) +) diff -Nru binaryen-108/test/passes/remove-unused-names_optimize-instructions_all-features.wast binaryen-99/test/passes/remove-unused-names_optimize-instructions_all-features.wast --- binaryen-108/test/passes/remove-unused-names_optimize-instructions_all-features.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_optimize-instructions_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,83 @@ +(module + (func $dummy) + (event $e (attr 0) (param i32)) + + (func $getFallthrough ;; unit tests for Properties::getFallthrough + (local $x0 i32) + (local $x1 i32) + (local $x2 i32) + (local $x3 i32) + + ;; try - try body does not throw, can + (local.set $x0 + (try (result i32) + (do + (i32.const 1) + ) + (catch + (drop (pop exnref)) + (i32.const 3) + ) + ) + ) + (drop (i32.and (local.get $x0) (i32.const 7))) + + ;; try - try body may throw, can't + (local.set $x1 + (try (result i32) + (do + (call $dummy) + (i32.const 1) + ) + (catch + (drop (pop exnref)) + (i32.const 3) + ) + ) + ) + (drop (i32.and (local.get $x1) (i32.const 7))) + + ;; nested try - inner try may throw but will be caught by inner catch, can + (local.set $x2 + (try (result i32) + (do + (try + (do + (throw $e (i32.const 0)) + ) + (catch + (drop (pop exnref)) + ) + ) + (i32.const 1) + ) + (catch + (drop (pop exnref)) + (i32.const 3) + ) + ) + ) + (drop (i32.and (local.get $x2) (i32.const 7))) + + ;; nested try - inner catch may throw, can't + (local.set $x3 + (try (result i32) + (do + (try + (do) + (catch + (drop (pop exnref)) + (throw $e (i32.const 0)) + ) + ) + (i32.const 1) + ) + (catch + (drop (pop exnref)) + (i32.const 3) + ) + ) + ) + (drop (i32.and (local.get $x3) (i32.const 7))) + ) +) diff -Nru binaryen-108/test/passes/remove-unused-names_remove-unused-brs_vacuum.txt binaryen-99/test/passes/remove-unused-names_remove-unused-brs_vacuum.txt --- binaryen-108/test/passes/remove-unused-names_remove-unused-brs_vacuum.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_remove-unused-brs_vacuum.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $4 (func (param i32))) - (type $2 (func (param i32 i32) (result i32))) - (type $5 (func (result i32))) - (type $0 (func (param i32 i32 i32) (result i32))) - (type $6 (func)) - (type $7 (func (param i32 i32))) - (type $1 (func (param f64) (result i32))) - (type $13 (func (param i32 i32 i32 i32 i32))) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) + (type $f64_=>_i32 (func (param f64) (result i32))) (type $i32_=>_i64 (func (param i32) (result i64))) (import "env" "memory" (memory $0 256)) (import "env" "table" (table $timport$0 18 18 funcref)) diff -Nru binaryen-108/test/passes/remove-unused-names.txt binaryen-99/test/passes/remove-unused-names.txt --- binaryen-108/test/passes/remove-unused-names.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $1 (func)) - (type $0 (func (param i32) (result i32))) + (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 256 256) (func $b0 (param $i1 i32) (result i32) (i32.const 0) diff -Nru binaryen-108/test/passes/remove-unused-names_vacuum_ignore-implicit-traps.txt binaryen-99/test/passes/remove-unused-names_vacuum_ignore-implicit-traps.txt --- binaryen-108/test/passes/remove-unused-names_vacuum_ignore-implicit-traps.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_vacuum_ignore-implicit-traps.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,14 +1,14 @@ (module - (type $FUNCSIG$vj (func (param i32 i32))) - (type $FUNCSIG$i (func (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $none_=>_f32 (func (result f32))) + (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (type $i64_=>_none (func (param i64))) (type $f32_=>_none (func (param f32))) - (type $none_=>_f64 (func (result f64))) (type $f64_=>_none (func (param f64))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i64 (func (result i64))) - (type $i64_=>_none (func (param i64))) - (type $0 (func)) + (type $none_=>_f32 (func (result f32))) + (type $none_=>_f64 (func (result f64))) (import "env" "wasm2js_scratch_load_i32" (func $wasm2js_scratch_load_i32 (param i32) (result i32))) (import "env" "wasm2js_scratch_store_i32" (func $wasm2js_scratch_store_i32 (param i32 i32))) (import "env" "wasm2js_scratch_load_f32" (func $wasm2js_scratch_load_f32 (result f32))) @@ -20,8 +20,8 @@ (import "env" "wasm2js_scratch_store_i64" (func $legalimport$wasm2js_scratch_store_i64 (param i32 i32))) (import "env" "wasm2js_scratch_load_i64" (func $wasm2js_scratch_load_i64 (result i64))) (import "env" "wasm2js_scratch_store_i64" (func $wasm2js_scratch_store_i64 (param i64))) - (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) (memory $0 1 1) + (global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0)) (func $0 (local $0 f64) (local $1 i32) diff -Nru binaryen-108/test/passes/remove-unused-names_vacuum.txt binaryen-99/test/passes/remove-unused-names_vacuum.txt --- binaryen-108/test/passes/remove-unused-names_vacuum.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-names_vacuum.txt 2021-01-07 20:01:06.000000000 +0000 @@ -15,7 +15,9 @@ ) (func $to-drop-unreachable (drop - (unreachable) + (block (result i32) + (unreachable) + ) ) ) (func $return-i32-but-body-is-unreachable5 (result i32) diff -Nru binaryen-108/test/passes/remove-unused-nonfunction-module-elements_all-features.txt binaryen-99/test/passes/remove-unused-nonfunction-module-elements_all-features.txt --- binaryen-108/test/passes/remove-unused-nonfunction-module-elements_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-nonfunction-module-elements_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module - (type $0 (func)) - (type $1 (func (param i32))) - (type $2 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (memory $0 0) (table $0 1 1 funcref) (elem (i32.const 0) $called_indirect) @@ -51,40 +51,40 @@ (call $remove3) ) (func $other1 (param $0 i32) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) - (call_indirect $0 (type $1) + (call_indirect (type $i32_=>_none) (i32.const 0) (i32.const 0) ) - (call_indirect $0 (type $1) + (call_indirect (type $i32_=>_none) (i32.const 0) (i32.const 0) ) (drop - (call_indirect $0 (type $2) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 0) ) ) (drop - (call_indirect $0 (type $2) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 0) ) ) (drop - (call_indirect $0 (type $2) + (call_indirect (type $i32_=>_i32) (i32.const 0) (i32.const 0) ) @@ -102,7 +102,7 @@ (import "env" "memory" (memory $0 256)) (import "env" "table" (table $timport$0 1 funcref)) (export "mem" (memory $0)) - (export "tab" (table $timport$0)) + (export "tab" (table $0)) ) (module (type $none_=>_none (func)) @@ -115,7 +115,7 @@ ) ) (module - (type $0 (func)) + (type $none_=>_none (func)) (import "env" "memory" (memory $0 256)) (import "env" "table" (table $timport$0 0 funcref)) (export "user" (func $user)) @@ -125,7 +125,7 @@ (i32.const 0) ) ) - (call_indirect $timport$0 (type $0) + (call_indirect (type $none_=>_none) (i32.const 0) ) ) @@ -224,9 +224,9 @@ (import "env" "memory" (memory $0 256)) (data (global.get $memoryBase) "hello, world!") (import "env" "table" (table $timport$0 0 funcref)) + (elem (global.get $tableBase) $waka) (import "env" "memoryBase" (global $memoryBase i32)) (import "env" "tableBase" (global $tableBase i32)) - (elem (global.get $tableBase) $waka) (func $waka (nop) ) @@ -285,7 +285,7 @@ ) ) (module - (type $0 (func (param f64) (result f64))) + (type $f64_=>_f64 (func (param f64) (result f64))) (func $0 (param $var$0 f64) (result f64) (if (result f64) (f64.eq @@ -298,7 +298,7 @@ ) ) (module - (type $0 (func (param f64) (result f64))) + (type $f64_=>_f64 (func (param f64) (result f64))) (table $0 6 6 funcref) (func $0 (param $var$0 f64) (result f64) (if (result f64) @@ -306,7 +306,7 @@ (f64.const 1) (f64.const 1) ) - (call_indirect $0 (type $0) + (call_indirect (type $f64_=>_f64) (f64.const 1) (i32.const 0) ) @@ -315,7 +315,7 @@ ) ) (module - (type $0 (func (param f64) (result f64))) + (type $f64_=>_f64 (func (param f64) (result f64))) (import "env" "table" (table $timport$0 6 6 funcref)) (elem (i32.const 0) $0) (func $0 (param $var$0 f64) (result f64) @@ -330,10 +330,10 @@ ) ) (module + (type $i32_=>_none (func (param i32))) (type $i64_=>_none (func (param i64))) - (type $0 (func (param i32))) - (tag $e1 (param i64)) - (export "e1" (tag $e1)) + (event $e1 (attr 0) (param i64)) + (export "e1" (event $e1)) (func $f (param $0 i32) (nop) ) diff -Nru binaryen-108/test/passes/remove-unused-nonfunction-module-elements_all-features.wast binaryen-99/test/passes/remove-unused-nonfunction-module-elements_all-features.wast --- binaryen-108/test/passes/remove-unused-nonfunction-module-elements_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/remove-unused-nonfunction-module-elements_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -261,11 +261,11 @@ ) ) ) -(module ;; non-exported tags can be removed +(module ;; non-exported events can be removed (type $0 (func (param i32))) - (tag $e0 (type $0)) - (tag $e1 (param i64)) - (export "e1" (tag $e1)) - (import "env" "e" (tag $e2 (param i32))) + (event $e0 (attr 0) (type $0)) + (event $e1 (attr 0) (param i64)) + (export "e1" (event $e1)) + (import "env" "e" (event $e2 (attr 0) (param i32))) (func $f (; 0 ;) (type $0)) ) diff -Nru binaryen-108/test/passes/reorder-functions.txt binaryen-99/test/passes/reorder-functions.txt --- binaryen-108/test/passes/reorder-functions.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/reorder-functions.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 256 256) (func $c (call $c) diff -Nru binaryen-108/test/passes/reorder-locals_print_roundtrip.txt binaryen-99/test/passes/reorder-locals_print_roundtrip.txt --- binaryen-108/test/passes/reorder-locals_print_roundtrip.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/reorder-locals_print_roundtrip.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -(module - (type $none_=>_none (func)) - (func $a - (local $x i32) - (local $y f64) - (drop - (local.get $x) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - (func $b - (local $y f64) - (local $x i32) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $y) - ) - ) -) -(module - (type $none_=>_none (func)) - (func $a - (local $x i32) - (local $y f64) - (drop - (local.get $x) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - ) - (func $b - (local $y f64) - (local $x i32) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $y) - ) - ) -) diff -Nru binaryen-108/test/passes/reorder-locals_print_roundtrip.wast binaryen-99/test/passes/reorder-locals_print_roundtrip.wast --- binaryen-108/test/passes/reorder-locals_print_roundtrip.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/reorder-locals_print_roundtrip.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -(module - (func $a - (local $x i32) - (local $y f64) - ;; x appears twice - (drop (local.get $x)) - (drop (local.get $x)) - (drop (local.get $y)) - ) - (func $b - (local $x i32) - (local $y f64) - ;; y appears twice, so it will be reordered to be first, and that should be - ;; preserved in the binary format - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $y)) - ) -) diff -Nru binaryen-108/test/passes/reorder-locals.txt binaryen-99/test/passes/reorder-locals.txt --- binaryen-108/test/passes/reorder-locals.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/reorder-locals.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $1 (func)) - (type $0 (func (param i32 i32))) + (type $none_=>_none (func)) + (type $i32_i32_=>_none (func (param i32 i32))) (memory $0 256 256) (func $b0-yes (param $a i32) (param $b i32) (local $z i32) diff -Nru binaryen-108/test/passes/reverse_dwarf_abbrevs.bin.txt binaryen-99/test/passes/reverse_dwarf_abbrevs.bin.txt --- binaryen-108/test/passes/reverse_dwarf_abbrevs.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/reverse_dwarf_abbrevs.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -118,8 +118,8 @@ (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) (type $i32_i64_i32_=>_i64 (func (param i32 i64 i32) (result i64))) (type $none_=>_none (func)) - (type $i32_i32_i64_i32_=>_i64 (func (param i32 i32 i64 i32) (result i64))) (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) + (type $i32_i32_i64_i32_=>_i64 (func (param i32 i32 i64 i32) (result i64))) (import "env" "memory" (memory $mimport$0 256 256)) (data (i32.const 1024) "hello, world!\00\00\00\18\04") (data (i32.const 1048) "\05") @@ -128,12 +128,12 @@ (data (i32.const 1108) "\01") (data (i32.const 1123) "\n\ff\ff\ff\ff") (import "env" "__indirect_function_table" (table $timport$0 4 funcref)) + (elem (i32.const 1) $6 $5 $7) (import "wasi_snapshot_preview1" "fd_write" (func $fimport$0 (param i32 i32 i32 i32) (result i32))) (import "env" "emscripten_memcpy_big" (func $fimport$1 (param i32 i32 i32) (result i32))) (import "env" "setTempRet0" (func $fimport$2 (param i32))) (global $global$0 (mut i32) (i32.const 5245136)) (global $global$1 i32 (i32.const 2248)) - (elem (i32.const 1) $6 $5 $7) (export "__wasm_call_ctors" (func $0)) (export "main" (func $2)) (export "__errno_location" (func $3)) diff -Nru binaryen-108/test/passes/roundtrip_signed.bin.txt binaryen-99/test/passes/roundtrip_signed.bin.txt --- binaryen-108/test/passes/roundtrip_signed.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/roundtrip_signed.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_none (func)) - (global $global$0 (mut i32) (i32.const 10)) (memory $0 16 17) + (global $global$0 (mut i32) (i32.const 10)) (export "as-br_table-index" (func $0)) (export "as-local.set-value" (func $0)) (func $0 diff -Nru binaryen-108/test/passes/roundtrip_typenames_features.passes binaryen-99/test/passes/roundtrip_typenames_features.passes --- binaryen-108/test/passes/roundtrip_typenames_features.passes 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/roundtrip_typenames_features.passes 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -enable-reference-types_enable-gc_emit-target-features_roundtrip diff -Nru binaryen-108/test/passes/roundtrip_typenames_features.txt binaryen-99/test/passes/roundtrip_typenames_features.txt --- binaryen-108/test/passes/roundtrip_typenames_features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/roundtrip_typenames_features.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -(module - (type $ref?|$NamedStruct|_=>_none (func (param (ref null $NamedStruct)))) - (type $NamedStruct (struct )) - (export "export" (func $0)) - (func $0 (param $0 (ref null $NamedStruct)) - (nop) - ) - ;; features section: reference-types, gc -) diff -Nru binaryen-108/test/passes/roundtrip_typenames_features.wast binaryen-99/test/passes/roundtrip_typenames_features.wast --- binaryen-108/test/passes/roundtrip_typenames_features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/roundtrip_typenames_features.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -;; This test enables two features, then roundtrips through binary. We should -;; preserve the features and type names while doing so. - -(module - (type $ref?|$NamedStruct|_=>_none (func (param (ref null $NamedStruct)))) - (type $NamedStruct (struct )) - (export "export" (func $0)) - (func $0 (param $0 (ref null $NamedStruct)) - (nop) - ) -) - diff -Nru binaryen-108/test/passes/rse_all-features.txt binaryen-99/test/passes/rse_all-features.txt --- binaryen-108/test/passes/rse_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/rse_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -3,6 +3,7 @@ (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_f64_=>_none (func (param i32 f64))) + (event $e (attr 0) (param i32)) (func $basic (param $x i32) (param $y f64) (local $a f32) (local $b i64) @@ -474,4 +475,136 @@ ) ) ) + (func $try1 + (local $x i32) + (try + (do + (nop) + ) + (catch + (drop + (pop exnref) + ) + (local.set $x + (i32.const 1) + ) + ) + ) + (local.set $x + (i32.const 1) + ) + ) + (func $try2 + (local $x i32) + (try + (do + (throw $e + (i32.const 0) + ) + (local.set $x + (i32.const 1) + ) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (local.set $x + (i32.const 1) + ) + ) + (func $try3 + (local $x i32) + (try + (do + (throw $e + (i32.const 0) + ) + ) + (catch + (drop + (pop exnref) + ) + (local.set $x + (i32.const 1) + ) + ) + ) + (drop + (i32.const 1) + ) + ) + (func $foo + (nop) + ) + (func $try4 + (local $x i32) + (try + (do + (call $foo) + (local.set $x + (i32.const 1) + ) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (local.set $x + (i32.const 1) + ) + ) + (func $try5 + (local $x i32) + (try + (do + (local.set $x + (i32.const 1) + ) + (call $foo) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + (drop + (i32.const 1) + ) + ) + (func $nested-try + (local $x i32) + (try + (do + (try + (do + (throw $e + (i32.const 0) + ) + ) + (catch + (rethrow + (pop exnref) + ) + ) + ) + ) + (catch + (drop + (pop exnref) + ) + (local.set $x + (i32.const 1) + ) + ) + ) + (drop + (i32.const 1) + ) + ) ) diff -Nru binaryen-108/test/passes/rse_all-features.wast binaryen-99/test/passes/rse_all-features.wast --- binaryen-108/test/passes/rse_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/rse_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -286,4 +286,90 @@ ) ) ) + + (event $e (attr 0) (param i32)) + (func $try1 + (local $x i32) + (try + (do) + (catch + (drop (pop exnref)) + (local.set $x (i32.const 1)) + ) + ) + (local.set $x (i32.const 1)) ;; should NOT be dropped + ) + (func $try2 + (local $x i32) + (try + (do + (throw $e (i32.const 0)) + (local.set $x (i32.const 1)) + ) + (catch + (drop (pop exnref)) + ) + ) + (local.set $x (i32.const 1)) ;; should NOT be dropped + ) + (func $try3 + (local $x i32) + (try + (do + (throw $e (i32.const 0)) + ) + (catch + (drop (pop exnref)) + (local.set $x (i32.const 1)) + ) + ) + (local.set $x (i32.const 1)) ;; should be dropped + ) + (func $foo) + (func $try4 + (local $x i32) + (try + (do + (call $foo) + (local.set $x (i32.const 1)) + ) + (catch + (drop (pop exnref)) + ) + ) + (local.set $x (i32.const 1)) ;; should NOT be dropped + ) + (func $try5 + (local $x i32) + (try + (do + (local.set $x (i32.const 1)) + (call $foo) + ) + (catch + (drop (pop exnref)) + ) + ) + (local.set $x (i32.const 1)) ;; should be dropped + ) + (func $nested-try + (local $x i32) + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (catch + (rethrow (pop exnref)) + ) + ) + ) + (catch + (drop (pop exnref)) + (local.set $x (i32.const 1)) + ) + ) + (local.set $x (i32.const 1)) ;; should be dropped + ) ) diff -Nru binaryen-108/test/passes/safe-heap_disable-simd.txt binaryen-99/test/passes/safe-heap_disable-simd.txt --- binaryen-108/test/passes/safe-heap_disable-simd.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/safe-heap_disable-simd.txt 2021-01-07 20:01:06.000000000 +0000 @@ -3,10 +3,10 @@ (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i32))) @@ -1916,10 +1916,10 @@ (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $foo (result i32))) @@ -3829,10 +3829,10 @@ (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) (import "env" "segfault" (func $segfault)) diff -Nru binaryen-108/test/passes/safe-heap_enable-threads_enable-simd64.txt binaryen-99/test/passes/safe-heap_enable-threads_enable-simd64.txt --- binaryen-108/test/passes/safe-heap_enable-threads_enable-simd64.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/safe-heap_enable-threads_enable-simd64.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,15 @@ (module (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) - (type $i64_i64_=>_i32 (func (param i64 i64) (result i32))) (type $i64_i64_i64_=>_none (func (param i64 i64 i64))) + (type $i64_i64_=>_i32 (func (param i64 i64) (result i32))) (type $i64_i64_i32_=>_none (func (param i64 i64 i32))) - (type $i64_i64_=>_v128 (func (param i64 i64) (result v128))) (type $i64_i64_v128_=>_none (func (param i64 i64 v128))) + (type $i64_i64_=>_v128 (func (param i64 i64) (result v128))) (type $none_=>_none (func)) - (type $i64_i64_=>_f64 (func (param i64 i64) (result f64))) (type $i64_i64_f64_=>_none (func (param i64 i64 f64))) - (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) + (type $i64_i64_=>_f64 (func (param i64 i64) (result f64))) (type $i64_i64_f32_=>_none (func (param i64 i64 f32))) + (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) (type $none_=>_i64 (func (result i64))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i64))) (import "env" "segfault" (func $segfault)) @@ -3252,13 +3252,13 @@ (type $i64_i64_i64_=>_none (func (param i64 i64 i64))) (type $i64_i64_=>_i32 (func (param i64 i64) (result i32))) (type $i64_i64_i32_=>_none (func (param i64 i64 i32))) - (type $i64_i64_=>_v128 (func (param i64 i64) (result v128))) (type $i64_i64_v128_=>_none (func (param i64 i64 v128))) - (type $i64_i64_=>_f64 (func (param i64 i64) (result f64))) + (type $i64_i64_=>_v128 (func (param i64 i64) (result v128))) (type $i64_i64_f64_=>_none (func (param i64 i64 f64))) + (type $i64_i64_=>_f64 (func (param i64 i64) (result f64))) (type $none_=>_none (func)) - (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) (type $i64_i64_f32_=>_none (func (param i64 i64 f32))) + (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) (type $none_=>_i64 (func (result i64))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i64))) (import "env" "segfault" (func $segfault)) @@ -5613,16 +5613,16 @@ ) (module (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) - (type $i64_i64_=>_i32 (func (param i64 i64) (result i32))) (type $i64_i64_i64_=>_none (func (param i64 i64 i64))) + (type $i64_i64_=>_i32 (func (param i64 i64) (result i32))) (type $i64_i64_i32_=>_none (func (param i64 i64 i32))) - (type $i64_i64_=>_v128 (func (param i64 i64) (result v128))) (type $i64_i64_v128_=>_none (func (param i64 i64 v128))) - (type $i64_i64_=>_f64 (func (param i64 i64) (result f64))) + (type $i64_i64_=>_v128 (func (param i64 i64) (result v128))) (type $i64_i64_f64_=>_none (func (param i64 i64 f64))) - (type $FUNCSIG$v (func)) - (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) + (type $i64_i64_=>_f64 (func (param i64 i64) (result f64))) + (type $none_=>_none (func)) (type $i64_i64_f32_=>_none (func (param i64 i64 f32))) + (type $i64_i64_=>_f32 (func (param i64 i64) (result f32))) (type $none_=>_i64 (func (result i64))) (import "env" "emscripten_get_sbrk_ptr" (func $foo (result i64))) (import "env" "segfault" (func $segfault)) diff -Nru binaryen-108/test/passes/safe-heap_enable-threads_enable-simd.txt binaryen-99/test/passes/safe-heap_enable-threads_enable-simd.txt --- binaryen-108/test/passes/safe-heap_enable-threads_enable-simd.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/safe-heap_enable-threads_enable-simd.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,15 @@ (module (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_v128_=>_none (func (param i32 i32 v128))) + (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $none_=>_none (func)) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i32))) (import "env" "segfault" (func $segfault)) @@ -3146,13 +3146,13 @@ (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_v128_=>_none (func (param i32 i32 v128))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $none_=>_none (func)) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i32))) (import "env" "segfault" (func $segfault)) @@ -5427,16 +5427,16 @@ ) (module (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_v128_=>_none (func (param i32 i32 v128))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $FUNCSIG$v (func)) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $none_=>_none (func)) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "segfault" (func $segfault)) (import "env" "alignfault" (func $alignfault)) diff -Nru binaryen-108/test/passes/safe-heap_low-memory-unused_enable-threads_enable-simd.txt binaryen-99/test/passes/safe-heap_low-memory-unused_enable-threads_enable-simd.txt --- binaryen-108/test/passes/safe-heap_low-memory-unused_enable-threads_enable-simd.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/safe-heap_low-memory-unused_enable-threads_enable-simd.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,15 @@ (module (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_v128_=>_none (func (param i32 i32 v128))) + (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $none_=>_none (func)) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i32))) (import "env" "segfault" (func $segfault)) @@ -3146,13 +3146,13 @@ (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_v128_=>_none (func (param i32 i32 v128))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $none_=>_none (func)) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i32))) (import "env" "segfault" (func $segfault)) @@ -5427,16 +5427,16 @@ ) (module (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_v128_=>_none (func (param i32 i32 v128))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $i32_i32_=>_v128 (func (param i32 i32) (result v128))) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $FUNCSIG$v (func)) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $none_=>_none (func)) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $foo (result i32))) (import "env" "segfault" (func $segfault)) diff -Nru binaryen-108/test/passes/safe-heap_start-function.txt binaryen-99/test/passes/safe-heap_start-function.txt --- binaryen-108/test/passes/safe-heap_start-function.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/safe-heap_start-function.txt 2021-01-07 20:01:06.000000000 +0000 @@ -2,27 +2,18 @@ (type $i32_i32_=>_i64 (func (param i32 i32) (result i64))) (type $i32_i32_i64_=>_none (func (param i32 i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $none_=>_none (func)) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) + (type $none_=>_none (func)) (type $i32_i32_f64_=>_none (func (param i32 i32 f64))) - (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_i32_f32_=>_none (func (param i32 i32 f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (type $none_=>_i32 (func (result i32))) (import "env" "emscripten_get_sbrk_ptr" (func $emscripten_get_sbrk_ptr (result i32))) (import "env" "segfault" (func $segfault)) (import "env" "alignfault" (func $alignfault)) (memory $0 1 1) - (start $mystart) - (func $mystart - (i32.store - (i32.load - (i32.const 42) - ) - (i32.const 43) - ) - (call $foo) - ) + (start $foo) (func $foo (i32.store (i32.load @@ -30,15 +21,6 @@ ) (i32.const 5678) ) - (call $foo2) - ) - (func $foo2 - (i32.store - (i32.load - (i32.const 98) - ) - (i32.const 99) - ) ) (func $bar (call $SAFE_HEAP_STORE_i32_4_4 diff -Nru binaryen-108/test/passes/safe-heap_start-function.wast binaryen-99/test/passes/safe-heap_start-function.wast --- binaryen-108/test/passes/safe-heap_start-function.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/safe-heap_start-function.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,21 +1,11 @@ (module (memory 1 1) - (func $mystart - ;; should not be modified because its the start function - (i32.store (i32.load (i32.const 42)) (i32.const 43)) - (call $foo) - ) (func $foo - ;; should not be modified because its reachable from start function + ;; should not be modified because its the start function (i32.store (i32.load (i32.const 1234)) (i32.const 5678)) - (call $foo2) - ) - (func $foo2 - ;; should not be modified because its reachable from start function - (i32.store (i32.load (i32.const 98)) (i32.const 99)) ) (func $bar (i32.store (i32.load (i32.const 1234)) (i32.const 5678)) ) - (start $mystart) + (start $foo) ) diff -Nru binaryen-108/test/passes/set-globals.passes binaryen-99/test/passes/set-globals.passes --- binaryen-108/test/passes/set-globals.passes 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/set-globals.passes 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -set-globals_pass-arg=set-globals@foo=1337,bar=42 diff -Nru binaryen-108/test/passes/set-globals.txt binaryen-99/test/passes/set-globals.txt --- binaryen-108/test/passes/set-globals.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/set-globals.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -(module - (global $foo i32 (i32.const 1337)) - (global $bar i64 (i64.const 42)) -) diff -Nru binaryen-108/test/passes/set-globals.wast binaryen-99/test/passes/set-globals.wast --- binaryen-108/test/passes/set-globals.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/set-globals.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -(module - ;; an imported i32 - (import "env" "in" (global $foo i32)) - - ;; a defined i64 - (global $bar i64 (i64.const 1234)) -) diff -Nru binaryen-108/test/passes/simplify-globals_all-features_fuzz-exec.txt binaryen-99/test/passes/simplify-globals_all-features_fuzz-exec.txt --- binaryen-108/test/passes/simplify-globals_all-features_fuzz-exec.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-globals_all-features_fuzz-exec.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,11 @@ [fuzz-exec] calling export -[fuzz-exec] note result: export => funcref +[fuzz-exec] note result: export => funcref(0) (module - (type $f32_i31ref_i64_f64_funcref_=>_none (func (param f32 i31ref i64 f64 funcref))) + (type $f32_ref?|i31|_i64_f64_funcref_=>_none (func (param f32 (ref null i31) i64 f64 funcref))) (type $none_=>_funcref (func (result funcref))) (global $global$0 (mut funcref) (ref.null func)) - (elem declare func $0) (export "export" (func $1)) - (func $0 (param $0 f32) (param $1 i31ref) (param $2 i64) (param $3 f64) (param $4 funcref) + (func $0 (param $0 f32) (param $1 (ref null i31)) (param $2 i64) (param $3 f64) (param $4 funcref) (nop) ) (func $1 (result funcref) @@ -17,5 +16,5 @@ ) ) [fuzz-exec] calling export -[fuzz-exec] note result: export => funcref +[fuzz-exec] note result: export => funcref(0) [fuzz-exec] comparing export diff -Nru binaryen-108/test/passes/simplify-globals_all-features.txt binaryen-99/test/passes/simplify-globals_all-features.txt --- binaryen-108/test/passes/simplify-globals_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-globals_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -213,9 +213,9 @@ ) (module (type $none_=>_none (func)) - (import "env" "global-1" (global $g1 anyref)) - (global $g2 anyref (global.get $g1)) - (global $g3 anyref (ref.null any)) + (import "env" "global-1" (global $g1 externref)) + (global $g2 externref (global.get $g1)) + (global $g3 externref (ref.null extern)) (func $test1 (drop (global.get $g1) @@ -226,7 +226,7 @@ ) (func $test2 (drop - (ref.null any) + (ref.null extern) ) ) ) diff -Nru binaryen-108/test/passes/simplify-locals_all-features_disable-exception-handling.txt binaryen-99/test/passes/simplify-locals_all-features_disable-exception-handling.txt --- binaryen-108/test/passes/simplify-locals_all-features_disable-exception-handling.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-locals_all-features_disable-exception-handling.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,16 +1,16 @@ (module - (type $5 (func (param i32) (result i32))) - (type $FUNCSIG$v (func)) - (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iiiii (func (param i32 i32 i32 i32) (result i32))) - (type $6 (func (param i32 i32 i32 i32 i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iiiiii (func (param i32 i32 i32 i32 i32) (result i32))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i64_=>_none (func (param i64))) (type $f32_=>_none (func (param f32))) - (type $4 (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) - (type $i64_=>_none (func (param i64))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) (type $i32_f64_f64_f32_i32_=>_f64 (func (param i32 f64 f64 f32 i32) (result f64))) (import "env" "waka" (func $waka)) (import "env" "waka_int" (func $waka_int (result i32))) @@ -18,8 +18,8 @@ (import "env" "moddi" (func $___udivmoddi4 (param i32 i32 i32 i32 i32) (result i32))) (import "env" "lp" (func $lp (param i32 i32) (result i32))) (import "fuzzing-support" "log-f32" (func $fimport$0 (param f32))) - (global $global$0 (mut i32) (i32.const 10)) (memory $0 256 256) + (global $global$0 (mut i32) (i32.const 10)) (func $contrast (local $x i32) (local $y i32) @@ -1116,21 +1116,21 @@ ) ) (module - (type $FUNCSIG$v (func)) - (type $FUNCSIG$i (func (result i32))) - (type $5 (func (param i32) (result i32))) - (type $FUNCSIG$iiiiii (func (param i32 i32 i32 i32 i32) (result i32))) - (type $4 (func (param i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) (type $f32_=>_none (func (param f32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_f64 (func (result f64))) (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "fuzzing-support" "log1" (func $fimport$0 (result i32))) (import "fuzzing-support" "log2" (func $fimport$1 (param i32))) (import "fuzzing-support" "log3" (func $fimport$2 (param f32))) - (global $global$0 (mut i32) (i32.const 10)) (memory $0 (shared 256 256)) + (global $global$0 (mut i32) (i32.const 10)) (func $nonatomics (result i32) (local $x i32) (nop) @@ -1720,7 +1720,7 @@ (module (type $none_=>_none (func)) (memory $0 256 256) - (data "hello, there!") + (data passive "hello, there!") (func $memory-init-load (local $x i32) (local.set $x diff -Nru binaryen-108/test/passes/simplify-locals_all-features_disable-exception-handling.wast binaryen-99/test/passes/simplify-locals_all-features_disable-exception-handling.wast --- binaryen-108/test/passes/simplify-locals_all-features_disable-exception-handling.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-locals_all-features_disable-exception-handling.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1548,7 +1548,7 @@ ) (module (memory 256 256) - (data "hello, there!") + (data passive "hello, there!") (func $memory-init-load (local $x i32) (local.set $x diff -Nru binaryen-108/test/passes/simplify-locals_all-features.txt binaryen-99/test/passes/simplify-locals_all-features.txt --- binaryen-108/test/passes/simplify-locals_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-locals_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,16 +1,16 @@ (module - (type $5 (func (param i32) (result i32))) - (type $FUNCSIG$v (func)) - (type $FUNCSIG$i (func (result i32))) - (type $FUNCSIG$iiiii (func (param i32 i32 i32 i32) (result i32))) - (type $6 (func (param i32 i32 i32 i32 i32 i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32 i32))) (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) - (type $FUNCSIG$iiiiii (func (param i32 i32 i32 i32 i32) (result i32))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) + (type $i64_=>_none (func (param i64))) (type $f32_=>_none (func (param f32))) - (type $4 (func (param i32))) (type $i32_i32_=>_none (func (param i32 i32))) - (type $i64_=>_none (func (param i64))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) (type $i32_f64_f64_f32_i32_=>_f64 (func (param i32 f64 f64 f32 i32) (result f64))) (import "env" "waka" (func $waka)) (import "env" "waka_int" (func $waka_int (result i32))) @@ -18,8 +18,8 @@ (import "env" "moddi" (func $___udivmoddi4 (param i32 i32 i32 i32 i32) (result i32))) (import "env" "lp" (func $lp (param i32 i32) (result i32))) (import "fuzzing-support" "log-f32" (func $fimport$0 (param f32))) - (global $global$0 (mut i32) (i32.const 10)) (memory $0 256 256) + (global $global$0 (mut i32) (i32.const 10)) (func $contrast (local $x i32) (local $y i32) @@ -1122,21 +1122,21 @@ ) ) (module - (type $FUNCSIG$v (func)) - (type $FUNCSIG$i (func (result i32))) - (type $5 (func (param i32) (result i32))) - (type $FUNCSIG$iiiiii (func (param i32 i32 i32 i32 i32) (result i32))) - (type $4 (func (param i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) + (type $i32_=>_none (func (param i32))) (type $f32_=>_none (func (param f32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_f64 (func (result f64))) (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "fuzzing-support" "log1" (func $fimport$0 (result i32))) (import "fuzzing-support" "log2" (func $fimport$1 (param i32))) (import "fuzzing-support" "log3" (func $fimport$2 (param f32))) - (global $global$0 (mut i32) (i32.const 10)) (memory $0 (shared 256 256)) + (global $global$0 (mut i32) (i32.const 10)) (func $nonatomics (result i32) (local $x i32) (nop) @@ -1726,7 +1726,7 @@ (module (type $none_=>_none (func)) (memory $0 256 256) - (data "hello, there!") + (data passive "hello, there!") (func $memory-init-load (local $x i32) (local.set $x @@ -1884,7 +1884,7 @@ (module (type $none_=>_anyref (func (result anyref))) (func $subtype-test (result anyref) - (local $0 anyref) + (local $0 externref) (local $1 anyref) (local $2 anyref) (block $block @@ -1895,9 +1895,136 @@ ) ) (module + (type $none_=>_none (func)) + (type $exnref_=>_none (func (param exnref))) + (type $i32_exnref_=>_none (func (param i32 exnref))) + (type $none_=>_i32 (func (result i32))) + (type $none_=>_exnref (func (result exnref))) + (event $event$0 (attr 0) (param)) + (event $event$1 (attr 0) (param exnref)) + (func $unoptimizable-br_on_exn-block (result exnref) + (local $0 exnref) + (block $label$0 + (local.set $0 + (br_on_exn $label$0 $event$0 + (ref.null exn) + ) + ) + ) + (local.get $0) + ) + (func $br_on_exn-trap + (local $0 exnref) + (drop + (block $label$1 (result exnref) + (br_on_exn $label$1 $event$1 + (ref.null exn) + ) + ) + ) + ) + (func $rethrow-trap + (local $0 i32) + (drop + (block $label$1 (result i32) + (try + (do + (rethrow + (ref.null exn) + ) + ) + (catch + (nop) + ) + ) + (i32.const 0) + ) + ) + ) + (func $foo (param $0 i32) (param $1 exnref) + (nop) + ) + (func $pop-cannot-be-sinked + (local $0 exnref) + (try + (do + (nop) + ) + (catch + (local.set $0 + (pop exnref) + ) + (call $foo + (i32.const 3) + (local.get $0) + ) + ) + ) + ) + (func $pop-within-catch-can-be-sinked + (local $0 exnref) + (try + (do + (nop) + ) + (catch + (nop) + (call $foo + (i32.const 3) + (try (result exnref) + (do + (ref.null exn) + ) + (catch + (pop exnref) + ) + ) + ) + ) + ) + ) + (func $bar (result i32) + (i32.const 3) + ) + (func $call-cannot-be-sinked-into-try + (local $0 i32) + (local.set $0 + (call $bar) + ) + (try + (do + (drop + (local.get $0) + ) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + ) + (func $non-call-can-be-sinked-into-try + (local $0 i32) + (nop) + (try + (do + (drop + (i32.const 3) + ) + ) + (catch + (drop + (pop exnref) + ) + ) + ) + ) +) +(module (type $none_=>_i32 (func (result i32))) (memory $0 (shared 1 1)) - (data "data") + (data passive "data") (export "foo" (func $0)) (func $0 (result i32) (local $0 i32) diff -Nru binaryen-108/test/passes/simplify-locals_all-features.wast binaryen-99/test/passes/simplify-locals_all-features.wast --- binaryen-108/test/passes/simplify-locals_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-locals_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1548,7 +1548,7 @@ ) (module (memory 256 256) - (data "hello, there!") + (data passive "hello, there!") (func $memory-init-load (local $x i32) (local.set $x @@ -1671,10 +1671,121 @@ (local.get $1) ) ) +(module + (event $event$0 (attr 0) (param)) + (func $unoptimizable-br_on_exn-block (result exnref) (local $0 exnref) + (block $label$0 + (local.set $0 + ;; br_on_exn's target block cannot be optimized to have a return value + (br_on_exn $label$0 $event$0 + (ref.null exn) + ) + ) + ) + (local.get $0) + ) + + (event $event$1 (attr 0) (param exnref)) + (func $br_on_exn-trap (local $0 exnref) + ;; This dead local.set cannot be replaced with a nop because br_on_exn can + ;; trap. + (local.set $0 + (block $label$1 (result exnref) + (br_on_exn $label$1 $event$1 + (ref.null exn) + ) + ) + ) + ) + + (func $rethrow-trap (local $0 i32) + ;; This dead local.set cannot be replaced with a nop because rethrow can + ;; trap. + (local.set $0 + (block $label$1 (result i32) + (try + (do (rethrow (ref.null exn))) + (catch) + ) + (i32.const 0) + ) + ) + ) + + (func $foo (param i32 exnref)) + (func $pop-cannot-be-sinked (local $0 exnref) + (try + (do) + (catch + ;; This (local.set $0) of (pop exnref) cannot be sinked to + ;; (local.get $0) below, because pop exnref should follow right after + ;; 'catch'. + (local.set $0 (pop exnref)) + (call $foo + (i32.const 3) + (local.get $0) + ) + ) + ) + ) + + (func $pop-within-catch-can-be-sinked (local $0 exnref) + (try + (do) + (catch + ;; This whole 'try' body can be sinked to eliminate local.set / + ;; local.get. Even though it contains a pop, it is enclosed within + ;; try-catch, so it is OK. + (local.set $0 + (try (result exnref) + (do (ref.null exn)) + (catch (pop exnref)) + ) + ) + (call $foo + (i32.const 3) + (local.get $0) + ) + ) + ) + ) + + (func $bar (result i32) (i32.const 3)) + (func $call-cannot-be-sinked-into-try (local $0 i32) + (drop + ;; This local.tee should NOT be sinked into 'try' below, because it may + ;; throw + (local.tee $0 (call $bar)) + ) + (try + (do + (drop (local.get $0)) + ) + (catch + (drop (pop exnref)) + ) + ) + ) + + (func $non-call-can-be-sinked-into-try (local $0 i32) + (drop + ;; This local.tee can be sinked into 'try' below, because it cannot throw + (local.tee $0 (i32.const 3)) + ) + (try + (do + (drop (local.get $0)) + ) + (catch + (drop (pop exnref)) + ) + ) + ) +) ;; data.drop has global side effects (module (memory $0 (shared 1 1)) - (data "data") + (data passive "data") (func "foo" (result i32) (local $0 i32) (block (result i32) @@ -1693,16 +1804,16 @@ ;; it is no longer equivalent ;; (see https://github.com/WebAssembly/binaryen/issues/3266) (module - (func "test" (param $0 eqref) (param $1 (ref null i31)) (result i32) + (func "test" (param $0 eqref) (param $1 i31ref) (result i32) (local $2 eqref) - (local $3 (ref null i31)) + (local $3 i31ref) (local.set $2 (local.get $0) ;; $0 and $2 are equivalent ) (local.set $0 ;; set $0 to something with another type (local.get $3) ) - ;; compares a null eqref and a zero (ref null i31) - should be false + ;; compares a null eqref and a zero i31ref - should be false (ref.eq (local.get $2) (local.get $1) diff -Nru binaryen-108/test/passes/simplify-locals-nonesting.txt binaryen-99/test/passes/simplify-locals-nonesting.txt --- binaryen-108/test/passes/simplify-locals-nonesting.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-locals-nonesting.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $0 (func (param i64 i64 i64) (result i32))) - (type $1 (func (param i32) (result i32))) + (type $i64_i64_i64_=>_i32 (func (param i64 i64 i64) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (func $figure-1a (param $a i64) (param $x i64) (param $y i64) (result i32) (local $i i32) (local $j i32) diff -Nru binaryen-108/test/passes/simplify-locals-nostructure.txt binaryen-99/test/passes/simplify-locals-nostructure.txt --- binaryen-108/test/passes/simplify-locals-nostructure.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/simplify-locals-nostructure.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_none (func)) - (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_f64 (func (param i32 i32) (result f64))) (memory $0 1) (func $contrast (local $x i32) diff -Nru binaryen-108/test/passes/sparse_matrix_liveness.bin.txt binaryen-99/test/passes/sparse_matrix_liveness.bin.txt --- binaryen-108/test/passes/sparse_matrix_liveness.bin.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/sparse_matrix_liveness.bin.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -total - [exports] : 1 - [funcs] : 1 - [globals] : 0 - [imports] : 0 - [tables] : 0 - [tags] : 0 - [total] : 4 - [vars] : 8194 - Block : 1 - Const : 1 - LocalGet : 1 - LocalSet : 1 -total - [exports] : 1 - [funcs] : 1 - [globals] : 0 - [imports] : 0 - [tables] : 0 - [tags] : 0 - [total] : 4 - [vars] : 1 -8193 - Block : 1 - Const : 1 - LocalGet : 1 - LocalSet : 1 -(module - (type $none_=>_i32 (func (result i32))) - (export "foo" (func $0)) - (func $0 (result i32) - (local $0 i32) - (local.set $0 - (i32.const 0) - ) - (local.get $0) - ) -) diff -Nru binaryen-108/test/passes/sparse_matrix_liveness.passes binaryen-99/test/passes/sparse_matrix_liveness.passes --- binaryen-108/test/passes/sparse_matrix_liveness.passes 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/sparse_matrix_liveness.passes 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -metrics_coalesce-locals_metrics_reorder-locals Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/passes/sparse_matrix_liveness.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/passes/sparse_matrix_liveness.wasm differ diff -Nru binaryen-108/test/passes/ssa_fuzz-exec_enable-threads.txt binaryen-99/test/passes/ssa_fuzz-exec_enable-threads.txt --- binaryen-108/test/passes/ssa_fuzz-exec_enable-threads.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/ssa_fuzz-exec_enable-threads.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ [fuzz-exec] calling func_0 [fuzz-exec] note result: func_0 => 16384 (module - (type $0 (func (result i32))) + (type $none_=>_i32 (func (result i32))) (memory $0 (shared 1 1)) (table $0 0 0 funcref) (export "func_0" (func $0)) diff -Nru binaryen-108/test/passes/ssa-nomerge_enable-simd.txt binaryen-99/test/passes/ssa-nomerge_enable-simd.txt --- binaryen-108/test/passes/ssa-nomerge_enable-simd.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/ssa-nomerge_enable-simd.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,9 +1,9 @@ (module (type $i32_=>_none (func (param i32))) - (type $i32_i32_=>_none (func (param i32 i32))) (type $none_=>_none (func)) - (global $global$0 (mut i32) (i32.const 1)) + (type $i32_i32_=>_none (func (param i32 i32))) (memory $0 1 1) + (global $global$0 (mut i32) (i32.const 1)) (func $basics (param $x i32) (local $y i32) (local $z f32) diff -Nru binaryen-108/test/passes/stack-check_enable-mutable-globals.txt binaryen-99/test/passes/stack-check_enable-mutable-globals.txt --- binaryen-108/test/passes/stack-check_enable-mutable-globals.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/stack-check_enable-mutable-globals.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "__stack_pointer" (global $sp (mut i32))) (global $__stack_base (mut i32) (i32.const 0)) (global $__stack_limit (mut i32) (i32.const 0)) @@ -40,8 +40,8 @@ ) ) (module - (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_none (func (param i32 i32))) + (type $none_=>_i32 (func (result i32))) (import "env" "__stack_pointer" (global $sp (mut i32))) (global $__stack_base (mut i32) (i32.const 0)) (global $__stack_limit (mut i32) (i32.const 0)) diff -Nru binaryen-108/test/passes/strip-target-features_roundtrip_print-features_all-features.txt binaryen-99/test/passes/strip-target-features_roundtrip_print-features_all-features.txt --- binaryen-108/test/passes/strip-target-features_roundtrip_print-features_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/strip-target-features_roundtrip_print-features_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -11,17 +11,15 @@ --enable-gc --enable-memory64 --enable-typed-function-references ---enable-relaxed-simd ---enable-extended-const (module - (type $none_=>_v128_anyref (func (result v128 anyref))) - (func $foo (result v128 anyref) + (type $none_=>_v128_externref (func (result v128 externref))) + (func $foo (result v128 externref) (tuple.make (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) - (ref.null any) + (ref.null extern) ) ) - (func $bar (result v128 anyref) + (func $bar (result v128 externref) (return_call $foo) ) ) diff -Nru binaryen-108/test/passes/stub-unsupported-js.txt binaryen-99/test/passes/stub-unsupported-js.txt --- binaryen-108/test/passes/stub-unsupported-js.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/stub-unsupported-js.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_f32 (func (result f32))) - (type $i64_=>_f32 (func (param i64) (result f32))) (type $i32_=>_f32 (func (param i32) (result f32))) + (type $i64_=>_f32 (func (param i64) (result f32))) (func $yes (param $x i64) (result f32) (drop (local.get $x) @@ -23,9 +23,9 @@ ) ) (module - (type $none_=>_f32 (func (result f32))) (type $none_=>_none (func)) (type $none_=>_i32 (func (result i32))) + (type $none_=>_f32 (func (result f32))) (table $0 2 2 funcref) (elem (i32.const 1) $return-f32) (func $return-f32 (result f32) diff -Nru binaryen-108/test/passes/too_much_for_liveness.bin.txt binaryen-99/test/passes/too_much_for_liveness.bin.txt --- binaryen-108/test/passes/too_much_for_liveness.bin.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/too_much_for_liveness.bin.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,35 @@ +total + [events] : 0 + [exports] : 1 + [funcs] : 1 + [globals] : 0 + [imports] : 0 + [total] : 4 + [vars] : 65536 + block : 1 + const : 1 + local.get : 1 + local.set : 1 +total + [events] : 0 + [exports] : 1 + [funcs] : 1 + [globals] : 0 + [imports] : 0 + [total] : 4 + [vars] : 65536 + block : 1 + const : 1 + local.get : 1 + local.set : 1 +(module + (type $none_=>_i32 (func (result i32))) + (export "foo" (func $0)) + (func $0 (result i32) + (local $0 i32) + (local.set $0 + (i32.const 0) + ) + (local.get $0) + ) +) diff -Nru binaryen-108/test/passes/too_much_for_liveness.passes binaryen-99/test/passes/too_much_for_liveness.passes --- binaryen-108/test/passes/too_much_for_liveness.passes 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/too_much_for_liveness.passes 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1 @@ +metrics_coalesce-locals_metrics_reorder-locals Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/passes/too_much_for_liveness.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/passes/too_much_for_liveness.wasm differ diff -Nru binaryen-108/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt binaryen-99/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt --- binaryen-108/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/translate-to-fuzz_all-features_metrics_noprint.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,36 +1,42 @@ total - [exports] : 5 - [funcs] : 4 + [events] : 1 + [exports] : 3 + [funcs] : 2 [globals] : 6 - [imports] : 5 + [imports] : 6 [memory-data] : 22 [table-data] : 0 - [tables] : 1 - [tags] : 1 - [total] : 363 - [vars] : 9 - AtomicFence : 1 - AtomicRMW : 1 - Binary : 65 - Block : 36 - Break : 7 - Call : 2 - CallRef : 1 - Const : 75 - Drop : 1 - GlobalGet : 19 - GlobalSet : 10 - I31New : 1 - If : 13 - Load : 19 - LocalGet : 47 - LocalSet : 24 - Loop : 6 - MemoryCopy : 1 - Nop : 6 - RefFunc : 2 - Return : 10 - Select : 2 - Store : 2 - TupleMake : 1 - Unary : 11 + [total] : 592 + [vars] : 1 + atomic.cmpxchg : 1 + atomic.fence : 3 + binary : 58 + block : 84 + break : 26 + call : 4 + call_ref : 1 + const : 149 + data.drop : 1 + drop : 3 + global.get : 29 + global.set : 17 + i31.get : 2 + i31.new : 7 + if : 35 + load : 15 + local.get : 10 + local.set : 14 + loop : 13 + memory.init : 1 + nop : 36 + ref.eq : 2 + ref.func : 2 + ref.is_null : 3 + ref.null : 8 + return : 14 + select : 2 + simd_extract : 2 + store : 8 + tuple.extract : 5 + tuple.make : 4 + unary : 33 diff -Nru binaryen-108/test/passes/translate-to-fuzz_all-features.txt binaryen-99/test/passes/translate-to-fuzz_all-features.txt --- binaryen-108/test/passes/translate-to-fuzz_all-features.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/translate-to-fuzz_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,1143 @@ +(module + (type $none_=>_i32_v128_f64_v128 (func (result i32 v128 f64 v128))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i64_=>_none (func (param i64))) + (type $i64_i32_=>_none (func (param i64 i32))) + (type $f32_=>_none (func (param f32))) + (type $f64_=>_none (func (param f64))) + (type $v128_=>_none (func (param v128))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_i32 (func (result i32))) + (import "fuzzing-support" "log-i32" (func $log-i32 (param i32))) + (import "fuzzing-support" "log-i64" (func $log-i64 (param i64))) + (import "fuzzing-support" "log-f32" (func $log-f32 (param f32))) + (import "fuzzing-support" "log-f64" (func $log-f64 (param f64))) + (import "fuzzing-support" "log-v128" (func $log-v128 (param v128))) + (import "fuzzing-support" "log-exnref" (func $log-exnref (param exnref))) + (memory $0 (shared 16 17)) + (data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3") + (table $0 0 funcref) + (global $global$ (mut eqref) (ref.null eq)) + (global $global$_0 (mut externref) (ref.null extern)) + (global $global$_1 (mut v128) (v128.const i32x4 0xfffffff9 0x06071c48 0x3f800000 0xc3800ae1)) + (global $global$_2 (mut eqref) (ref.null eq)) + (global $global$_3 (mut f64) (f64.const 0)) + (global $hangLimit (mut i32) (i32.const 10)) + (event $event$ (attr 0) (param i64 i32)) + (export "hashMemory" (func $hashMemory)) + (export "memory" (memory $0)) + (export "hangLimitInitializer" (func $hangLimitInitializer)) + (func $hashMemory (result i32) + (local $0 i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 64) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (local.set $0 + (i32.const 5381) + ) + (local.set $0 + (i32.const 1140933654) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (i32.const -127) + ) + (i32.load8_u offset=1 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (i32.const 303045650) + (i32.const 5) + ) + (i32.shl + (ref.eq + (i31.new + (i32.const -65535) + ) + (tuple.extract 2 + (tuple.make + (f64.const 274877906944) + (i31.new + (i32.const -134217728) + ) + (ref.null eq) + ) + ) + ) + (i32.const 5) + ) + ) + (i32.load8_u offset=2 + (i32.const 0) + ) + ) + ) + (nop) + (local.set $0 + (i32.xor + (i32.add + (loop $label$1 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 4878) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$2 (result i32) + (drop + (f64.const 3402823466385288598117041e14) + ) + (loop $label$6 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -13) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (block $label$7 + (nop) + (if + (block $label$8 + (nop) + (br $label$1) + ) + (block $label$9 + (f64.store offset=2 align=2 + (i32.and + (i32.const 118163717) + (i32.const 15) + ) + (if (result f64) + (call $hashMemory) + (block $label$10 (result f64) + (memory.copy + (i32.const -129) + (i32.and + (i32.const 1195786829) + (i32.const 15) + ) + (i32.const -8) + ) + (f64.const -562949953421312.2) + ) + (block $label$11 + (nop) + (br $label$7) + ) + ) + ) + (if + (i32.eqz + (i32.atomic.load + (i32.and + (i32.const 65535) + (i32.const 15) + ) + ) + ) + (block $label$12 + (nop) + (nop) + ) + (block $label$13 + (br_if $label$7 + (i32.const 10539) + ) + (loop $label$14 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 1495078923) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (atomic.fence) + ) + ) + ) + ) + (nop) + ) + ) + (br_if $label$6 + (i32.const -50) + ) + (loop $label$15 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -96) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$16 + (if + (i32.eqz + (br_if $label$2 + (i8x16.extract_lane_s 2 + (f64x2.gt + (v128.const i32x4 0xffffffc0 0xffffffff 0x60631d62 0x630f6218) + (if (result v128) + (i32.eqz + (f32.ne + (block $label$18 + (nop) + (br $label$15) + ) + (f32.const -nan:0x7fff8a) + ) + ) + (block $label$19 (result v128) + (nop) + (v128.const i32x4 0x00000000 0x38100000 0x00000000 0x40d89880) + ) + (block $label$20 + (if + (i32.atomic.rmw8.cmpxchg_u offset=4 + (i32.and + (i32.const 2) + (i32.const 15) + ) + (i32.const 65525) + (br_if $label$2 + (i32.const -33554432) + (i64.lt_u + (i64.const -65536) + (i64.const 6663) + ) + ) + ) + (block $label$21 + (br_if $label$21 + (i32.eqz + (i32.const 65535) + ) + ) + (nop) + ) + (block $label$22 + (v128.store offset=4 + (i32.and + (i32.const 55) + (i32.const 15) + ) + (v128.const i32x4 0xfffffe00 0x7fffffff 0x00005b34 0x00000039) + ) + (nop) + ) + ) + (br $label$16) + ) + ) + ) + ) + (i32.eqz + (i32.const 85459227) + ) + ) + ) + (block $label$23 + (block $label$24 + (block $label$25 + (nop) + (nop) + ) + (nop) + ) + (nop) + ) + (block $label$26 + (if + (br_if $label$2 + (i32.const 1091126348) + (i32.const 1276841216) + ) + (br_if $label$26 + (i32.eqz + (tuple.extract 0 + (if (result i32 v128 f64 v128) + (i32.load8_u offset=3 + (i32.and + (f64.ge + (block $label$27 (result f64) + (nop) + (f64.const 41) + ) + (f64x2.extract_lane 0 + (v128.const i32x4 0xffffc000 0x00000007 0x00000001 0x473f2147) + ) + ) + (i32.const 15) + ) + ) + (block $label$28 (result i32 v128 f64 v128) + (tuple.make + (i32.const 67308125) + (v128.const i32x4 0xff00011d 0x0601e545 0x7f0e14ff 0x00b1f843) + (f64.const 1314148947) + (v128.const i32x4 0x0000003a 0x42d00000 0x00000000 0x40280000) + ) + ) + (block $label$29 (result i32 v128 f64 v128) + (br_if $label$15 + (i32.eqz + (br_if $label$2 + (i32.const -8192) + (i32.eqz + (i32.const -2) + ) + ) + ) + ) + (tuple.make + (i32.const 65534) + (v128.const i32x4 0x41530000 0x008045b2 0x01ff7f00 0xff2d8349) + (f64.const 1797693134862315708145274e284) + (v128.const i32x4 0xffbc630d 0xffb6ffbb 0x00015658 0xffb4ffff) + ) + ) + ) + ) + ) + ) + (block $label$30 + (if + (loop $label$31 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 1578633994) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$32 (result i32) + (block $label$33 + (if + (i32.eqz + (i32.atomic.rmw.and offset=4 + (i32.const -2147483648) + (block $label$34 + (loop $label$35 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 403574365) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (nop) + (br_if $label$35 + (i32.const -65536) + ) + (nop) + ) + ) + (br $label$1) + ) + ) + ) + (block $label$36 + (nop) + (br_if $label$16 + (i32.const 2136) + ) + ) + (block $label$37 + (nop) + (nop) + ) + ) + (atomic.fence) + ) + (f32.lt + (f32.const 2147483648) + (f32.const 2147483648) + ) + ) + ) + (block $label$40 + (i32.atomic.store16 offset=2 + (i32.and + (i31.get_s + (loop $label$41 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -2) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$42 + (loop $label$43 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -13) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$44 + (nop) + (nop) + ) + ) + (block $label$45 + (nop) + (br $label$16) + ) + ) + ) + ) + (i32.const 15) + ) + (block $label$46 + (nop) + (ref.is_null + (if + (i32.eqz + (if (result i32) + (i32.eqz + (block $label$47 + (nop) + (br $label$16) + ) + ) + (i32.const -4194304) + (i32.const 5140) + ) + ) + (block $label$48 + (block $label$49 + (nop) + (br_if $label$15 + (i32.eqz + (loop $label$50 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 112) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (nop) + (br_if $label$50 + (i32.eqz + (i32.const 3) + ) + ) + (i31.get_s + (i31.new + (i32.const 4095) + ) + ) + ) + ) + ) + ) + ) + (br $label$40) + ) + (block $label$51 + (drop + (ref.null exn) + ) + (br $label$16) + ) + ) + ) + ) + ) + ) + (block $label$52 + (loop $label$53 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 7506) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (nop) + (br_if $label$53 + (loop $label$54 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 50922251) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.const 6912) + ) + ) + (br_if $label$6 + (br_if $label$2 + (call $hashMemory) + (loop $label$55 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 319820056) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.const 2147483647) + ) + ) + ) + ) + ) + (memory.copy + (i32.and + (i32.atomic.load offset=3 + (i32.and + (loop $label$56 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -2147483648) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (loop $label$57 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 262143) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$58 + (if + (i32.eqz + (i32.const 775321902) + ) + (nop) + (if + (i32.eqz + (i32.const -18) + ) + (nop) + (nop) + ) + ) + (nop) + ) + (br_if $label$57 + (i32.const 4194304) + ) + (f32.le + (f32.const 18446744073709551615) + (f32.const -nan:0x7fff87) + ) + ) + ) + ) + (i32.const 15) + ) + ) + (i32.const 15) + ) + (i32.and + (block $label$59 (result i32) + (loop $label$60 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -32768) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block + (block $label$61 + (drop + (i31.new + (i32.const -8192) + ) + ) + (nop) + ) + (br_if $label$60 + (i32.eqz + (loop $label$62 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 7) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block $label$63 (result i32) + (nop) + (i32.const 65521) + ) + ) + ) + ) + (memory.fill + (i32.trunc_f32_u + (f32.const 256) + ) + (i64.eq + (i64.const 256) + (i64.const -16384) + ) + (i32.const 387455770) + ) + ) + ) + (i32.const 4627) + ) + (i32.const 15) + ) + (i32.load8_s offset=3 + (i32.and + (br_if $label$2 + (loop $label$64 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -96) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$65 + (loop $label$66 + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 65518) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (nop) + ) + (nop) + ) + (br_if $label$64 + (tuple.extract 1 + (tuple.make + (v128.const i32x4 0x0606ff82 0xfffe0000 0x04052000 0xfffe0000) + (i32.const 1529028702) + ) + ) + ) + (loop $label$67 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const -1073741825) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.const 128) + ) + ) + ) + (i32.eqz + (ref.is_null + (select (result anyref) + (ref.null eq) + (ref.null extern) + (i32.const 129) + ) + ) + ) + ) + (i32.const 15) + ) + ) + ) + ) + ) + (nop) + ) + ) + (block $label$68 + (nop) + (nop) + ) + ) + ) + (nop) + ) + ) + ) + ) + (if (result i32) + (block $label$69 (result i32) + (if + (if (result i32) + (br_if $label$2 + (loop $label$71 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 15) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (block (result i32) + (block $label$72 + (br_if $label$72 + (i32.const -1) + ) + (nop) + ) + (br_if $label$71 + (i32.eqz + (i32.const -2147483648) + ) + ) + (if (result i32) + (i32.eqz + (i32.const -32766) + ) + (block $label$73 (result i32) + (br_if $label$71 + (i32.eqz + (tuple.extract 1 + (block $label$74 + (nop) + (br $label$1) + ) + ) + ) + ) + (ref.is_null + (global.get $global$_0) + ) + ) + (i32x4.all_true + (v128.const i32x4 0x3c800c01 0x193fff27 0x52a20001 0x970000ff) + ) + ) + ) + ) + (i32.eqz + (loop $label$70 (result i32) + (block + (if + (i32.eqz + (global.get $hangLimit) + ) + (return + (i32.const 1048576) + ) + ) + (global.set $hangLimit + (i32.sub + (global.get $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.const 256) + ) + ) + ) + (i32.atomic.load8_u offset=22 + (i32.const 858607703) + ) + (block $label$75 (result i32) + (nop) + (br_if $label$75 + (i32.const 7) + (i31.get_s + (tuple.extract 0 + (tuple.make + (i31.new + (i32.const 219815443) + ) + (v128.const i32x4 0x00000001 0x151b1e13 0x00000001 0x1a5f0000) + ) + ) + ) + ) + ) + ) + (block $label$76 + (nop) + ) + (nop) + ) + (i32.const 2097152) + ) + (i32.const -84) + (block $label$77 (result i32) + (i32.const -16) + ) + ) + ) + ) + (local.get $0) + ) + (i32.load8_u offset=4 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.load8_u offset=5 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.const 6506) + ) + ) + (nop) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.load8_u offset=6 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (i32.const 1633371484) + (i32.const 5) + ) + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.load8_u offset=8 + (i32.const 0) + ) + ) + ) + (i32.load8_u offset=9 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.load8_u offset=10 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.const 1937132399) + (i32.load8_u offset=11 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (i32.const -85) + (i32.const 5) + ) + (local.get $0) + ) + (i32.shl + (local.get $0) + (i32.const 5) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.load8_u offset=13 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.const 5) + (local.get $0) + ) + (i32.load8_u offset=14 + (i32.const 0) + ) + ) + ) + (local.set $0 + (i32.xor + (i32.add + (i32.shl + (local.get $0) + (i32.const 5) + ) + (local.get $0) + ) + (i32.load8_u offset=12 + (i32.const 0) + ) + ) + ) + (local.get $0) + ) + ) + (func $hangLimitInitializer + (global.set $hangLimit + (i32.const 10) + ) + ) +) diff -Nru binaryen-108/test/passes/trap-mode-clamp.txt binaryen-99/test/passes/trap-mode-clamp.txt --- binaryen-108/test/passes/trap-mode-clamp.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/trap-mode-clamp.txt 2021-01-07 20:01:06.000000000 +0000 @@ -3,8 +3,8 @@ (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) (type $i32_i64_=>_none (func (param i32 i64))) (type $f32_=>_i32 (func (param f32) (result i32))) - (type $f32_=>_i64 (func (param f32) (result i64))) (type $f64_=>_i32 (func (param f64) (result i32))) + (type $f32_=>_i64 (func (param f32) (result i64))) (type $f64_=>_i64 (func (param f64) (result i64))) (type $f32_=>_none (func (param f32))) (type $f64_=>_none (func (param f64))) diff -Nru binaryen-108/test/passes/untee.txt binaryen-99/test/passes/untee.txt --- binaryen-108/test/passes/untee.txt 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/untee.txt 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,47 @@ +(module + (type $none_=>_none (func)) + (func $tee + (local $x i32) + (local $y f64) + (drop + (block (result i32) + (local.set $x + (i32.const 1) + ) + (local.get $x) + ) + ) + (drop + (block (result f64) + (local.set $y + (f64.const 2) + ) + (local.get $y) + ) + ) + (local.set $x + (block (result i32) + (local.set $x + (i32.const 3) + ) + (local.get $x) + ) + ) + (local.set $x + (block (result i32) + (local.set $x + (block (result i32) + (local.set $x + (i32.const 3) + ) + (local.get $x) + ) + ) + (local.get $x) + ) + ) + (drop + (unreachable) + ) + ) +) diff -Nru binaryen-108/test/passes/untee.wast binaryen-99/test/passes/untee.wast --- binaryen-108/test/passes/untee.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/passes/untee.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,12 @@ +(module + (func $tee + (local $x i32) + (local $y f64) + (drop (local.tee $x (i32.const 1))) + (drop (local.tee $y (f64.const 2))) + (local.set $x (local.tee $x (i32.const 3))) + (local.set $x (local.tee $x (local.tee $x (i32.const 3)))) + (drop (local.tee $x (unreachable))) + ) +) + diff -Nru binaryen-108/test/passes/vacuum_all-features.txt binaryen-99/test/passes/vacuum_all-features.txt --- binaryen-108/test/passes/vacuum_all-features.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/vacuum_all-features.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,13 +1,13 @@ (module - (type $0 (func)) - (type $3 (func (result i32))) - (type $1 (func (param i32))) - (type $2 (func (result f32))) - (type $4 (func (param i32 f64 i32 i32))) + (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_none (func (param i32))) + (type $none_=>_f32 (func (result f32))) + (type $i32_f64_i32_i32_=>_none (func (param i32 f64 i32 i32))) (type $none_=>_f64 (func (result f64))) (import "env" "int" (func $int (result i32))) - (global $Int i32 (i32.const 0)) (memory $0 256 256) + (global $Int i32 (i32.const 0)) (func $b (nop) ) @@ -299,8 +299,8 @@ ) ) (module - (type $0 (func (param i64))) - (type $1 (func (param f32 i32) (result i32))) + (type $i64_=>_none (func (param i64))) + (type $f32_i32_=>_i32 (func (param f32 i32) (result i32))) (func $0 (param $0 i64) (nop) ) @@ -322,8 +322,8 @@ (module (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - (global $global$1 (mut i32) (i32.const 0)) (memory $0 1 1) + (global $global$1 (mut i32) (i32.const 0)) (export "compress" (func $3)) (func $_deflate (param $0 i32) (result i32) (call $_deflate @@ -436,14 +436,30 @@ ) (module (type $none_=>_none (func)) - (func $foo + (type $i32_=>_none (func (param i32))) + (event $e (attr 0) (param i32)) + (func $try-test (nop) ) -) -(module - (type $none_=>_none (func)) - (global $global$0 (mut i32) (i32.const 10)) - (func $1 - (nop) + (func $inner-try-test + (local $0 i32) + (try + (do + (throw $e + (i32.const 0) + ) + ) + (catch + (drop + (pop exnref) + ) + (local.set $0 + (i32.const 1) + ) + ) + ) + ) + (func $br-in-catch + (unreachable) ) ) diff -Nru binaryen-108/test/passes/vacuum_all-features.wast binaryen-99/test/passes/vacuum_all-features.wast --- binaryen-108/test/passes/vacuum_all-features.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/vacuum_all-features.wast 2021-01-07 20:01:06.000000000 +0000 @@ -797,46 +797,54 @@ ) (module - (type $A (struct (field (mut i32)))) - (func $foo - (drop - (block (result dataref) - ;; this dropped item can be vacuumed out in principle, but it is a non- - ;; nullable reference type and we don't have a type to put in its place, so - ;; don't try to replace it. (later operations will remove all the body of - ;; this function; this test verifies we don't crash along the way) - (struct.new_default_with_rtt $A - (rtt.canon $A) + (event $e (attr 0) (param i32)) + ;; When try body does not throw, try-body can be replaced with the try body + (func $try-test + (try + (do + (drop (i32.const 0)) + ) + (catch + (drop (pop exnref)) + ) ) - ) ) - ) -) -(module - (global $global$0 (mut i32) (i32.const 10)) - (func $1 - (drop - (block $block (result funcref i32) - ;; we can vaccum out all parts of this block: the br_if is not taken, there - ;; is a nop, and the tuple at the end goes to a dropped block anyhow. this - ;; test specifically verifies handling of tuples containing non-nullable - ;; types, for which we try to create a zero in an intermediate step along - ;; the way. - (drop - (br_if $block - (tuple.make - (ref.func $1) - (i32.const 0) + + ;; The exception thrown in the inner try is caught by the inner catch, so the + ;; outer try body does not throw and the outer try-catch can be removed + (func $inner-try-test (local $0 i32) + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (catch + (drop (pop exnref)) + (local.set $0 (i32.const 1)) + ) + ) + ) + (catch + (drop (pop exnref)) ) - (i32.const 0) - ) ) - (nop) - (tuple.make - (ref.func $1) - (i32.const 1) + ) + + ;; When catch body is removed, the removal of 'br' inside the catch body + ;; should be propagated up to the outer block, so that its type will be + ;; correctly updated to unreachable. + (func $br-in-catch + (block $label$1 + (try + (do + (unreachable) + ) + (catch + (drop (pop exnref)) + (br $label$1) + ) + ) ) - ) ) - ) ) diff -Nru binaryen-108/test/passes/vacuum_ignore-implicit-traps.txt binaryen-99/test/passes/vacuum_ignore-implicit-traps.txt --- binaryen-108/test/passes/vacuum_ignore-implicit-traps.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/passes/vacuum_ignore-implicit-traps.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module - (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) + (type $none_=>_i32 (func (result i32))) (memory $0 1) (func $load-would-normally-have-side-effects (result i32) (i64.ge_s diff -Nru binaryen-108/test/polymorphic_stack.wast.fromBinary binaryen-99/test/polymorphic_stack.wast.fromBinary --- binaryen-108/test/polymorphic_stack.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/polymorphic_stack.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_i32 (func (result i32))) - (type $FUNCSIG$ii (func (param i32) (result i32))) (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_=>_none (func (param i32))) (import "env" "table" (table $timport$0 9 9 funcref)) (func $break-and-binary (result i32) diff -Nru binaryen-108/test/polymorphic_stack.wast.fromBinary.noDebugInfo binaryen-99/test/polymorphic_stack.wast.fromBinary.noDebugInfo --- binaryen-108/test/polymorphic_stack.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/polymorphic_stack.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (type $none_=>_i32 (func (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $i32_=>_none (func (param i32))) (import "env" "table" (table $timport$0 9 9 funcref)) (func $0 (result i32) diff -Nru binaryen-108/test/polymorphic_stack.wast.from-wast binaryen-99/test/polymorphic_stack.wast.from-wast --- binaryen-108/test/polymorphic_stack.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/polymorphic_stack.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,6 +1,6 @@ (module (type $none_=>_i32 (func (result i32))) - (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_none (func)) (type $i32_=>_none (func (param i32))) (import "env" "table" (table $timport$0 9 9 funcref)) @@ -36,7 +36,7 @@ ) (drop (i64.eqz - (call_indirect $timport$0 (type $FUNCSIG$ii) + (call_indirect (type $i32_=>_i32) (unreachable) (unreachable) ) diff -Nru binaryen-108/test/print/min.minified.txt binaryen-99/test/print/min.minified.txt --- binaryen-108/test/print/min.minified.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/print/min.minified.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,4 @@ -(module(type $0 (func(param f32)(result f32)))(type $1 (func(param i32 i32)(result f32)))(type $2 (func(param i32)(result i32)))(type $3 (func(param i32 i32 i32)(result i32)))(memory $0 256 256) +(module(type $i32_=>_i32 (func(param i32)(result i32)))(type $i32_i32_i32_=>_i32 (func(param i32 i32 i32)(result i32)))(type $f32_=>_f32 (func(param f32)(result f32)))(type $i32_i32_=>_f32 (func(param i32 i32)(result f32)))(memory $0 256 256) (export "floats" (func $floats))(func $floats(param $f f32)(result f32)(local $t f32)(f32.add(local.get $t)(local.get $f)))(func $neg(param $k i32)(param $p i32)(result f32)(local $n f32)(local.tee $n(f32.neg(block $block0 (result f32)(i32.store(local.get $k)(local.get $p))(f32.load(local.get $k))))))(func $littleswitch(param $x i32)(result i32)(block $topmost (result i32)(block $switch-case$2(block $switch-case$1(br_table $switch-case$1 $switch-case$2 $switch-case$1(i32.sub(local.get $x)(i32.const 1)))) (br $topmost(i32.const 1))) (br $topmost(i32.const 2))(i32.const 0)))(func $f1(param $i1 i32)(param $i2 i32)(param $i3 i32)(result i32)(block $topmost (result i32)(local.get $i3)))) \ No newline at end of file diff -Nru binaryen-108/test/print/min.txt binaryen-99/test/print/min.txt --- binaryen-108/test/print/min.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/print/min.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module - (type $0 (func (param f32) (result f32))) - (type $1 (func (param i32 i32) (result f32))) - (type $2 (func (param i32) (result i32))) - (type $3 (func (param i32 i32 i32) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32))) + (type $f32_=>_f32 (func (param f32) (result f32))) + (type $i32_i32_=>_f32 (func (param i32 i32) (result f32))) (memory $0 256 256) (export "floats" (func $floats)) (func $floats (param $f f32) (result f32) diff -Nru binaryen-108/test/printf.c binaryen-99/test/printf.c --- binaryen-108/test/printf.c 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/printf.c 2021-01-07 20:01:06.000000000 +0000 @@ -1,24 +1,20 @@ #include int main() { - int a = 12345; - unsigned b = 123456; - long c = 1234567; - unsigned long d = 12345678; - long long e = 1234567891011; - unsigned long long f = 123456789101112; + int a = 12345; + unsigned b = 123456; + long c = 1234567; + unsigned long d = 12345678; + long long e = 1234567891011; + unsigned long long f = 123456789101112; - printf("int a = %d\n" - "unsigned b = %u\n" - "long c = %ld\n" - "unsigned long d = %lu\n" - "long long e = %lld\n" - "unsigned long long f = %llu\n", - a, - b, - c, - d, - e, - f); - return 0; + printf( + "int a = %d\n" + "unsigned b = %u\n" + "long c = %ld\n" + "unsigned long d = %lu\n" + "long long e = %lld\n" + "unsigned long long f = %llu\n" + , a, b, c, d, e, f); + return 0; } diff -Nru binaryen-108/test/reduce/atomics-and-bulk-memory.wast binaryen-99/test/reduce/atomics-and-bulk-memory.wast --- binaryen-108/test/reduce/atomics-and-bulk-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reduce/atomics-and-bulk-memory.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -(module - (memory 1 1) - ;; this can be removed destructively - (data "some-data") - (func "foo" (result i32) - ;; this can be removed destructively - (memory.init 0 - (i32.const 3) - (i32.const 3) - (i32.const 3)) - (i32.atomic.store8 - (i32.const 0) - ;; an add that can be optimized - (i32.add - (i32.const 97) - (i32.const 2) - ) - ) - ;; add some nops and blocks for reduction to remove - (nop) - (block (result i32) - (i32.atomic.load8_u - (i32.const 0) - ) - ) - ) -) diff -Nru binaryen-108/test/reduce/atomics-and-bulk-memory.wast.txt binaryen-99/test/reduce/atomics-and-bulk-memory.wast.txt --- binaryen-108/test/reduce/atomics-and-bulk-memory.wast.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reduce/atomics-and-bulk-memory.wast.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -(module - (type $none_=>_i32 (func (result i32))) - (memory $0 1 1) - (export "foo" (func $0)) - (func $0 (result i32) - (i32.atomic.store8 - (i32.const 0) - (i32.const 99) - ) - (i32.atomic.load8_u - (i32.const 0) - ) - ) -) - diff -Nru binaryen-108/test/reference-types.wast binaryen-99/test/reference-types.wast --- binaryen-108/test/reference-types.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reference-types.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,4 +1,4 @@ -;; reftype :: externref | funcref +;; reftype :: externref | funcref | exnref ;; NOTE: the subtyping relationship has been removed from the reference-types proposal but an ;; `--enable-anyref` feature flag is present in Binaryen that we use below to test subtyping. @@ -9,15 +9,16 @@ (module (type $sig_externref (func (param externref))) (type $sig_funcref (func (param funcref))) + (type $sig_exnref (func (param exnref))) (type $sig_anyref (func (param anyref))) (func $take_externref (param externref)) (func $take_funcref (param funcref)) + (func $take_exnref (param exnref)) (func $take_anyref (param anyref)) (func $foo) - (table funcref (elem $take_externref $take_funcref $take_anyref)) - (elem declare func $ref-taken-but-not-in-table) + (table funcref (elem $take_externref $take_funcref $take_exnref $take_anyref)) (import "env" "import_func" (func $import_func (param externref) (result funcref))) (import "env" "import_global" (global $import_global externref)) @@ -28,18 +29,19 @@ (global $global_externref (mut externref) (ref.null extern)) (global $global_funcref (mut funcref) (ref.null func)) (global $global_funcref_func (mut funcref) (ref.func $foo)) + (global $global_exnref (mut exnref) (ref.null exn)) (global $global_anyref (mut anyref) (ref.null any)) ;; Test subtype relationship in global initializer expressions (global $global_anyref2 (mut anyref) (ref.null extern)) (global $global_anyref3 (mut anyref) (ref.null func)) (global $global_anyref4 (mut anyref) (ref.func $foo)) - - (tag $e-i32 (param i32)) + (global $global_anyref5 (mut anyref) (ref.null exn)) (func $test (local $local_externref externref) (local $local_funcref funcref) + (local $local_exnref exnref) (local $local_anyref anyref) ;; Test types for local.get/set @@ -50,6 +52,9 @@ (local.set $local_funcref (global.get $global_funcref)) (local.set $local_funcref (ref.null func)) (local.set $local_funcref (ref.func $foo)) + (local.set $local_exnref (local.get $local_exnref)) + (local.set $local_exnref (global.get $global_exnref)) + (local.set $local_exnref (ref.null exn)) (local.set $local_anyref (local.get $local_anyref)) (local.set $local_anyref (global.get $global_anyref)) (local.set $local_anyref (ref.null any)) @@ -62,6 +67,9 @@ (local.set $local_anyref (global.get $global_funcref)) (local.set $local_anyref (ref.null func)) (local.set $local_anyref (ref.func $foo)) + (local.set $local_anyref (local.get $local_exnref)) + (local.set $local_anyref (global.get $global_exnref)) + (local.set $local_anyref (ref.null exn)) ;; Test types for global.get/set (global.set $global_externref (global.get $global_externref)) @@ -71,6 +79,9 @@ (global.set $global_funcref (local.get $local_funcref)) (global.set $global_funcref (ref.null func)) (global.set $global_funcref (ref.func $foo)) + (global.set $global_exnref (global.get $global_exnref)) + (global.set $global_exnref (local.get $local_exnref)) + (global.set $global_exnref (ref.null exn)) (global.set $global_anyref (global.get $global_anyref)) (global.set $global_anyref (local.get $local_anyref)) (global.set $global_anyref (ref.null any)) @@ -83,6 +94,9 @@ (global.set $global_anyref (local.get $local_funcref)) (global.set $global_anyref (ref.null func)) (global.set $global_anyref (ref.func $foo)) + (global.set $global_anyref (global.get $global_exnref)) + (global.set $global_anyref (local.get $local_exnref)) + (global.set $global_anyref (ref.null exn)) ;; Test function call params (call $take_externref (local.get $local_externref)) @@ -92,6 +106,9 @@ (call $take_funcref (global.get $global_funcref)) (call $take_funcref (ref.null func)) (call $take_funcref (ref.func $foo)) + (call $take_exnref (local.get $local_exnref)) + (call $take_exnref (global.get $global_exnref)) + (call $take_exnref (ref.null exn)) (call $take_anyref (local.get $local_anyref)) (call $take_anyref (global.get $global_anyref)) (call $take_anyref (ref.null any)) @@ -104,6 +121,9 @@ (call $take_anyref (global.get $global_funcref)) (call $take_anyref (ref.null func)) (call $take_anyref (ref.func $foo)) + (call $take_anyref (local.get $local_exnref)) + (call $take_anyref (global.get $global_exnref)) + (call $take_anyref (ref.null exn)) ;; Test call_indirect params (call_indirect (type $sig_externref) (local.get $local_externref) (i32.const 0)) @@ -113,6 +133,9 @@ (call_indirect (type $sig_funcref) (global.get $global_funcref) (i32.const 1)) (call_indirect (type $sig_funcref) (ref.null func) (i32.const 1)) (call_indirect (type $sig_funcref) (ref.func $foo) (i32.const 1)) + (call_indirect (type $sig_exnref) (local.get $local_exnref) (i32.const 2)) + (call_indirect (type $sig_exnref) (global.get $global_exnref) (i32.const 2)) + (call_indirect (type $sig_exnref) (ref.null exn) (i32.const 2)) (call_indirect (type $sig_anyref) (local.get $local_anyref) (i32.const 3)) (call_indirect (type $sig_anyref) (global.get $global_anyref) (i32.const 3)) (call_indirect (type $sig_anyref) (ref.null any) (i32.const 3)) @@ -125,6 +148,9 @@ (call_indirect (type $sig_anyref) (global.get $global_funcref) (i32.const 3)) (call_indirect (type $sig_anyref) (ref.null func) (i32.const 3)) (call_indirect (type $sig_anyref) (ref.func $foo) (i32.const 3)) + (call_indirect (type $sig_anyref) (local.get $local_exnref) (i32.const 3)) + (call_indirect (type $sig_anyref) (global.get $global_exnref) (i32.const 3)) + (call_indirect (type $sig_anyref) (ref.null exn) (i32.const 3)) ;; Test block return type (drop @@ -163,6 +189,21 @@ ) ) (drop + (block (result exnref) + (br_if 0 (local.get $local_exnref) (i32.const 1)) + ) + ) + (drop + (block (result exnref) + (br_if 0 (global.get $global_exnref) (i32.const 1)) + ) + ) + (drop + (block (result exnref) + (br_if 0 (ref.null exn) (i32.const 1)) + ) + ) + (drop (block (result anyref) (br_if 0 (local.get $local_anyref) (i32.const 1)) ) @@ -191,6 +232,11 @@ ) (drop (block (result anyref) + (br_if 0 (local.get $local_exnref) (i32.const 1)) + ) + ) + (drop + (block (result anyref) (br_if 0 (ref.null extern) (i32.const 1)) ) ) @@ -204,6 +250,11 @@ (br_if 0 (ref.func $foo) (i32.const 1)) ) ) + (drop + (block (result anyref) + (br_if 0 (ref.null exn) (i32.const 1)) + ) + ) ;; Test loop return type (drop @@ -242,6 +293,21 @@ ) ) (drop + (loop (result exnref) + (local.get $local_exnref) + ) + ) + (drop + (loop (result exnref) + (global.get $global_exnref) + ) + ) + (drop + (loop (result exnref) + (ref.null exn) + ) + ) + (drop (loop (result anyref) (local.get $local_anyref) ) @@ -293,6 +359,21 @@ (ref.func $foo) ) ) + (drop + (loop (result anyref) + (local.get $local_exnref) + ) + ) + (drop + (loop (result anyref) + (global.get $global_exnref) + ) + ) + (drop + (loop (result anyref) + (ref.null exn) + ) + ) ;; Test if return type (drop @@ -310,6 +391,13 @@ ) ) (drop + (if (result exnref) + (i32.const 1) + (local.get $local_exnref) + (ref.null exn) + ) + ) + (drop (if (result anyref) (i32.const 1) (local.get $local_anyref) @@ -328,6 +416,20 @@ (drop (if (result anyref) (i32.const 1) + (local.get $local_externref) + (local.get $local_exnref) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $local_funcref) + (local.get $local_exnref) + ) + ) + (drop + (if (result anyref) + (i32.const 1) (ref.null extern) (ref.null func) ) @@ -335,6 +437,20 @@ (drop (if (result anyref) (i32.const 1) + (ref.null extern) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null func) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) (ref.func $foo) (ref.null extern) ) @@ -346,8 +462,8 @@ (do (local.get $local_externref) ) - (catch $e-i32 - (drop (pop i32)) + (catch + (drop (pop exnref)) (ref.null extern) ) ) @@ -357,12 +473,22 @@ (do (ref.func $foo) ) - (catch $e-i32 - (drop (pop i32)) + (catch + (drop (pop exnref)) (ref.null func) ) ) ) + (drop + (try (result exnref) + (do + (ref.null exn) + ) + (catch + (pop exnref) + ) + ) + ) ;; Test subtype relationship for try return type (drop @@ -370,10 +496,31 @@ (do (local.get $local_externref) ) - (catch $e-i32 - (drop (pop i32)) + (catch + (drop (pop exnref)) + (ref.func $foo) + ) + ) + ) + (drop + (try (result anyref) + (do + (local.get $local_externref) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do (ref.func $foo) ) + (catch + (drop (pop exnref)) + (local.get $local_externref) + ) ) ) (drop @@ -381,12 +528,33 @@ (do (ref.func $foo) ) - (catch $e-i32 - (drop (pop i32)) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop (pop exnref)) (local.get $local_externref) ) ) ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop (pop exnref)) + (ref.func $foo) + ) + ) + ) ;; Test typed select (drop @@ -404,6 +572,13 @@ ) ) (drop + (select (result exnref) + (local.get $local_exnref) + (ref.null exn) + (i32.const 1) + ) + ) + (drop (select (result i32) (i32.const 0) (i32.const 2) @@ -421,11 +596,39 @@ ) (drop (select (result anyref) + (local.get $local_externref) + (local.get $local_exnref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $local_funcref) + (local.get $local_externref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) (local.get $local_funcref) + (local.get $local_exnref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $local_exnref) (local.get $local_externref) (i32.const 1) ) ) + (drop + (select (result anyref) + (local.get $local_exnref) + (local.get $local_funcref) + (i32.const 1) + ) + ) ;; ref.is_null takes any reference types (drop (ref.is_null (local.get $local_externref))) @@ -435,6 +638,9 @@ (drop (ref.is_null (global.get $global_funcref))) (drop (ref.is_null (ref.null func))) (drop (ref.is_null (ref.func $foo))) + (drop (ref.is_null (local.get $local_exnref))) + (drop (ref.is_null (global.get $global_exnref))) + (drop (ref.is_null (ref.null exn))) (drop (ref.is_null (local.get $local_anyref))) (drop (ref.is_null (global.get $global_anyref))) (drop (ref.is_null (ref.null any))) @@ -464,6 +670,16 @@ (func $return_funcref_func (result funcref) (ref.func $foo) ) + (func $return_exnref_local (result exnref) + (local $local_exnref exnref) + (local.get $local_exnref) + ) + (func $return_exnref_global (result exnref) + (global.get $global_exnref) + ) + (func $return_exnref_null (result exnref) + (ref.null exn) + ) (func $return_anyref_local (result anyref) (local $local_anyref anyref) (local.get $local_anyref) @@ -499,6 +715,16 @@ (func $return_anyref8 (result anyref) (ref.func $foo) ) + (func $return_anyref9 (result anyref) + (local $local_exnref exnref) + (local.get $local_exnref) + ) + (func $return_anyref10 (result anyref) + (global.get $global_exnref) + ) + (func $return_anyref11 (result anyref) + (ref.null exn) + ) ;; Test returns (func $returns_externref (result externref) @@ -514,6 +740,12 @@ (return (ref.func $foo)) (return (ref.null func)) ) + (func $returns_exnref (result exnref) + (local $local_exnref exnref) + (return (local.get $local_exnref)) + (return (global.get $global_exnref)) + (return (ref.null exn)) + ) (func $returns_anyref (result anyref) (local $local_anyref anyref) (return (local.get $local_anyref)) @@ -525,6 +757,7 @@ (func $returns_anyref2 (result anyref) (local $local_externref externref) (local $local_funcref funcref) + (local $local_exnref exnref) (return (local.get $local_externref)) (return (global.get $global_externref)) (return (ref.null extern)) @@ -532,14 +765,8 @@ (return (global.get $global_funcref)) (return (ref.func $foo)) (return (ref.null func)) + (return (local.get $local_exnref)) + (return (global.get $global_exnref)) + (return (ref.null exn)) ) - - (func $ref-user - (drop - ;; an "elem declare func" must be emitted for this ref.func which is not - ;; in the table - (ref.func $ref-taken-but-not-in-table) - ) - ) - (func $ref-taken-but-not-in-table) ) diff -Nru binaryen-108/test/reference-types.wast.fromBinary binaryen-99/test/reference-types.wast.fromBinary --- binaryen-108/test/reference-types.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reference-types.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,32 +1,38 @@ (module (type $none_=>_anyref (func (result anyref))) - (type $sig_anyref (func (param anyref))) - (type $sig_funcref (func (param funcref))) + (type $anyref_=>_none (func (param anyref))) + (type $funcref_=>_none (func (param funcref))) (type $none_=>_funcref (func (result funcref))) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_externref (func (result externref))) + (type $none_=>_exnref (func (result exnref))) (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) - (type $anyref_=>_funcref (func (param anyref) (result funcref))) - (import "env" "import_global" (global $import_global anyref)) - (import "env" "import_func" (func $import_func (param anyref) (result funcref))) - (global $global_externref (mut anyref) (ref.null any)) + (type $externref_=>_funcref (func (param externref) (result funcref))) + (import "env" "import_global" (global $import_global externref)) + (import "env" "import_func" (func $import_func (param externref) (result funcref))) + (table $0 4 4 funcref) + (elem (i32.const 0) $take_externref $take_funcref $take_exnref $take_anyref) + (global $global_externref (mut externref) (ref.null extern)) (global $global_funcref (mut funcref) (ref.null func)) (global $global_funcref_func (mut funcref) (ref.func $foo)) + (global $global_exnref (mut exnref) (ref.null exn)) (global $global_anyref (mut anyref) (ref.null any)) - (global $global_anyref2 (mut anyref) (ref.null any)) + (global $global_anyref2 (mut anyref) (ref.null extern)) (global $global_anyref3 (mut anyref) (ref.null func)) (global $global_anyref4 (mut anyref) (ref.func $foo)) - (table $0 3 3 funcref) - (elem (i32.const 0) $take_externref $take_funcref $take_anyref) - (elem declare func $foo $ref-taken-but-not-in-table) - (tag $tag$0 (param i32)) + (global $global_anyref5 (mut anyref) (ref.null exn)) (export "export_func" (func $import_func)) (export "export_global" (global $import_global)) - (func $take_externref (param $0 anyref) + (func $take_externref (param $0 externref) (nop) ) (func $take_funcref (param $0 funcref) (nop) ) + (func $take_exnref (param $0 exnref) + (nop) + ) (func $take_anyref (param $0 anyref) (nop) ) @@ -34,30 +40,40 @@ (nop) ) (func $test - (local $local_externref anyref) + (local $local_externref funcref) + (local $local_funcref externref) + (local $local_exnref exnref) (local $local_anyref anyref) - (local $local_funcref funcref) - (local.set $local_externref - (local.get $local_externref) + (local.set $local_funcref + (local.get $local_funcref) ) - (local.set $local_externref + (local.set $local_funcref (global.get $global_externref) ) - (local.set $local_externref - (ref.null any) - ) (local.set $local_funcref - (local.get $local_funcref) + (ref.null extern) ) - (local.set $local_funcref + (local.set $local_externref + (local.get $local_externref) + ) + (local.set $local_externref (global.get $global_funcref) ) - (local.set $local_funcref + (local.set $local_externref (ref.null func) ) - (local.set $local_funcref + (local.set $local_externref (ref.func $foo) ) + (local.set $local_exnref + (local.get $local_exnref) + ) + (local.set $local_exnref + (global.get $global_exnref) + ) + (local.set $local_exnref + (ref.null exn) + ) (local.set $local_anyref (local.get $local_anyref) ) @@ -68,16 +84,16 @@ (ref.null any) ) (local.set $local_anyref - (local.get $local_externref) + (local.get $local_funcref) ) (local.set $local_anyref (global.get $global_externref) ) (local.set $local_anyref - (ref.null any) + (ref.null extern) ) (local.set $local_anyref - (local.get $local_funcref) + (local.get $local_externref) ) (local.set $local_anyref (global.get $global_funcref) @@ -88,20 +104,29 @@ (local.set $local_anyref (ref.func $foo) ) + (local.set $local_anyref + (local.get $local_exnref) + ) + (local.set $local_anyref + (global.get $global_exnref) + ) + (local.set $local_anyref + (ref.null exn) + ) (global.set $global_externref (global.get $global_externref) ) (global.set $global_externref - (local.get $local_externref) + (local.get $local_funcref) ) (global.set $global_externref - (ref.null any) + (ref.null extern) ) (global.set $global_funcref (global.get $global_funcref) ) (global.set $global_funcref - (local.get $local_funcref) + (local.get $local_externref) ) (global.set $global_funcref (ref.null func) @@ -109,6 +134,15 @@ (global.set $global_funcref (ref.func $foo) ) + (global.set $global_exnref + (global.get $global_exnref) + ) + (global.set $global_exnref + (local.get $local_exnref) + ) + (global.set $global_exnref + (ref.null exn) + ) (global.set $global_anyref (global.get $global_anyref) ) @@ -122,16 +156,16 @@ (global.get $global_externref) ) (global.set $global_anyref - (local.get $local_externref) + (local.get $local_funcref) ) (global.set $global_anyref - (ref.null any) + (ref.null extern) ) (global.set $global_anyref (global.get $global_funcref) ) (global.set $global_anyref - (local.get $local_funcref) + (local.get $local_externref) ) (global.set $global_anyref (ref.null func) @@ -139,17 +173,26 @@ (global.set $global_anyref (ref.func $foo) ) + (global.set $global_anyref + (global.get $global_exnref) + ) + (global.set $global_anyref + (local.get $local_exnref) + ) + (global.set $global_anyref + (ref.null exn) + ) (call $take_externref - (local.get $local_externref) + (local.get $local_funcref) ) (call $take_externref (global.get $global_externref) ) (call $take_externref - (ref.null any) + (ref.null extern) ) (call $take_funcref - (local.get $local_funcref) + (local.get $local_externref) ) (call $take_funcref (global.get $global_funcref) @@ -160,6 +203,15 @@ (call $take_funcref (ref.func $foo) ) + (call $take_exnref + (local.get $local_exnref) + ) + (call $take_exnref + (global.get $global_exnref) + ) + (call $take_exnref + (ref.null exn) + ) (call $take_anyref (local.get $local_anyref) ) @@ -170,16 +222,16 @@ (ref.null any) ) (call $take_anyref - (local.get $local_externref) + (local.get $local_funcref) ) (call $take_anyref (global.get $global_externref) ) (call $take_anyref - (ref.null any) + (ref.null extern) ) (call $take_anyref - (local.get $local_funcref) + (local.get $local_externref) ) (call $take_anyref (global.get $global_funcref) @@ -190,84 +242,117 @@ (call $take_anyref (ref.func $foo) ) - (call_indirect $0 (type $sig_anyref) - (local.get $local_externref) + (call $take_anyref + (local.get $local_exnref) + ) + (call $take_anyref + (global.get $global_exnref) + ) + (call $take_anyref + (ref.null exn) + ) + (call_indirect (type $externref_=>_none) + (local.get $local_funcref) (i32.const 0) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $externref_=>_none) (global.get $global_externref) (i32.const 0) ) - (call_indirect $0 (type $sig_anyref) - (ref.null any) + (call_indirect (type $externref_=>_none) + (ref.null extern) (i32.const 0) ) - (call_indirect $0 (type $sig_funcref) - (local.get $local_funcref) + (call_indirect (type $funcref_=>_none) + (local.get $local_externref) (i32.const 1) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (global.get $global_funcref) (i32.const 1) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (ref.null func) (i32.const 1) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (ref.func $foo) (i32.const 1) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $exnref_=>_none) + (local.get $local_exnref) + (i32.const 2) + ) + (call_indirect (type $exnref_=>_none) + (global.get $global_exnref) + (i32.const 2) + ) + (call_indirect (type $exnref_=>_none) + (ref.null exn) + (i32.const 2) + ) + (call_indirect (type $anyref_=>_none) (local.get $local_anyref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (global.get $global_anyref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (ref.null any) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) - (local.get $local_externref) + (call_indirect (type $anyref_=>_none) + (local.get $local_funcref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (global.get $global_externref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) - (ref.null any) + (call_indirect (type $anyref_=>_none) + (ref.null extern) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) - (local.get $local_funcref) + (call_indirect (type $anyref_=>_none) + (local.get $local_externref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (global.get $global_funcref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (ref.null func) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (ref.func $foo) (i32.const 3) ) + (call_indirect (type $anyref_=>_none) + (local.get $local_exnref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global_exnref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null exn) + (i32.const 3) + ) (drop - (block $label$1 (result anyref) + (block $label$1 (result externref) (br_if $label$1 - (local.get $local_externref) + (local.get $local_funcref) (i32.const 1) ) ) ) (drop - (block $label$2 (result anyref) + (block $label$2 (result externref) (br_if $label$2 (global.get $global_externref) (i32.const 1) @@ -275,9 +360,9 @@ ) ) (drop - (block $label$3 (result anyref) + (block $label$3 (result externref) (br_if $label$3 - (ref.null any) + (ref.null extern) (i32.const 1) ) ) @@ -285,7 +370,7 @@ (drop (block $label$4 (result funcref) (br_if $label$4 - (local.get $local_funcref) + (local.get $local_externref) (i32.const 1) ) ) @@ -315,25 +400,25 @@ ) ) (drop - (block $label$8 (result anyref) + (block $label$8 (result exnref) (br_if $label$8 - (local.get $local_anyref) + (local.get $local_exnref) (i32.const 1) ) ) ) (drop - (block $label$9 (result anyref) + (block $label$9 (result exnref) (br_if $label$9 - (global.get $global_anyref) + (global.get $global_exnref) (i32.const 1) ) ) ) (drop - (block $label$10 (result anyref) + (block $label$10 (result exnref) (br_if $label$10 - (ref.null any) + (ref.null exn) (i32.const 1) ) ) @@ -341,7 +426,7 @@ (drop (block $label$11 (result anyref) (br_if $label$11 - (local.get $local_externref) + (local.get $local_anyref) (i32.const 1) ) ) @@ -349,7 +434,7 @@ (drop (block $label$12 (result anyref) (br_if $label$12 - (local.get $local_funcref) + (global.get $global_anyref) (i32.const 1) ) ) @@ -365,7 +450,7 @@ (drop (block $label$14 (result anyref) (br_if $label$14 - (ref.null func) + (local.get $local_funcref) (i32.const 1) ) ) @@ -373,111 +458,188 @@ (drop (block $label$15 (result anyref) (br_if $label$15 + (local.get $local_externref) + (i32.const 1) + ) + ) + ) + (drop + (block $label$16 (result anyref) + (br_if $label$16 + (local.get $local_exnref) + (i32.const 1) + ) + ) + ) + (drop + (block $label$17 (result anyref) + (br_if $label$17 + (ref.null extern) + (i32.const 1) + ) + ) + ) + (drop + (block $label$18 (result anyref) + (br_if $label$18 + (ref.null func) + (i32.const 1) + ) + ) + ) + (drop + (block $label$19 (result anyref) + (br_if $label$19 (ref.func $foo) (i32.const 1) ) ) ) (drop - (loop $label$16 (result anyref) - (local.get $local_externref) + (block $label$20 (result anyref) + (br_if $label$20 + (ref.null exn) + (i32.const 1) + ) + ) + ) + (drop + (loop $label$21 (result externref) + (local.get $local_funcref) ) ) (drop - (loop $label$17 (result anyref) + (loop $label$22 (result externref) (global.get $global_externref) ) ) (drop - (loop $label$18 (result anyref) - (ref.null any) + (loop $label$23 (result externref) + (ref.null extern) ) ) (drop - (loop $label$19 (result funcref) - (local.get $local_funcref) + (loop $label$24 (result funcref) + (local.get $local_externref) ) ) (drop - (loop $label$20 (result funcref) + (loop $label$25 (result funcref) (global.get $global_funcref) ) ) (drop - (loop $label$21 (result funcref) + (loop $label$26 (result funcref) (ref.null func) ) ) (drop - (loop $label$22 (result funcref) + (loop $label$27 (result funcref) (ref.func $foo) ) ) (drop - (loop $label$23 (result anyref) + (loop $label$28 (result exnref) + (local.get $local_exnref) + ) + ) + (drop + (loop $label$29 (result exnref) + (global.get $global_exnref) + ) + ) + (drop + (loop $label$30 (result exnref) + (ref.null exn) + ) + ) + (drop + (loop $label$31 (result anyref) (local.get $local_anyref) ) ) (drop - (loop $label$24 (result anyref) + (loop $label$32 (result anyref) (global.get $global_anyref) ) ) (drop - (loop $label$25 (result anyref) + (loop $label$33 (result anyref) (ref.null any) ) ) (drop - (loop $label$26 (result anyref) - (local.get $local_externref) + (loop $label$34 (result anyref) + (local.get $local_funcref) ) ) (drop - (loop $label$27 (result anyref) + (loop $label$35 (result anyref) (global.get $global_externref) ) ) (drop - (loop $label$28 (result anyref) - (ref.null any) + (loop $label$36 (result anyref) + (ref.null extern) ) ) (drop - (loop $label$29 (result anyref) - (local.get $local_funcref) + (loop $label$37 (result anyref) + (local.get $local_externref) ) ) (drop - (loop $label$30 (result anyref) + (loop $label$38 (result anyref) (global.get $global_funcref) ) ) (drop - (loop $label$31 (result anyref) + (loop $label$39 (result anyref) (ref.null func) ) ) (drop - (loop $label$32 (result anyref) + (loop $label$40 (result anyref) (ref.func $foo) ) ) (drop - (if (result anyref) + (loop $label$41 (result anyref) + (local.get $local_exnref) + ) + ) + (drop + (loop $label$42 (result anyref) + (global.get $global_exnref) + ) + ) + (drop + (loop $label$43 (result anyref) + (ref.null exn) + ) + ) + (drop + (if (result externref) (i32.const 1) - (local.get $local_externref) - (ref.null any) + (local.get $local_funcref) + (ref.null extern) ) ) (drop (if (result funcref) (i32.const 1) - (local.get $local_funcref) + (local.get $local_externref) (ref.null func) ) ) (drop + (if (result exnref) + (i32.const 1) + (local.get $local_exnref) + (ref.null exn) + ) + ) + (drop (if (result anyref) (i32.const 1) (local.get $local_anyref) @@ -487,91 +649,182 @@ (drop (if (result anyref) (i32.const 1) + (local.get $local_funcref) (local.get $local_externref) + ) + ) + (drop + (if (result anyref) + (i32.const 1) (local.get $local_funcref) + (local.get $local_exnref) ) ) (drop (if (result anyref) (i32.const 1) - (ref.null any) + (local.get $local_externref) + (local.get $local_exnref) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null extern) (ref.null func) ) ) (drop (if (result anyref) (i32.const 1) + (ref.null extern) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null func) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) (ref.func $foo) - (ref.null any) + (ref.null extern) ) ) (drop - (try $label$47 (result anyref) + (try (result externref) (do - (local.get $local_externref) + (local.get $local_funcref) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) - (ref.null any) + (ref.null extern) ) ) ) (drop - (try $label$50 (result funcref) + (try (result funcref) (do (ref.func $foo) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) (ref.null func) ) ) ) (drop - (try $label$53 (result anyref) + (try (result exnref) (do - (local.get $local_externref) + (ref.null exn) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do + (local.get $local_funcref) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) (ref.func $foo) ) ) ) (drop - (try $label$56 (result anyref) + (try (result anyref) + (do + (local.get $local_funcref) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) (do (ref.func $foo) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) - (local.get $local_externref) + (local.get $local_funcref) ) ) ) (drop - (select (result anyref) - (local.get $local_externref) - (ref.null any) + (try (result anyref) + (do + (ref.func $foo) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (pop exnref) + ) + (local.get $local_funcref) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (pop exnref) + ) + (ref.func $foo) + ) + ) + ) + (drop + (select (result externref) + (local.get $local_funcref) + (ref.null extern) (i32.const 1) ) ) (drop (select (result funcref) - (local.get $local_funcref) + (local.get $local_externref) (ref.null func) (i32.const 1) ) ) (drop + (select (result exnref) + (local.get $local_exnref) + (ref.null exn) + (i32.const 1) + ) + ) + (drop (select (i32.const 0) (i32.const 2) @@ -580,21 +833,49 @@ ) (drop (select (result anyref) + (local.get $local_funcref) (local.get $local_externref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) (local.get $local_funcref) + (local.get $local_exnref) (i32.const 1) ) ) (drop (select (result anyref) + (local.get $local_externref) (local.get $local_funcref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) (local.get $local_externref) + (local.get $local_exnref) (i32.const 1) ) ) (drop - (ref.is_null + (select (result anyref) + (local.get $local_exnref) + (local.get $local_funcref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $local_exnref) (local.get $local_externref) + (i32.const 1) + ) + ) + (drop + (ref.is_null + (local.get $local_funcref) ) ) (drop @@ -604,12 +885,12 @@ ) (drop (ref.is_null - (ref.null any) + (ref.null extern) ) ) (drop (ref.is_null - (local.get $local_funcref) + (local.get $local_externref) ) ) (drop @@ -629,6 +910,21 @@ ) (drop (ref.is_null + (local.get $local_exnref) + ) + ) + (drop + (ref.is_null + (global.get $global_exnref) + ) + ) + (drop + (ref.is_null + (ref.null exn) + ) + ) + (drop + (ref.is_null (local.get $local_anyref) ) ) @@ -643,15 +939,15 @@ ) ) ) - (func $return_externref_local (result anyref) - (local $local_externref anyref) + (func $return_externref_local (result externref) + (local $local_externref externref) (local.get $local_externref) ) - (func $return_externref_global (result anyref) + (func $return_externref_global (result externref) (global.get $global_externref) ) - (func $return_externref_null (result anyref) - (ref.null any) + (func $return_externref_null (result externref) + (ref.null extern) ) (func $return_funcref_local (result funcref) (local $local_funcref funcref) @@ -666,6 +962,16 @@ (func $return_funcref_func (result funcref) (ref.func $foo) ) + (func $return_exnref_local (result exnref) + (local $local_exnref exnref) + (local.get $local_exnref) + ) + (func $return_exnref_global (result exnref) + (global.get $global_exnref) + ) + (func $return_exnref_null (result exnref) + (ref.null exn) + ) (func $return_anyref_local (result anyref) (local $local_anyref anyref) (local.get $local_anyref) @@ -677,14 +983,14 @@ (ref.null any) ) (func $return_anyref2 (result anyref) - (local $local_externref anyref) + (local $local_externref externref) (local.get $local_externref) ) (func $return_anyref3 (result anyref) (global.get $global_externref) ) (func $return_anyref4 (result anyref) - (ref.null any) + (ref.null extern) ) (func $return_anyref5 (result anyref) (local $local_funcref funcref) @@ -699,8 +1005,18 @@ (func $return_anyref8 (result anyref) (ref.func $foo) ) - (func $returns_externref (result anyref) - (local $local_externref anyref) + (func $return_anyref9 (result anyref) + (local $local_exnref exnref) + (local.get $local_exnref) + ) + (func $return_anyref10 (result anyref) + (global.get $global_exnref) + ) + (func $return_anyref11 (result anyref) + (ref.null exn) + ) + (func $returns_externref (result externref) + (local $local_externref externref) (return (local.get $local_externref) ) @@ -711,6 +1027,12 @@ (local.get $local_funcref) ) ) + (func $returns_exnref (result exnref) + (local $local_exnref exnref) + (return + (local.get $local_exnref) + ) + ) (func $returns_anyref (result anyref) (local $local_anyref anyref) (return @@ -718,19 +1040,12 @@ ) ) (func $returns_anyref2 (result anyref) - (local $local_externref anyref) - (local $local_funcref funcref) + (local $local_externref funcref) + (local $local_funcref externref) + (local $local_exnref exnref) (return - (local.get $local_externref) - ) - ) - (func $ref-user - (drop - (ref.func $ref-taken-but-not-in-table) + (local.get $local_funcref) ) ) - (func $ref-taken-but-not-in-table - (nop) - ) ) diff -Nru binaryen-108/test/reference-types.wast.fromBinary.noDebugInfo binaryen-99/test/reference-types.wast.fromBinary.noDebugInfo --- binaryen-108/test/reference-types.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reference-types.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -3,153 +3,196 @@ (type $anyref_=>_none (func (param anyref))) (type $funcref_=>_none (func (param funcref))) (type $none_=>_funcref (func (result funcref))) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_externref (func (result externref))) + (type $none_=>_exnref (func (result exnref))) (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) - (type $anyref_=>_funcref (func (param anyref) (result funcref))) - (import "env" "import_global" (global $gimport$0 anyref)) - (import "env" "import_func" (func $fimport$0 (param anyref) (result funcref))) - (global $global$0 (mut anyref) (ref.null any)) + (type $externref_=>_funcref (func (param externref) (result funcref))) + (import "env" "import_global" (global $gimport$0 externref)) + (import "env" "import_func" (func $fimport$0 (param externref) (result funcref))) + (table $0 4 4 funcref) + (elem (i32.const 0) $0 $1 $2 $3) + (global $global$0 (mut externref) (ref.null extern)) (global $global$1 (mut funcref) (ref.null func)) - (global $global$2 (mut funcref) (ref.func $3)) - (global $global$3 (mut anyref) (ref.null any)) + (global $global$2 (mut funcref) (ref.func $4)) + (global $global$3 (mut exnref) (ref.null exn)) (global $global$4 (mut anyref) (ref.null any)) - (global $global$5 (mut anyref) (ref.null func)) - (global $global$6 (mut anyref) (ref.func $3)) - (table $0 3 3 funcref) - (elem (i32.const 0) $0 $1 $2) - (elem declare func $27 $3) - (tag $tag$0 (param i32)) + (global $global$5 (mut anyref) (ref.null extern)) + (global $global$6 (mut anyref) (ref.null func)) + (global $global$7 (mut anyref) (ref.func $4)) + (global $global$8 (mut anyref) (ref.null exn)) (export "export_func" (func $fimport$0)) (export "export_global" (global $gimport$0)) - (func $0 (param $0 anyref) + (func $0 (param $0 externref) (nop) ) (func $1 (param $0 funcref) (nop) ) - (func $2 (param $0 anyref) + (func $2 (param $0 exnref) (nop) ) - (func $3 + (func $3 (param $0 anyref) (nop) ) (func $4 - (local $0 anyref) - (local $1 anyref) - (local $2 funcref) + (nop) + ) + (func $5 + (local $0 funcref) + (local $1 externref) + (local $2 exnref) + (local $3 anyref) + (local.set $1 + (local.get $1) + ) + (local.set $1 + (global.get $global$0) + ) + (local.set $1 + (ref.null extern) + ) (local.set $0 (local.get $0) ) (local.set $0 - (global.get $global$0) + (global.get $global$1) ) (local.set $0 - (ref.null any) + (ref.null func) + ) + (local.set $0 + (ref.func $4) ) (local.set $2 (local.get $2) ) (local.set $2 - (global.get $global$1) + (global.get $global$3) ) (local.set $2 - (ref.null func) + (ref.null exn) ) - (local.set $2 - (ref.func $3) + (local.set $3 + (local.get $3) ) - (local.set $1 - (local.get $1) + (local.set $3 + (global.get $global$4) ) - (local.set $1 - (global.get $global$3) - ) - (local.set $1 + (local.set $3 (ref.null any) ) - (local.set $1 - (local.get $0) + (local.set $3 + (local.get $1) ) - (local.set $1 + (local.set $3 (global.get $global$0) ) - (local.set $1 - (ref.null any) + (local.set $3 + (ref.null extern) ) - (local.set $1 - (local.get $2) + (local.set $3 + (local.get $0) ) - (local.set $1 + (local.set $3 (global.get $global$1) ) - (local.set $1 + (local.set $3 (ref.null func) ) - (local.set $1 - (ref.func $3) + (local.set $3 + (ref.func $4) + ) + (local.set $3 + (local.get $2) + ) + (local.set $3 + (global.get $global$3) + ) + (local.set $3 + (ref.null exn) ) (global.set $global$0 (global.get $global$0) ) (global.set $global$0 - (local.get $0) + (local.get $1) ) (global.set $global$0 - (ref.null any) + (ref.null extern) ) (global.set $global$1 (global.get $global$1) ) (global.set $global$1 - (local.get $2) + (local.get $0) ) (global.set $global$1 (ref.null func) ) (global.set $global$1 - (ref.func $3) + (ref.func $4) ) (global.set $global$3 (global.get $global$3) ) (global.set $global$3 - (local.get $1) + (local.get $2) ) (global.set $global$3 + (ref.null exn) + ) + (global.set $global$4 + (global.get $global$4) + ) + (global.set $global$4 + (local.get $3) + ) + (global.set $global$4 (ref.null any) ) - (global.set $global$3 + (global.set $global$4 (global.get $global$0) ) - (global.set $global$3 - (local.get $0) + (global.set $global$4 + (local.get $1) ) - (global.set $global$3 - (ref.null any) + (global.set $global$4 + (ref.null extern) ) - (global.set $global$3 + (global.set $global$4 (global.get $global$1) ) - (global.set $global$3 - (local.get $2) + (global.set $global$4 + (local.get $0) ) - (global.set $global$3 + (global.set $global$4 (ref.null func) ) - (global.set $global$3 - (ref.func $3) + (global.set $global$4 + (ref.func $4) + ) + (global.set $global$4 + (global.get $global$3) + ) + (global.set $global$4 + (local.get $2) + ) + (global.set $global$4 + (ref.null exn) ) (call $0 - (local.get $0) + (local.get $1) ) (call $0 (global.get $global$0) ) (call $0 - (ref.null any) + (ref.null extern) ) (call $1 - (local.get $2) + (local.get $0) ) (call $1 (global.get $global$1) @@ -158,116 +201,158 @@ (ref.null func) ) (call $1 - (ref.func $3) + (ref.func $4) ) (call $2 - (local.get $1) + (local.get $2) ) (call $2 (global.get $global$3) ) (call $2 + (ref.null exn) + ) + (call $3 + (local.get $3) + ) + (call $3 + (global.get $global$4) + ) + (call $3 (ref.null any) ) - (call $2 - (local.get $0) + (call $3 + (local.get $1) ) - (call $2 + (call $3 (global.get $global$0) ) - (call $2 - (ref.null any) + (call $3 + (ref.null extern) ) - (call $2 - (local.get $2) + (call $3 + (local.get $0) ) - (call $2 + (call $3 (global.get $global$1) ) - (call $2 + (call $3 (ref.null func) ) - (call $2 - (ref.func $3) + (call $3 + (ref.func $4) ) - (call_indirect $0 (type $anyref_=>_none) - (local.get $0) + (call $3 + (local.get $2) + ) + (call $3 + (global.get $global$3) + ) + (call $3 + (ref.null exn) + ) + (call_indirect (type $externref_=>_none) + (local.get $1) (i32.const 0) ) - (call_indirect $0 (type $anyref_=>_none) + (call_indirect (type $externref_=>_none) (global.get $global$0) (i32.const 0) ) - (call_indirect $0 (type $anyref_=>_none) - (ref.null any) + (call_indirect (type $externref_=>_none) + (ref.null extern) (i32.const 0) ) - (call_indirect $0 (type $funcref_=>_none) - (local.get $2) + (call_indirect (type $funcref_=>_none) + (local.get $0) (i32.const 1) ) - (call_indirect $0 (type $funcref_=>_none) + (call_indirect (type $funcref_=>_none) (global.get $global$1) (i32.const 1) ) - (call_indirect $0 (type $funcref_=>_none) + (call_indirect (type $funcref_=>_none) (ref.null func) (i32.const 1) ) - (call_indirect $0 (type $funcref_=>_none) - (ref.func $3) + (call_indirect (type $funcref_=>_none) + (ref.func $4) (i32.const 1) ) - (call_indirect $0 (type $anyref_=>_none) - (local.get $1) - (i32.const 3) + (call_indirect (type $exnref_=>_none) + (local.get $2) + (i32.const 2) ) - (call_indirect $0 (type $anyref_=>_none) + (call_indirect (type $exnref_=>_none) (global.get $global$3) + (i32.const 2) + ) + (call_indirect (type $exnref_=>_none) + (ref.null exn) + (i32.const 2) + ) + (call_indirect (type $anyref_=>_none) + (local.get $3) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) + (call_indirect (type $anyref_=>_none) + (global.get $global$4) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) (ref.null any) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) - (local.get $0) + (call_indirect (type $anyref_=>_none) + (local.get $1) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) + (call_indirect (type $anyref_=>_none) (global.get $global$0) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) - (ref.null any) + (call_indirect (type $anyref_=>_none) + (ref.null extern) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) - (local.get $2) + (call_indirect (type $anyref_=>_none) + (local.get $0) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) + (call_indirect (type $anyref_=>_none) (global.get $global$1) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) + (call_indirect (type $anyref_=>_none) (ref.null func) (i32.const 3) ) - (call_indirect $0 (type $anyref_=>_none) - (ref.func $3) + (call_indirect (type $anyref_=>_none) + (ref.func $4) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (local.get $2) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global$3) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null exn) (i32.const 3) ) (drop - (block $label$1 (result anyref) + (block $label$1 (result externref) (br_if $label$1 - (local.get $0) + (local.get $1) (i32.const 1) ) ) ) (drop - (block $label$2 (result anyref) + (block $label$2 (result externref) (br_if $label$2 (global.get $global$0) (i32.const 1) @@ -275,9 +360,9 @@ ) ) (drop - (block $label$3 (result anyref) + (block $label$3 (result externref) (br_if $label$3 - (ref.null any) + (ref.null extern) (i32.const 1) ) ) @@ -285,7 +370,7 @@ (drop (block $label$4 (result funcref) (br_if $label$4 - (local.get $2) + (local.get $0) (i32.const 1) ) ) @@ -309,21 +394,21 @@ (drop (block $label$7 (result funcref) (br_if $label$7 - (ref.func $3) + (ref.func $4) (i32.const 1) ) ) ) (drop - (block $label$8 (result anyref) + (block $label$8 (result exnref) (br_if $label$8 - (local.get $1) + (local.get $2) (i32.const 1) ) ) ) (drop - (block $label$9 (result anyref) + (block $label$9 (result exnref) (br_if $label$9 (global.get $global$3) (i32.const 1) @@ -331,9 +416,9 @@ ) ) (drop - (block $label$10 (result anyref) + (block $label$10 (result exnref) (br_if $label$10 - (ref.null any) + (ref.null exn) (i32.const 1) ) ) @@ -341,7 +426,7 @@ (drop (block $label$11 (result anyref) (br_if $label$11 - (local.get $0) + (local.get $3) (i32.const 1) ) ) @@ -349,7 +434,7 @@ (drop (block $label$12 (result anyref) (br_if $label$12 - (local.get $2) + (global.get $global$4) (i32.const 1) ) ) @@ -365,7 +450,7 @@ (drop (block $label$14 (result anyref) (br_if $label$14 - (ref.null func) + (local.get $1) (i32.const 1) ) ) @@ -373,205 +458,373 @@ (drop (block $label$15 (result anyref) (br_if $label$15 - (ref.func $3) + (local.get $0) (i32.const 1) ) ) ) (drop - (loop $label$16 (result anyref) - (local.get $0) + (block $label$16 (result anyref) + (br_if $label$16 + (local.get $2) + (i32.const 1) + ) + ) + ) + (drop + (block $label$17 (result anyref) + (br_if $label$17 + (ref.null extern) + (i32.const 1) + ) ) ) (drop - (loop $label$17 (result anyref) + (block $label$18 (result anyref) + (br_if $label$18 + (ref.null func) + (i32.const 1) + ) + ) + ) + (drop + (block $label$19 (result anyref) + (br_if $label$19 + (ref.func $4) + (i32.const 1) + ) + ) + ) + (drop + (block $label$20 (result anyref) + (br_if $label$20 + (ref.null exn) + (i32.const 1) + ) + ) + ) + (drop + (loop $label$21 (result externref) + (local.get $1) + ) + ) + (drop + (loop $label$22 (result externref) (global.get $global$0) ) ) (drop - (loop $label$18 (result anyref) - (ref.null any) + (loop $label$23 (result externref) + (ref.null extern) ) ) (drop - (loop $label$19 (result funcref) - (local.get $2) + (loop $label$24 (result funcref) + (local.get $0) ) ) (drop - (loop $label$20 (result funcref) + (loop $label$25 (result funcref) (global.get $global$1) ) ) (drop - (loop $label$21 (result funcref) + (loop $label$26 (result funcref) (ref.null func) ) ) (drop - (loop $label$22 (result funcref) - (ref.func $3) + (loop $label$27 (result funcref) + (ref.func $4) ) ) (drop - (loop $label$23 (result anyref) - (local.get $1) + (loop $label$28 (result exnref) + (local.get $2) ) ) (drop - (loop $label$24 (result anyref) + (loop $label$29 (result exnref) (global.get $global$3) ) ) (drop - (loop $label$25 (result anyref) + (loop $label$30 (result exnref) + (ref.null exn) + ) + ) + (drop + (loop $label$31 (result anyref) + (local.get $3) + ) + ) + (drop + (loop $label$32 (result anyref) + (global.get $global$4) + ) + ) + (drop + (loop $label$33 (result anyref) (ref.null any) ) ) (drop - (loop $label$26 (result anyref) - (local.get $0) + (loop $label$34 (result anyref) + (local.get $1) ) ) (drop - (loop $label$27 (result anyref) + (loop $label$35 (result anyref) (global.get $global$0) ) ) (drop - (loop $label$28 (result anyref) - (ref.null any) + (loop $label$36 (result anyref) + (ref.null extern) ) ) (drop - (loop $label$29 (result anyref) - (local.get $2) + (loop $label$37 (result anyref) + (local.get $0) ) ) (drop - (loop $label$30 (result anyref) + (loop $label$38 (result anyref) (global.get $global$1) ) ) (drop - (loop $label$31 (result anyref) + (loop $label$39 (result anyref) (ref.null func) ) ) (drop - (loop $label$32 (result anyref) - (ref.func $3) + (loop $label$40 (result anyref) + (ref.func $4) ) ) (drop - (if (result anyref) + (loop $label$41 (result anyref) + (local.get $2) + ) + ) + (drop + (loop $label$42 (result anyref) + (global.get $global$3) + ) + ) + (drop + (loop $label$43 (result anyref) + (ref.null exn) + ) + ) + (drop + (if (result externref) (i32.const 1) - (local.get $0) - (ref.null any) + (local.get $1) + (ref.null extern) ) ) (drop (if (result funcref) (i32.const 1) - (local.get $2) + (local.get $0) (ref.null func) ) ) (drop + (if (result exnref) + (i32.const 1) + (local.get $2) + (ref.null exn) + ) + ) + (drop (if (result anyref) (i32.const 1) - (local.get $1) + (local.get $3) (ref.null any) ) ) (drop (if (result anyref) (i32.const 1) + (local.get $1) (local.get $0) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $1) (local.get $2) ) ) (drop (if (result anyref) (i32.const 1) - (ref.null any) + (local.get $0) + (local.get $2) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null extern) (ref.null func) ) ) (drop (if (result anyref) (i32.const 1) - (ref.func $3) - (ref.null any) + (ref.null extern) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null func) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.func $4) + (ref.null extern) ) ) (drop - (try $label$47 (result anyref) + (try (result externref) (do - (local.get $0) + (local.get $1) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) - (ref.null any) + (ref.null extern) ) ) ) (drop - (try $label$50 (result funcref) + (try (result funcref) (do - (ref.func $3) + (ref.func $4) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) (ref.null func) ) ) ) (drop - (try $label$53 (result anyref) + (try (result exnref) (do - (local.get $0) + (ref.null exn) ) - (catch $tag$0 + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do + (local.get $1) + ) + (catch (drop - (pop i32) + (pop exnref) ) - (ref.func $3) + (ref.func $4) + ) + ) + ) + (drop + (try (result anyref) + (do + (local.get $1) + ) + (catch + (pop exnref) ) ) ) (drop - (try $label$56 (result anyref) + (try (result anyref) (do - (ref.func $3) + (ref.func $4) ) - (catch $tag$0 + (catch (drop - (pop i32) + (pop exnref) ) - (local.get $0) + (local.get $1) ) ) ) (drop - (select (result anyref) - (local.get $0) - (ref.null any) + (try (result anyref) + (do + (ref.func $4) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (pop exnref) + ) + (local.get $1) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (pop exnref) + ) + (ref.func $4) + ) + ) + ) + (drop + (select (result externref) + (local.get $1) + (ref.null extern) (i32.const 1) ) ) (drop (select (result funcref) - (local.get $2) + (local.get $0) (ref.null func) (i32.const 1) ) ) (drop + (select (result exnref) + (local.get $2) + (ref.null exn) + (i32.const 1) + ) + ) + (drop (select (i32.const 0) (i32.const 2) @@ -580,6 +833,27 @@ ) (drop (select (result anyref) + (local.get $1) + (local.get $0) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $1) + (local.get $2) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $0) + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select (result anyref) (local.get $0) (local.get $2) (i32.const 1) @@ -588,13 +862,20 @@ (drop (select (result anyref) (local.get $2) + (local.get $1) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $2) (local.get $0) (i32.const 1) ) ) (drop (ref.is_null - (local.get $0) + (local.get $1) ) ) (drop @@ -604,12 +885,12 @@ ) (drop (ref.is_null - (ref.null any) + (ref.null extern) ) ) (drop (ref.is_null - (local.get $2) + (local.get $0) ) ) (drop @@ -624,12 +905,12 @@ ) (drop (ref.is_null - (ref.func $3) + (ref.func $4) ) ) (drop (ref.is_null - (local.get $1) + (local.get $2) ) ) (drop @@ -639,98 +920,132 @@ ) (drop (ref.is_null + (ref.null exn) + ) + ) + (drop + (ref.is_null + (local.get $3) + ) + ) + (drop + (ref.is_null + (global.get $global$4) + ) + ) + (drop + (ref.is_null (ref.null any) ) ) ) - (func $5 (result anyref) - (local $0 anyref) + (func $6 (result externref) + (local $0 externref) (local.get $0) ) - (func $6 (result anyref) + (func $7 (result externref) (global.get $global$0) ) - (func $7 (result anyref) - (ref.null any) + (func $8 (result externref) + (ref.null extern) ) - (func $8 (result funcref) + (func $9 (result funcref) (local $0 funcref) (local.get $0) ) - (func $9 (result funcref) + (func $10 (result funcref) (global.get $global$1) ) - (func $10 (result funcref) + (func $11 (result funcref) (ref.null func) ) - (func $11 (result funcref) - (ref.func $3) + (func $12 (result funcref) + (ref.func $4) ) - (func $12 (result anyref) - (local $0 anyref) + (func $13 (result exnref) + (local $0 exnref) (local.get $0) ) - (func $13 (result anyref) + (func $14 (result exnref) (global.get $global$3) ) - (func $14 (result anyref) - (ref.null any) + (func $15 (result exnref) + (ref.null exn) ) - (func $15 (result anyref) + (func $16 (result anyref) (local $0 anyref) (local.get $0) ) - (func $16 (result anyref) - (global.get $global$0) - ) (func $17 (result anyref) - (ref.null any) + (global.get $global$4) ) (func $18 (result anyref) - (local $0 funcref) - (local.get $0) + (ref.null any) ) (func $19 (result anyref) - (global.get $global$1) + (local $0 externref) + (local.get $0) ) (func $20 (result anyref) - (ref.null func) + (global.get $global$0) ) (func $21 (result anyref) - (ref.func $3) + (ref.null extern) ) (func $22 (result anyref) - (local $0 anyref) + (local $0 funcref) + (local.get $0) + ) + (func $23 (result anyref) + (global.get $global$1) + ) + (func $24 (result anyref) + (ref.null func) + ) + (func $25 (result anyref) + (ref.func $4) + ) + (func $26 (result anyref) + (local $0 exnref) + (local.get $0) + ) + (func $27 (result anyref) + (global.get $global$3) + ) + (func $28 (result anyref) + (ref.null exn) + ) + (func $29 (result externref) + (local $0 externref) (return (local.get $0) ) ) - (func $23 (result funcref) + (func $30 (result funcref) (local $0 funcref) (return (local.get $0) ) ) - (func $24 (result anyref) - (local $0 anyref) + (func $31 (result exnref) + (local $0 exnref) (return (local.get $0) ) ) - (func $25 (result anyref) + (func $32 (result anyref) (local $0 anyref) - (local $1 funcref) (return (local.get $0) ) ) - (func $26 - (drop - (ref.func $27) + (func $33 (result anyref) + (local $0 funcref) + (local $1 externref) + (local $2 exnref) + (return + (local.get $1) ) ) - (func $27 - (nop) - ) ) diff -Nru binaryen-108/test/reference-types.wast.from-wast binaryen-99/test/reference-types.wast.from-wast --- binaryen-108/test/reference-types.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reference-types.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,32 +1,38 @@ (module (type $none_=>_anyref (func (result anyref))) - (type $sig_anyref (func (param anyref))) - (type $sig_funcref (func (param funcref))) + (type $anyref_=>_none (func (param anyref))) + (type $funcref_=>_none (func (param funcref))) (type $none_=>_funcref (func (result funcref))) + (type $externref_=>_none (func (param externref))) + (type $exnref_=>_none (func (param exnref))) + (type $none_=>_externref (func (result externref))) + (type $none_=>_exnref (func (result exnref))) (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) - (type $anyref_=>_funcref (func (param anyref) (result funcref))) - (import "env" "import_global" (global $import_global anyref)) - (import "env" "import_func" (func $import_func (param anyref) (result funcref))) - (global $global_externref (mut anyref) (ref.null any)) + (type $externref_=>_funcref (func (param externref) (result funcref))) + (import "env" "import_global" (global $import_global externref)) + (import "env" "import_func" (func $import_func (param externref) (result funcref))) + (table $0 4 4 funcref) + (elem (i32.const 0) $take_externref $take_funcref $take_exnref $take_anyref) + (global $global_externref (mut externref) (ref.null extern)) (global $global_funcref (mut funcref) (ref.null func)) (global $global_funcref_func (mut funcref) (ref.func $foo)) + (global $global_exnref (mut exnref) (ref.null exn)) (global $global_anyref (mut anyref) (ref.null any)) - (global $global_anyref2 (mut anyref) (ref.null any)) + (global $global_anyref2 (mut anyref) (ref.null extern)) (global $global_anyref3 (mut anyref) (ref.null func)) (global $global_anyref4 (mut anyref) (ref.func $foo)) - (table $0 3 3 funcref) - (elem (i32.const 0) $take_externref $take_funcref $take_anyref) - (elem declare func $foo $ref-taken-but-not-in-table) - (tag $e-i32 (param i32)) + (global $global_anyref5 (mut anyref) (ref.null exn)) (export "export_func" (func $import_func)) (export "export_global" (global $import_global)) - (func $take_externref (param $0 anyref) + (func $take_externref (param $0 externref) (nop) ) (func $take_funcref (param $0 funcref) (nop) ) + (func $take_exnref (param $0 exnref) + (nop) + ) (func $take_anyref (param $0 anyref) (nop) ) @@ -34,8 +40,9 @@ (nop) ) (func $test - (local $local_externref anyref) + (local $local_externref externref) (local $local_funcref funcref) + (local $local_exnref exnref) (local $local_anyref anyref) (local.set $local_externref (local.get $local_externref) @@ -44,7 +51,7 @@ (global.get $global_externref) ) (local.set $local_externref - (ref.null any) + (ref.null extern) ) (local.set $local_funcref (local.get $local_funcref) @@ -58,6 +65,15 @@ (local.set $local_funcref (ref.func $foo) ) + (local.set $local_exnref + (local.get $local_exnref) + ) + (local.set $local_exnref + (global.get $global_exnref) + ) + (local.set $local_exnref + (ref.null exn) + ) (local.set $local_anyref (local.get $local_anyref) ) @@ -74,7 +90,7 @@ (global.get $global_externref) ) (local.set $local_anyref - (ref.null any) + (ref.null extern) ) (local.set $local_anyref (local.get $local_funcref) @@ -88,6 +104,15 @@ (local.set $local_anyref (ref.func $foo) ) + (local.set $local_anyref + (local.get $local_exnref) + ) + (local.set $local_anyref + (global.get $global_exnref) + ) + (local.set $local_anyref + (ref.null exn) + ) (global.set $global_externref (global.get $global_externref) ) @@ -95,7 +120,7 @@ (local.get $local_externref) ) (global.set $global_externref - (ref.null any) + (ref.null extern) ) (global.set $global_funcref (global.get $global_funcref) @@ -109,6 +134,15 @@ (global.set $global_funcref (ref.func $foo) ) + (global.set $global_exnref + (global.get $global_exnref) + ) + (global.set $global_exnref + (local.get $local_exnref) + ) + (global.set $global_exnref + (ref.null exn) + ) (global.set $global_anyref (global.get $global_anyref) ) @@ -125,7 +159,7 @@ (local.get $local_externref) ) (global.set $global_anyref - (ref.null any) + (ref.null extern) ) (global.set $global_anyref (global.get $global_funcref) @@ -139,6 +173,15 @@ (global.set $global_anyref (ref.func $foo) ) + (global.set $global_anyref + (global.get $global_exnref) + ) + (global.set $global_anyref + (local.get $local_exnref) + ) + (global.set $global_anyref + (ref.null exn) + ) (call $take_externref (local.get $local_externref) ) @@ -146,7 +189,7 @@ (global.get $global_externref) ) (call $take_externref - (ref.null any) + (ref.null extern) ) (call $take_funcref (local.get $local_funcref) @@ -160,6 +203,15 @@ (call $take_funcref (ref.func $foo) ) + (call $take_exnref + (local.get $local_exnref) + ) + (call $take_exnref + (global.get $global_exnref) + ) + (call $take_exnref + (ref.null exn) + ) (call $take_anyref (local.get $local_anyref) ) @@ -176,7 +228,7 @@ (global.get $global_externref) ) (call $take_anyref - (ref.null any) + (ref.null extern) ) (call $take_anyref (local.get $local_funcref) @@ -190,76 +242,109 @@ (call $take_anyref (ref.func $foo) ) - (call_indirect $0 (type $sig_anyref) + (call $take_anyref + (local.get $local_exnref) + ) + (call $take_anyref + (global.get $global_exnref) + ) + (call $take_anyref + (ref.null exn) + ) + (call_indirect (type $externref_=>_none) (local.get $local_externref) (i32.const 0) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $externref_=>_none) (global.get $global_externref) (i32.const 0) ) - (call_indirect $0 (type $sig_anyref) - (ref.null any) + (call_indirect (type $externref_=>_none) + (ref.null extern) (i32.const 0) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (local.get $local_funcref) (i32.const 1) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (global.get $global_funcref) (i32.const 1) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (ref.null func) (i32.const 1) ) - (call_indirect $0 (type $sig_funcref) + (call_indirect (type $funcref_=>_none) (ref.func $foo) (i32.const 1) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $exnref_=>_none) + (local.get $local_exnref) + (i32.const 2) + ) + (call_indirect (type $exnref_=>_none) + (global.get $global_exnref) + (i32.const 2) + ) + (call_indirect (type $exnref_=>_none) + (ref.null exn) + (i32.const 2) + ) + (call_indirect (type $anyref_=>_none) (local.get $local_anyref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (global.get $global_anyref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (ref.null any) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (local.get $local_externref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (global.get $global_externref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) - (ref.null any) + (call_indirect (type $anyref_=>_none) + (ref.null extern) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (local.get $local_funcref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (global.get $global_funcref) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (ref.null func) (i32.const 3) ) - (call_indirect $0 (type $sig_anyref) + (call_indirect (type $anyref_=>_none) (ref.func $foo) (i32.const 3) ) + (call_indirect (type $anyref_=>_none) + (local.get $local_exnref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (global.get $global_exnref) + (i32.const 3) + ) + (call_indirect (type $anyref_=>_none) + (ref.null exn) + (i32.const 3) + ) (drop - (block $block (result anyref) + (block $block (result externref) (br_if $block (local.get $local_externref) (i32.const 1) @@ -267,7 +352,7 @@ ) ) (drop - (block $block0 (result anyref) + (block $block0 (result externref) (br_if $block0 (global.get $global_externref) (i32.const 1) @@ -275,9 +360,9 @@ ) ) (drop - (block $block1 (result anyref) + (block $block1 (result externref) (br_if $block1 - (ref.null any) + (ref.null extern) (i32.const 1) ) ) @@ -315,25 +400,25 @@ ) ) (drop - (block $block6 (result anyref) + (block $block6 (result exnref) (br_if $block6 - (local.get $local_anyref) + (local.get $local_exnref) (i32.const 1) ) ) ) (drop - (block $block7 (result anyref) + (block $block7 (result exnref) (br_if $block7 - (global.get $global_anyref) + (global.get $global_exnref) (i32.const 1) ) ) ) (drop - (block $block8 (result anyref) + (block $block8 (result exnref) (br_if $block8 - (ref.null any) + (ref.null exn) (i32.const 1) ) ) @@ -341,7 +426,7 @@ (drop (block $block9 (result anyref) (br_if $block9 - (local.get $local_externref) + (local.get $local_anyref) (i32.const 1) ) ) @@ -349,7 +434,7 @@ (drop (block $block10 (result anyref) (br_if $block10 - (local.get $local_funcref) + (global.get $global_anyref) (i32.const 1) ) ) @@ -365,7 +450,7 @@ (drop (block $block12 (result anyref) (br_if $block12 - (ref.null func) + (local.get $local_externref) (i32.const 1) ) ) @@ -373,101 +458,171 @@ (drop (block $block13 (result anyref) (br_if $block13 + (local.get $local_funcref) + (i32.const 1) + ) + ) + ) + (drop + (block $block14 (result anyref) + (br_if $block14 + (local.get $local_exnref) + (i32.const 1) + ) + ) + ) + (drop + (block $block15 (result anyref) + (br_if $block15 + (ref.null extern) + (i32.const 1) + ) + ) + ) + (drop + (block $block16 (result anyref) + (br_if $block16 + (ref.null func) + (i32.const 1) + ) + ) + ) + (drop + (block $block17 (result anyref) + (br_if $block17 (ref.func $foo) (i32.const 1) ) ) ) (drop - (loop $loop-in (result anyref) + (block $block18 (result anyref) + (br_if $block18 + (ref.null exn) + (i32.const 1) + ) + ) + ) + (drop + (loop $loop-in (result externref) (local.get $local_externref) ) ) (drop - (loop $loop-in14 (result anyref) + (loop $loop-in19 (result externref) (global.get $global_externref) ) ) (drop - (loop $loop-in15 (result anyref) - (ref.null any) + (loop $loop-in20 (result externref) + (ref.null extern) ) ) (drop - (loop $loop-in16 (result funcref) + (loop $loop-in21 (result funcref) (local.get $local_funcref) ) ) (drop - (loop $loop-in17 (result funcref) + (loop $loop-in22 (result funcref) (global.get $global_funcref) ) ) (drop - (loop $loop-in18 (result funcref) + (loop $loop-in23 (result funcref) (ref.null func) ) ) (drop - (loop $loop-in19 (result funcref) + (loop $loop-in24 (result funcref) (ref.func $foo) ) ) (drop - (loop $loop-in20 (result anyref) + (loop $loop-in25 (result exnref) + (local.get $local_exnref) + ) + ) + (drop + (loop $loop-in26 (result exnref) + (global.get $global_exnref) + ) + ) + (drop + (loop $loop-in27 (result exnref) + (ref.null exn) + ) + ) + (drop + (loop $loop-in28 (result anyref) (local.get $local_anyref) ) ) (drop - (loop $loop-in21 (result anyref) + (loop $loop-in29 (result anyref) (global.get $global_anyref) ) ) (drop - (loop $loop-in22 (result anyref) + (loop $loop-in30 (result anyref) (ref.null any) ) ) (drop - (loop $loop-in23 (result anyref) + (loop $loop-in31 (result anyref) (local.get $local_externref) ) ) (drop - (loop $loop-in24 (result anyref) + (loop $loop-in32 (result anyref) (global.get $global_externref) ) ) (drop - (loop $loop-in25 (result anyref) - (ref.null any) + (loop $loop-in33 (result anyref) + (ref.null extern) ) ) (drop - (loop $loop-in26 (result anyref) + (loop $loop-in34 (result anyref) (local.get $local_funcref) ) ) (drop - (loop $loop-in27 (result anyref) + (loop $loop-in35 (result anyref) (global.get $global_funcref) ) ) (drop - (loop $loop-in28 (result anyref) + (loop $loop-in36 (result anyref) (ref.null func) ) ) (drop - (loop $loop-in29 (result anyref) + (loop $loop-in37 (result anyref) (ref.func $foo) ) ) (drop - (if (result anyref) + (loop $loop-in38 (result anyref) + (local.get $local_exnref) + ) + ) + (drop + (loop $loop-in39 (result anyref) + (global.get $global_exnref) + ) + ) + (drop + (loop $loop-in40 (result anyref) + (ref.null exn) + ) + ) + (drop + (if (result externref) (i32.const 1) (local.get $local_externref) - (ref.null any) + (ref.null extern) ) ) (drop @@ -478,6 +633,13 @@ ) ) (drop + (if (result exnref) + (i32.const 1) + (local.get $local_exnref) + (ref.null exn) + ) + ) + (drop (if (result anyref) (i32.const 1) (local.get $local_anyref) @@ -494,73 +656,157 @@ (drop (if (result anyref) (i32.const 1) - (ref.null any) + (local.get $local_externref) + (local.get $local_exnref) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (local.get $local_funcref) + (local.get $local_exnref) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null extern) + (ref.null func) + ) + ) + (drop + (if (result anyref) + (i32.const 1) + (ref.null extern) + (ref.null exn) + ) + ) + (drop + (if (result anyref) + (i32.const 1) (ref.null func) + (ref.null exn) ) ) (drop (if (result anyref) (i32.const 1) (ref.func $foo) - (ref.null any) + (ref.null extern) ) ) (drop - (try $try (result anyref) + (try (result externref) (do (local.get $local_externref) ) - (catch $e-i32 + (catch (drop - (pop i32) + (pop exnref) ) - (ref.null any) + (ref.null extern) ) ) ) (drop - (try $try35 (result funcref) + (try (result funcref) (do (ref.func $foo) ) - (catch $e-i32 + (catch (drop - (pop i32) + (pop exnref) ) (ref.null func) ) ) ) (drop - (try $try36 (result anyref) + (try (result exnref) + (do + (ref.null exn) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) (do (local.get $local_externref) ) - (catch $e-i32 + (catch (drop - (pop i32) + (pop exnref) ) (ref.func $foo) ) ) ) (drop - (try $try37 (result anyref) + (try (result anyref) + (do + (local.get $local_externref) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) (do (ref.func $foo) ) - (catch $e-i32 + (catch (drop - (pop i32) + (pop exnref) ) (local.get $local_externref) ) ) ) (drop - (select (result anyref) + (try (result anyref) + (do + (ref.func $foo) + ) + (catch + (pop exnref) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (pop exnref) + ) + (local.get $local_externref) + ) + ) + ) + (drop + (try (result anyref) + (do + (ref.null exn) + ) + (catch + (drop + (pop exnref) + ) + (ref.func $foo) + ) + ) + ) + (drop + (select (result externref) (local.get $local_externref) - (ref.null any) + (ref.null extern) (i32.const 1) ) ) @@ -572,6 +818,13 @@ ) ) (drop + (select (result exnref) + (local.get $local_exnref) + (ref.null exn) + (i32.const 1) + ) + ) + (drop (select (i32.const 0) (i32.const 2) @@ -587,12 +840,40 @@ ) (drop (select (result anyref) + (local.get $local_externref) + (local.get $local_exnref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $local_funcref) + (local.get $local_externref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) (local.get $local_funcref) + (local.get $local_exnref) + (i32.const 1) + ) + ) + (drop + (select (result anyref) + (local.get $local_exnref) (local.get $local_externref) (i32.const 1) ) ) (drop + (select (result anyref) + (local.get $local_exnref) + (local.get $local_funcref) + (i32.const 1) + ) + ) + (drop (ref.is_null (local.get $local_externref) ) @@ -604,7 +885,7 @@ ) (drop (ref.is_null - (ref.null any) + (ref.null extern) ) ) (drop @@ -629,6 +910,21 @@ ) (drop (ref.is_null + (local.get $local_exnref) + ) + ) + (drop + (ref.is_null + (global.get $global_exnref) + ) + ) + (drop + (ref.is_null + (ref.null exn) + ) + ) + (drop + (ref.is_null (local.get $local_anyref) ) ) @@ -643,15 +939,15 @@ ) ) ) - (func $return_externref_local (result anyref) - (local $local_externref anyref) + (func $return_externref_local (result externref) + (local $local_externref externref) (local.get $local_externref) ) - (func $return_externref_global (result anyref) + (func $return_externref_global (result externref) (global.get $global_externref) ) - (func $return_externref_null (result anyref) - (ref.null any) + (func $return_externref_null (result externref) + (ref.null extern) ) (func $return_funcref_local (result funcref) (local $local_funcref funcref) @@ -666,6 +962,16 @@ (func $return_funcref_func (result funcref) (ref.func $foo) ) + (func $return_exnref_local (result exnref) + (local $local_exnref exnref) + (local.get $local_exnref) + ) + (func $return_exnref_global (result exnref) + (global.get $global_exnref) + ) + (func $return_exnref_null (result exnref) + (ref.null exn) + ) (func $return_anyref_local (result anyref) (local $local_anyref anyref) (local.get $local_anyref) @@ -677,14 +983,14 @@ (ref.null any) ) (func $return_anyref2 (result anyref) - (local $local_externref anyref) + (local $local_externref externref) (local.get $local_externref) ) (func $return_anyref3 (result anyref) (global.get $global_externref) ) (func $return_anyref4 (result anyref) - (ref.null any) + (ref.null extern) ) (func $return_anyref5 (result anyref) (local $local_funcref funcref) @@ -699,8 +1005,18 @@ (func $return_anyref8 (result anyref) (ref.func $foo) ) - (func $returns_externref (result anyref) - (local $local_externref anyref) + (func $return_anyref9 (result anyref) + (local $local_exnref exnref) + (local.get $local_exnref) + ) + (func $return_anyref10 (result anyref) + (global.get $global_exnref) + ) + (func $return_anyref11 (result anyref) + (ref.null exn) + ) + (func $returns_externref (result externref) + (local $local_externref externref) (return (local.get $local_externref) ) @@ -708,7 +1024,7 @@ (global.get $global_externref) ) (return - (ref.null any) + (ref.null extern) ) ) (func $returns_funcref (result funcref) @@ -726,6 +1042,18 @@ (ref.null func) ) ) + (func $returns_exnref (result exnref) + (local $local_exnref exnref) + (return + (local.get $local_exnref) + ) + (return + (global.get $global_exnref) + ) + (return + (ref.null exn) + ) + ) (func $returns_anyref (result anyref) (local $local_anyref anyref) (return @@ -739,8 +1067,9 @@ ) ) (func $returns_anyref2 (result anyref) - (local $local_externref anyref) + (local $local_externref externref) (local $local_funcref funcref) + (local $local_exnref exnref) (return (local.get $local_externref) ) @@ -748,7 +1077,7 @@ (global.get $global_externref) ) (return - (ref.null any) + (ref.null extern) ) (return (local.get $local_funcref) @@ -762,13 +1091,14 @@ (return (ref.null func) ) - ) - (func $ref-user - (drop - (ref.func $ref-taken-but-not-in-table) + (return + (local.get $local_exnref) + ) + (return + (global.get $global_exnref) + ) + (return + (ref.null exn) ) - ) - (func $ref-taken-but-not-in-table - (nop) ) ) diff -Nru binaryen-108/test/reg_switch.wast.fromBinary binaryen-99/test/reg_switch.wast.fromBinary --- binaryen-108/test/reg_switch.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reg_switch.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $0 (if diff -Nru binaryen-108/test/reg_switch.wast.from-wast binaryen-99/test/reg_switch.wast.from-wast --- binaryen-108/test/reg_switch.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/reg_switch.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (memory $0 0) (func $0 (if diff -Nru binaryen-108/test/signext.wast.fromBinary binaryen-99/test/signext.wast.fromBinary --- binaryen-108/test/signext.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/signext.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (func $signext (local $0 i32) (local $1 i64) diff -Nru binaryen-108/test/signext.wast.from-wast binaryen-99/test/signext.wast.from-wast --- binaryen-108/test/signext.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/signext.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,5 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (func $signext (local $0 i32) (local $1 i64) diff -Nru binaryen-108/test/simd64.wast binaryen-99/test/simd64.wast --- binaryen-108/test/simd64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -11,53 +11,53 @@ (local.get $1) ) ) - (func $v128.load8_splat (param $0 i64) (result v128) - (v128.load8_splat + (func $v8x16.load_splat (param $0 i64) (result v128) + (v8x16.load_splat (local.get $0) ) ) - (func $v128.load16_splat (param $0 i64) (result v128) - (v128.load16_splat + (func $v16x8.load_splat (param $0 i64) (result v128) + (v16x8.load_splat (local.get $0) ) ) - (func $v128.load32_splat (param $0 i64) (result v128) - (v128.load32_splat + (func $v32x4.load_splat (param $0 i64) (result v128) + (v32x4.load_splat (local.get $0) ) ) - (func $v128.load64_splat (param $0 i64) (result v128) - (v128.load64_splat + (func $v64x2.load_splat (param $0 i64) (result v128) + (v64x2.load_splat (local.get $0) ) ) - (func $v128.load8x8_u (param $0 i64) (result v128) - (v128.load8x8_u + (func $i16x8.load8x8_u (param $0 i64) (result v128) + (i16x8.load8x8_u (local.get $0) ) ) - (func $v128.load8x8_s (param $0 i64) (result v128) - (v128.load8x8_s + (func $i16x8.load8x8_s (param $0 i64) (result v128) + (i16x8.load8x8_s (local.get $0) ) ) - (func $v128.load16x4_s (param $0 i64) (result v128) - (v128.load16x4_s + (func $i32x4.load16x4_s (param $0 i64) (result v128) + (i32x4.load16x4_s (local.get $0) ) ) - (func $v128.load16x4_u (param $0 i64) (result v128) - (v128.load16x4_u + (func $i32x4.load16x4_u (param $0 i64) (result v128) + (i32x4.load16x4_u (local.get $0) ) ) - (func $v128.load32x2_s (param $0 i64) (result v128) - (v128.load32x2_s + (func $i64x2.load32x2_s (param $0 i64) (result v128) + (i64x2.load32x2_s (local.get $0) ) ) - (func $v128.load32x2_u (param $0 i64) (result v128) - (v128.load32x2_u + (func $i64x2.load32x2_u (param $0 i64) (result v128) + (i64x2.load32x2_u (local.get $0) ) ) diff -Nru binaryen-108/test/simd64.wast.fromBinary binaryen-99/test/simd64.wast.fromBinary --- binaryen-108/test/simd64.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd64.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -13,53 +13,53 @@ (local.get $1) ) ) - (func $v128.load8_splat (param $0 i64) (result v128) - (v128.load8_splat + (func $v8x16.load_splat (param $0 i64) (result v128) + (v8x16.load_splat (local.get $0) ) ) - (func $v128.load16_splat (param $0 i64) (result v128) - (v128.load16_splat + (func $v16x8.load_splat (param $0 i64) (result v128) + (v16x8.load_splat (local.get $0) ) ) - (func $v128.load32_splat (param $0 i64) (result v128) - (v128.load32_splat + (func $v32x4.load_splat (param $0 i64) (result v128) + (v32x4.load_splat (local.get $0) ) ) - (func $v128.load64_splat (param $0 i64) (result v128) - (v128.load64_splat + (func $v64x2.load_splat (param $0 i64) (result v128) + (v64x2.load_splat (local.get $0) ) ) - (func $v128.load8x8_u (param $0 i64) (result v128) - (v128.load8x8_u + (func $i16x8.load8x8_u (param $0 i64) (result v128) + (i16x8.load8x8_u (local.get $0) ) ) - (func $v128.load8x8_s (param $0 i64) (result v128) - (v128.load8x8_s + (func $i16x8.load8x8_s (param $0 i64) (result v128) + (i16x8.load8x8_s (local.get $0) ) ) - (func $v128.load16x4_s (param $0 i64) (result v128) - (v128.load16x4_s + (func $i32x4.load16x4_s (param $0 i64) (result v128) + (i32x4.load16x4_s (local.get $0) ) ) - (func $v128.load16x4_u (param $0 i64) (result v128) - (v128.load16x4_u + (func $i32x4.load16x4_u (param $0 i64) (result v128) + (i32x4.load16x4_u (local.get $0) ) ) - (func $v128.load32x2_s (param $0 i64) (result v128) - (v128.load32x2_s + (func $i64x2.load32x2_s (param $0 i64) (result v128) + (i64x2.load32x2_s (local.get $0) ) ) - (func $v128.load32x2_u (param $0 i64) (result v128) - (v128.load32x2_u + (func $i64x2.load32x2_u (param $0 i64) (result v128) + (i64x2.load32x2_u (local.get $0) ) ) diff -Nru binaryen-108/test/simd64.wast.fromBinary.noDebugInfo binaryen-99/test/simd64.wast.fromBinary.noDebugInfo --- binaryen-108/test/simd64.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd64.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -14,52 +14,52 @@ ) ) (func $2 (param $0 i64) (result v128) - (v128.load8_splat + (v8x16.load_splat (local.get $0) ) ) (func $3 (param $0 i64) (result v128) - (v128.load16_splat + (v16x8.load_splat (local.get $0) ) ) (func $4 (param $0 i64) (result v128) - (v128.load32_splat + (v32x4.load_splat (local.get $0) ) ) (func $5 (param $0 i64) (result v128) - (v128.load64_splat + (v64x2.load_splat (local.get $0) ) ) (func $6 (param $0 i64) (result v128) - (v128.load8x8_u + (i16x8.load8x8_u (local.get $0) ) ) (func $7 (param $0 i64) (result v128) - (v128.load8x8_s + (i16x8.load8x8_s (local.get $0) ) ) (func $8 (param $0 i64) (result v128) - (v128.load16x4_s + (i32x4.load16x4_s (local.get $0) ) ) (func $9 (param $0 i64) (result v128) - (v128.load16x4_u + (i32x4.load16x4_u (local.get $0) ) ) (func $10 (param $0 i64) (result v128) - (v128.load32x2_s + (i64x2.load32x2_s (local.get $0) ) ) (func $11 (param $0 i64) (result v128) - (v128.load32x2_u + (i64x2.load32x2_u (local.get $0) ) ) diff -Nru binaryen-108/test/simd64.wast.from-wast binaryen-99/test/simd64.wast.from-wast --- binaryen-108/test/simd64.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd64.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -13,53 +13,53 @@ (local.get $1) ) ) - (func $v128.load8_splat (param $0 i64) (result v128) - (v128.load8_splat + (func $v8x16.load_splat (param $0 i64) (result v128) + (v8x16.load_splat (local.get $0) ) ) - (func $v128.load16_splat (param $0 i64) (result v128) - (v128.load16_splat + (func $v16x8.load_splat (param $0 i64) (result v128) + (v16x8.load_splat (local.get $0) ) ) - (func $v128.load32_splat (param $0 i64) (result v128) - (v128.load32_splat + (func $v32x4.load_splat (param $0 i64) (result v128) + (v32x4.load_splat (local.get $0) ) ) - (func $v128.load64_splat (param $0 i64) (result v128) - (v128.load64_splat + (func $v64x2.load_splat (param $0 i64) (result v128) + (v64x2.load_splat (local.get $0) ) ) - (func $v128.load8x8_u (param $0 i64) (result v128) - (v128.load8x8_u + (func $i16x8.load8x8_u (param $0 i64) (result v128) + (i16x8.load8x8_u (local.get $0) ) ) - (func $v128.load8x8_s (param $0 i64) (result v128) - (v128.load8x8_s + (func $i16x8.load8x8_s (param $0 i64) (result v128) + (i16x8.load8x8_s (local.get $0) ) ) - (func $v128.load16x4_s (param $0 i64) (result v128) - (v128.load16x4_s + (func $i32x4.load16x4_s (param $0 i64) (result v128) + (i32x4.load16x4_s (local.get $0) ) ) - (func $v128.load16x4_u (param $0 i64) (result v128) - (v128.load16x4_u + (func $i32x4.load16x4_u (param $0 i64) (result v128) + (i32x4.load16x4_u (local.get $0) ) ) - (func $v128.load32x2_s (param $0 i64) (result v128) - (v128.load32x2_s + (func $i64x2.load32x2_s (param $0 i64) (result v128) + (i64x2.load32x2_s (local.get $0) ) ) - (func $v128.load32x2_u (param $0 i64) (result v128) - (v128.load32x2_u + (func $i64x2.load32x2_u (param $0 i64) (result v128) + (i64x2.load32x2_u (local.get $0) ) ) diff -Nru binaryen-108/test/simd.wast binaryen-99/test/simd.wast --- binaryen-108/test/simd.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd.wast 2021-01-07 20:01:06.000000000 +0000 @@ -5,56 +5,6 @@ (local.get $0) ) ) - (func $v128.load8x8_s (param $0 i32) (result v128) - (v128.load8x8_s - (local.get $0) - ) - ) - (func $v128.load8x8_u (param $0 i32) (result v128) - (v128.load8x8_u - (local.get $0) - ) - ) - (func $v128.load16x4_s (param $0 i32) (result v128) - (v128.load16x4_s - (local.get $0) - ) - ) - (func $v128.load16x4_u (param $0 i32) (result v128) - (v128.load16x4_u - (local.get $0) - ) - ) - (func $v128.load32x2_s (param $0 i32) (result v128) - (v128.load32x2_s - (local.get $0) - ) - ) - (func $v128.load32x2_u (param $0 i32) (result v128) - (v128.load32x2_u - (local.get $0) - ) - ) - (func $v128.load8_splat (param $0 i32) (result v128) - (v128.load8_splat - (local.get $0) - ) - ) - (func $v128.load16_splat (param $0 i32) (result v128) - (v128.load16_splat - (local.get $0) - ) - ) - (func $v128.load32_splat (param $0 i32) (result v128) - (v128.load32_splat - (local.get $0) - ) - ) - (func $v128.load64_splat (param $0 i32) (result v128) - (v128.load64_splat - (local.get $0) - ) - ) (func $v128.store (param $0 i32) (param $1 v128) (v128.store offset=0 align=16 (local.get $0) @@ -79,14 +29,8 @@ (func $v128.const.f64x2 (result v128) (v128.const f64x2 1.0 2) ) - (func $i8x16.shuffle (param $0 v128) (param $1 v128) (result v128) - (i8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 - (local.get $0) - (local.get $1) - ) - ) - (func $i8x16.swizzle (param $0 v128) (param $1 v128) (result v128) - (i8x16.swizzle + (func $v128.shuffle (param $0 v128) (param $1 v128) (result v128) + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 (local.get $0) (local.get $1) ) @@ -96,21 +40,6 @@ (local.get $0) ) ) - (func $i16x8.splat (param $0 i32) (result v128) - (i16x8.splat - (local.get $0) - ) - ) - (func $f32x4.splat (param $0 f32) (result v128) - (f32x4.splat - (local.get $0) - ) - ) - (func $f64x2.splat (param $0 f64) (result v128) - (f64x2.splat - (local.get $0) - ) - ) (func $i8x16.extract_lane_s (param $0 v128) (result i32) (i8x16.extract_lane_s 0 (local.get $0) @@ -127,6 +56,11 @@ (local.get $1) ) ) + (func $i16x8.splat (param $0 i32) (result v128) + (i16x8.splat + (local.get $0) + ) + ) (func $i16x8.extract_lane_s (param $0 v128) (result i32) (i16x8.extract_lane_s 0 (local.get $0) @@ -143,6 +77,11 @@ (local.get $1) ) ) + (func $i32x4.splat (param $0 i32) (result v128) + (i32x4.splat + (local.get $0) + ) + ) (func $i32x4.extract_lane (param $0 v128) (result i32) (i32x4.extract_lane 0 (local.get $0) @@ -165,6 +104,11 @@ (local.get $1) ) ) + (func $f32x4.splat (param $0 f32) (result v128) + (f32x4.splat + (local.get $0) + ) + ) (func $f32x4.extract_lane (param $0 v128) (result f32) (f32x4.extract_lane 0 (local.get $0) @@ -176,6 +120,11 @@ (local.get $1) ) ) + (func $f64x2.splat (param $0 f64) (result v128) + (f64x2.splat + (local.get $0) + ) + ) (func $f64x2.extract_lane (param $0 v128) (result f64) (f64x2.extract_lane 0 (local.get $0) @@ -367,6 +316,12 @@ (local.get $1) ) ) + (func $i64x2.eq (param $0 v128) (param $1 v128) (result v128) + (i64x2.eq + (local.get $0) + (local.get $1) + ) + ) (func $f32x4.eq (param $0 v128) (param $1 v128) (result v128) (f32x4.eq (local.get $0) @@ -450,12 +405,6 @@ (local.get $1) ) ) - (func $v128.andnot (param $0 v128) (param $1 v128) (result v128) - (v128.andnot - (local.get $0) - (local.get $1) - ) - ) (func $v128.or (param $0 v128) (param $1 v128) (result v128) (v128.or (local.get $0) @@ -468,6 +417,12 @@ (local.get $1) ) ) + (func $v128.andnot (param $0 v128) (param $1 v128) (result v128) + (v128.andnot + (local.get $0) + (local.get $1) + ) + ) (func $v128.bitselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (v128.bitselect (local.get $0) @@ -475,9 +430,32 @@ (local.get $2) ) ) - (func $v128.any_true (param $0 v128) (result i32) - (v128.any_true + (func $v8x16.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v8x16.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v16x8.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v16x8.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v32x4.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v32x4.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v64x2.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v64x2.signselect (local.get $0) + (local.get $1) + (local.get $2) ) ) (func $v128.load8_lane (param $0 i32) (param $1 v128) (result v128) @@ -564,23 +542,8 @@ (local.get $1) ) ) - (func $v128.load32_zero (param $0 i32) (result v128) - (v128.load32_zero - (local.get $0) - ) - ) - (func $v128.load64_zero (param $0 i32) (result v128) - (v128.load64_zero - (local.get $0) - ) - ) - (func $f32x4.demote_f64x2_zero (param $0 v128) (result v128) - (f32x4.demote_f64x2_zero - (local.get $0) - ) - ) - (func $f64x2.promote_low_f32x4 (param $0 v128) (result v128) - (f64x2.promote_low_f32x4 + (func $i8x16.popcnt (param $0 v128) (result v128) + (i8x16.popcnt (local.get $0) ) ) @@ -594,8 +557,8 @@ (local.get $0) ) ) - (func $i8x16.popcnt (param $0 v128) (result v128) - (i8x16.popcnt + (func $i8x16.any_true (param $0 v128) (result i32) + (i8x16.any_true (local.get $0) ) ) @@ -609,38 +572,6 @@ (local.get $0) ) ) - (func $i8x16.narrow_i16x8_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_s - (local.get $0) - (local.get $1) - ) - ) - (func $i8x16.narrow_i16x8_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_u - (local.get $0) - (local.get $1) - ) - ) - (func $f32x4.ceil (param $0 v128) (result v128) - (f32x4.ceil - (local.get $0) - ) - ) - (func $f32x4.floor (param $0 v128) (result v128) - (f32x4.floor - (local.get $0) - ) - ) - (func $f32x4.trunc (param $0 v128) (result v128) - (f32x4.trunc - (local.get $0) - ) - ) - (func $f32x4.nearest (param $0 v128) (result v128) - (f32x4.nearest - (local.get $0) - ) - ) (func $i8x16.shl (param $0 v128) (param $1 i32) (result v128) (i8x16.shl (local.get $0) @@ -665,14 +596,14 @@ (local.get $1) ) ) - (func $i8x16.add_sat_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_s + (func $i8x16.add_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $i8x16.add_sat_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_u + (func $i8x16.add_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_u (local.get $0) (local.get $1) ) @@ -683,26 +614,22 @@ (local.get $1) ) ) - (func $i8x16.sub_sat_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_s + (func $i8x16.sub_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $i8x16.sub_sat_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_u + (func $i8x16.sub_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $f64x2.ceil (param $0 v128) (result v128) - (f64x2.ceil - (local.get $0) - ) - ) - (func $f64x2.floor (param $0 v128) (result v128) - (f64x2.floor + (func $i8x16.mul (param $0 v128) (param $1 v128) (result v128) + (i8x16.mul (local.get $0) + (local.get $1) ) ) (func $i8x16.min_s (param $0 v128) (param $1 v128) (result v128) @@ -729,37 +656,12 @@ (local.get $1) ) ) - (func $f64x2.trunc (param $0 v128) (result v128) - (f64x2.trunc - (local.get $0) - ) - ) (func $i8x16.avgr_u (param $0 v128) (param $1 v128) (result v128) (i8x16.avgr_u (local.get $0) (local.get $1) ) ) - (func $i16x8.extadd_pairwise_i8x16_s (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extadd_pairwise_i8x16_u (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_u - (local.get $0) - ) - ) - (func $i32x4.extadd_pairwise_i16x8_s (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extadd_pairwise_i16x8_u (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_u - (local.get $0) - ) - ) (func $i16x8.abs (param $0 v128) (result v128) (i16x8.abs (local.get $0) @@ -770,10 +672,9 @@ (local.get $0) ) ) - (func $i16x8.q15mulr_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.q15mulr_sat_s + (func $i16x8.any_true (param $0 v128) (result i32) + (i16x8.any_true (local.get $0) - (local.get $1) ) ) (func $i16x8.all_true (param $0 v128) (result i32) @@ -786,39 +687,7 @@ (local.get $0) ) ) - (func $i16x8.narrow_i32x4_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_s - (local.get $0) - (local.get $1) - ) - ) - (func $i16x8.narrow_i32x4_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_u - (local.get $0) - (local.get $1) - ) - ) - (func $i16x8.extend_low_i8x16_s (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extend_high_i8x16_s (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extend_low_i8x16_u (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_u - (local.get $0) - ) - ) - (func $i16x8.extend_high_i8x16_u (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_u - (local.get $0) - ) - ) -(func $i16x8.shl (param $0 v128) (param $1 i32) (result v128) + (func $i16x8.shl (param $0 v128) (param $1 i32) (result v128) (i16x8.shl (local.get $0) (local.get $1) @@ -842,14 +711,14 @@ (local.get $1) ) ) - (func $i16x8.add_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_s + (func $i16x8.add_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $i16x8.add_sat_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_u + (func $i16x8.add_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_u (local.get $0) (local.get $1) ) @@ -860,23 +729,18 @@ (local.get $1) ) ) - (func $i16x8.sub_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_s + (func $i16x8.sub_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $i16x8.sub_sat_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_u + (func $i16x8.sub_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $f64x2.nearest (param $0 v128) (result v128) - (f64x2.nearest - (local.get $0) - ) - ) (func $i16x8.mul (param $0 v128) (param $1 v128) (result v128) (i16x8.mul (local.get $0) @@ -913,6 +777,12 @@ (local.get $1) ) ) + (func $i16x8.q15mulr_sat_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.q15mulr_sat_s + (local.get $0) + (local.get $1) + ) + ) (func $i16x8.extmul_low_i8x16_s (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_low_i8x16_s (local.get $0) @@ -947,6 +817,11 @@ (local.get $0) ) ) + (func $i32x4.any_true (param $0 v128) (result i32) + (i32x4.any_true + (local.get $0) + ) + ) (func $i32x4.all_true (param $0 v128) (result i32) (i32x4.all_true (local.get $0) @@ -957,26 +832,6 @@ (local.get $0) ) ) - (func $i32x4.extend_low_i16x8_s (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extend_high_i16x8_s (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extend_low_i16x8_u (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_u - (local.get $0) - ) - ) - (func $i32x4.extend_high_i16x8_u (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_u - (local.get $0) - ) - ) (func $i32x4.shl (param $0 v128) (param $1 i32) (result v128) (i32x4.shl (local.get $0) @@ -1067,46 +922,16 @@ (local.get $1) ) ) - (func $i64x2.abs (param $0 v128) (result v128) - (i64x2.abs - (local.get $0) - ) - ) (func $i64x2.neg (param $0 v128) (result v128) (i64x2.neg (local.get $0) ) ) - (func $i64x2.all_true (param $0 v128) (result i32) - (i64x2.all_true - (local.get $0) - ) - ) (func $i64x2.bitmask (param $0 v128) (result i32) (i64x2.bitmask (local.get $0) ) ) - (func $i64x2.extend_low_i32x4_s (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_s - (local.get $0) - ) - ) - (func $i64x2.extend_high_i32x4_s (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_s - (local.get $0) - ) - ) - (func $i64x2.extend_low_i32x4_u (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_u - (local.get $0) - ) - ) - (func $i64x2.extend_high_i32x4_u (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_u - (local.get $0) - ) - ) (func $i64x2.shl (param $0 v128) (param $1 i32) (result v128) (i64x2.shl (local.get $0) @@ -1143,42 +968,6 @@ (local.get $1) ) ) - (func $i64x2.eq (param $0 v128) (param $1 v128) (result v128) - (i64x2.eq - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.ne (param $0 v128) (param $1 v128) (result v128) - (i64x2.ne - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.lt_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.lt_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.gt_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.gt_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.le_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.le_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.ge_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.ge_s - (local.get $0) - (local.get $1) - ) - ) (func $i64x2.extmul_low_i32x4_s (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_low_i32x4_s (local.get $0) @@ -1203,21 +992,6 @@ (local.get $1) ) ) - (func $f32x4.abs (param $0 v128) (result v128) - (f32x4.abs - (local.get $0) - ) - ) - (func $f32x4.neg (param $0 v128) (result v128) - (f32x4.neg - (local.get $0) - ) - ) - (func $f32x4.sqrt (param $0 v128) (result v128) - (f32x4.sqrt - (local.get $0) - ) - ) (func $f32x4.add (param $0 v128) (param $1 v128) (result v128) (f32x4.add (local.get $0) @@ -1266,21 +1040,55 @@ (local.get $1) ) ) - (func $f64x2.abs (param $0 v128) (result v128) - (f64x2.abs + (func $f32x4.ceil (param $0 v128) (result v128) + (f32x4.ceil (local.get $0) ) ) - (func $f64x2.neg (param $0 v128) (result v128) - (f64x2.neg + (func $f32x4.floor (param $0 v128) (result v128) + (f32x4.floor (local.get $0) ) ) - (func $f64x2.sqrt (param $0 v128) (result v128) - (f64x2.sqrt + (func $f32x4.trunc (param $0 v128) (result v128) + (f32x4.trunc + (local.get $0) + ) + ) + (func $f32x4.nearest (param $0 v128) (result v128) + (f32x4.nearest (local.get $0) ) ) + (func $f32x4.abs (param $0 v128) (result v128) + (f32x4.abs + (local.get $0) + ) + ) + (func $f32x4.neg (param $0 v128) (result v128) + (f32x4.neg + (local.get $0) + ) + ) + (func $f32x4.sqrt (param $0 v128) (result v128) + (f32x4.sqrt + (local.get $0) + ) + ) + (func $f32x4.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfma + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $f32x4.qfms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfms + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) (func $f64x2.add (param $0 v128) (param $1 v128) (result v128) (f64x2.add (local.get $0) @@ -1329,6 +1137,75 @@ (local.get $1) ) ) + (func $f64x2.ceil (param $0 v128) (result v128) + (f64x2.ceil + (local.get $0) + ) + ) + (func $f64x2.floor (param $0 v128) (result v128) + (f64x2.floor + (local.get $0) + ) + ) + (func $f64x2.trunc (param $0 v128) (result v128) + (f64x2.trunc + (local.get $0) + ) + ) + (func $f64x2.nearest (param $0 v128) (result v128) + (f64x2.nearest + (local.get $0) + ) + ) + (func $f64x2.abs (param $0 v128) (result v128) + (f64x2.abs + (local.get $0) + ) + ) + (func $f64x2.neg (param $0 v128) (result v128) + (f64x2.neg + (local.get $0) + ) + ) + (func $f64x2.sqrt (param $0 v128) (result v128) + (f64x2.sqrt + (local.get $0) + ) + ) + (func $f64x2.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfma + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $f64x2.qfms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfms + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $i16x8.extadd_pairwise_i8x16_s (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.extadd_pairwise_i8x16_u (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_u + (local.get $0) + ) + ) + (func $i32x4.extadd_pairwise_i16x8_s (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.extadd_pairwise_i16x8_u (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_u + (local.get $0) + ) + ) (func $i32x4.trunc_sat_f32x4_s (param $0 v128) (result v128) (i32x4.trunc_sat_f32x4_s (local.get $0) @@ -1339,6 +1216,16 @@ (local.get $0) ) ) + (func $i64x2.trunc_sat_f64x2_s (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_s + (local.get $0) + ) + ) + (func $i64x2.trunc_sat_f64x2_u (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_u + (local.get $0) + ) + ) (func $f32x4.convert_i32x4_s (param $0 v128) (result v128) (f32x4.convert_i32x4_s (local.get $0) @@ -1349,23 +1236,173 @@ (local.get $0) ) ) - (func $i32x4.trunc_sat_f64x2_s_zero (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_s_zero + (func $f64x2.convert_i64x2_s (param $0 v128) (result v128) + (f64x2.convert_i64x2_s + (local.get $0) + ) + ) + (func $f64x2.convert_i64x2_u (param $0 v128) (result v128) + (f64x2.convert_i64x2_u + (local.get $0) + ) + ) + (func $v8x16.load_splat (param $0 i32) (result v128) + (v8x16.load_splat + (local.get $0) + ) + ) + (func $v16x8.load_splat (param $0 i32) (result v128) + (v16x8.load_splat + (local.get $0) + ) + ) + (func $v32x4.load_splat (param $0 i32) (result v128) + (v32x4.load_splat + (local.get $0) + ) + ) + (func $v64x2.load_splat (param $0 i32) (result v128) + (v64x2.load_splat + (local.get $0) + ) + ) + (func $i8x16.narrow_i16x8_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.narrow_i16x8_s + (local.get $0) + (local.get $1) + ) + ) + (func $i8x16.narrow_i16x8_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.narrow_i16x8_u + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.narrow_i32x4_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_s + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.narrow_i32x4_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_u + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.widen_low_i8x16_s (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.widen_high_i8x16_s (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.widen_low_i8x16_u (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_u + (local.get $0) + ) + ) + (func $i16x8.widen_high_i8x16_u (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_u + (local.get $0) + ) + ) + (func $i32x4.widen_low_i16x8_s (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.widen_high_i16x8_s (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.widen_low_i16x8_u (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_u + (local.get $0) + ) + ) + (func $i32x4.widen_high_i16x8_u (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_u + (local.get $0) + ) + ) + (func $i64x2.widen_low_i32x4_s (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_s + (local.get $0) + ) + ) + (func $i64x2.widen_high_i32x4_s (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_s + (local.get $0) + ) + ) + (func $i64x2.widen_low_i32x4_u (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_u (local.get $0) ) ) - (func $i32x4.trunc_sat_f64x2_u_zero (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_u_zero + (func $i64x2.widen_high_i32x4_u (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_u (local.get $0) ) ) - (func $f64x2.convert_low_i32x4_s (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_s + (func $i16x8.load8x8_u (param $0 i32) (result v128) + (i16x8.load8x8_u + (local.get $0) + ) + ) + (func $i16x8.load8x8_s (param $0 i32) (result v128) + (i16x8.load8x8_s + (local.get $0) + ) + ) + (func $i32x4.load16x4_s (param $0 i32) (result v128) + (i32x4.load16x4_s + (local.get $0) + ) + ) + (func $i32x4.load16x4_u (param $0 i32) (result v128) + (i32x4.load16x4_u + (local.get $0) + ) + ) + (func $i64x2.load32x2_s (param $0 i32) (result v128) + (i64x2.load32x2_s + (local.get $0) + ) + ) + (func $i64x2.load32x2_u (param $0 i32) (result v128) + (i64x2.load32x2_u + (local.get $0) + ) + ) + (func $v128.load32_zero (param $0 i32) (result v128) + (v128.load32_zero + (local.get $0) + ) + ) + (func $v128.load64_zero (param $0 i32) (result v128) + (v128.load64_zero + (local.get $0) + ) + ) + (func $v8x16.swizzle (param $0 v128) (param $1 v128) (result v128) + (v8x16.swizzle + (local.get $0) + (local.get $1) + ) + ) + (func $prefetch.t (param $0 i32) + (prefetch.t offset=3 align=2 (local.get $0) ) ) - (func $f64x2.convert_low_i32x4_u (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_u + (func $prefetch.nt (param $0 i32) + (prefetch.nt offset=3 align=2 (local.get $0) ) ) diff -Nru binaryen-108/test/simd.wast.fromBinary binaryen-99/test/simd.wast.fromBinary --- binaryen-108/test/simd.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -2,76 +2,27 @@ (type $v128_v128_=>_v128 (func (param v128 v128) (result v128))) (type $v128_=>_v128 (func (param v128) (result v128))) (type $i32_=>_v128 (func (param i32) (result v128))) - (type $v128_i32_=>_v128 (func (param v128 i32) (result v128))) (type $v128_=>_i32 (func (param v128) (result i32))) + (type $v128_i32_=>_v128 (func (param v128 i32) (result v128))) + (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) (type $i32_v128_=>_none (func (param i32 v128))) (type $i32_v128_=>_v128 (func (param i32 v128) (result v128))) (type $none_=>_v128 (func (result v128))) + (type $i32_=>_none (func (param i32))) + (type $v128_=>_i64 (func (param v128) (result i64))) + (type $v128_=>_f32 (func (param v128) (result f32))) + (type $v128_=>_f64 (func (param v128) (result f64))) (type $f32_=>_v128 (func (param f32) (result v128))) (type $f64_=>_v128 (func (param f64) (result v128))) - (type $v128_=>_i64 (func (param v128) (result i64))) (type $v128_i64_=>_v128 (func (param v128 i64) (result v128))) - (type $v128_=>_f32 (func (param v128) (result f32))) (type $v128_f32_=>_v128 (func (param v128 f32) (result v128))) - (type $v128_=>_f64 (func (param v128) (result f64))) (type $v128_f64_=>_v128 (func (param v128 f64) (result v128))) - (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) (memory $0 1 1) (func $v128.load (param $0 i32) (result v128) (v128.load (local.get $0) ) ) - (func $v128.load8x8_s (param $0 i32) (result v128) - (v128.load8x8_s - (local.get $0) - ) - ) - (func $v128.load8x8_u (param $0 i32) (result v128) - (v128.load8x8_u - (local.get $0) - ) - ) - (func $v128.load16x4_s (param $0 i32) (result v128) - (v128.load16x4_s - (local.get $0) - ) - ) - (func $v128.load16x4_u (param $0 i32) (result v128) - (v128.load16x4_u - (local.get $0) - ) - ) - (func $v128.load32x2_s (param $0 i32) (result v128) - (v128.load32x2_s - (local.get $0) - ) - ) - (func $v128.load32x2_u (param $0 i32) (result v128) - (v128.load32x2_u - (local.get $0) - ) - ) - (func $v128.load8_splat (param $0 i32) (result v128) - (v128.load8_splat - (local.get $0) - ) - ) - (func $v128.load16_splat (param $0 i32) (result v128) - (v128.load16_splat - (local.get $0) - ) - ) - (func $v128.load32_splat (param $0 i32) (result v128) - (v128.load32_splat - (local.get $0) - ) - ) - (func $v128.load64_splat (param $0 i32) (result v128) - (v128.load64_splat - (local.get $0) - ) - ) (func $v128.store (param $0 i32) (param $1 v128) (v128.store (local.get $0) @@ -96,14 +47,8 @@ (func $v128.const.f64x2 (result v128) (v128.const i32x4 0x00000000 0x3ff00000 0x00000000 0x40000000) ) - (func $i8x16.shuffle (param $0 v128) (param $1 v128) (result v128) - (i8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 - (local.get $0) - (local.get $1) - ) - ) - (func $i8x16.swizzle (param $0 v128) (param $1 v128) (result v128) - (i8x16.swizzle + (func $v128.shuffle (param $0 v128) (param $1 v128) (result v128) + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 (local.get $0) (local.get $1) ) @@ -113,21 +58,6 @@ (local.get $0) ) ) - (func $i16x8.splat (param $0 i32) (result v128) - (i16x8.splat - (local.get $0) - ) - ) - (func $f32x4.splat (param $0 f32) (result v128) - (f32x4.splat - (local.get $0) - ) - ) - (func $f64x2.splat (param $0 f64) (result v128) - (f64x2.splat - (local.get $0) - ) - ) (func $i8x16.extract_lane_s (param $0 v128) (result i32) (i8x16.extract_lane_s 0 (local.get $0) @@ -144,6 +74,11 @@ (local.get $1) ) ) + (func $i16x8.splat (param $0 i32) (result v128) + (i16x8.splat + (local.get $0) + ) + ) (func $i16x8.extract_lane_s (param $0 v128) (result i32) (i16x8.extract_lane_s 0 (local.get $0) @@ -160,6 +95,11 @@ (local.get $1) ) ) + (func $i32x4.splat (param $0 i32) (result v128) + (i32x4.splat + (local.get $0) + ) + ) (func $i32x4.extract_lane (param $0 v128) (result i32) (i32x4.extract_lane 0 (local.get $0) @@ -182,6 +122,11 @@ (local.get $1) ) ) + (func $f32x4.splat (param $0 f32) (result v128) + (f32x4.splat + (local.get $0) + ) + ) (func $f32x4.extract_lane (param $0 v128) (result f32) (f32x4.extract_lane 0 (local.get $0) @@ -193,6 +138,11 @@ (local.get $1) ) ) + (func $f64x2.splat (param $0 f64) (result v128) + (f64x2.splat + (local.get $0) + ) + ) (func $f64x2.extract_lane (param $0 v128) (result f64) (f64x2.extract_lane 0 (local.get $0) @@ -384,6 +334,12 @@ (local.get $1) ) ) + (func $i64x2.eq (param $0 v128) (param $1 v128) (result v128) + (i64x2.eq + (local.get $0) + (local.get $1) + ) + ) (func $f32x4.eq (param $0 v128) (param $1 v128) (result v128) (f32x4.eq (local.get $0) @@ -467,12 +423,6 @@ (local.get $1) ) ) - (func $v128.andnot (param $0 v128) (param $1 v128) (result v128) - (v128.andnot - (local.get $0) - (local.get $1) - ) - ) (func $v128.or (param $0 v128) (param $1 v128) (result v128) (v128.or (local.get $0) @@ -485,6 +435,12 @@ (local.get $1) ) ) + (func $v128.andnot (param $0 v128) (param $1 v128) (result v128) + (v128.andnot + (local.get $0) + (local.get $1) + ) + ) (func $v128.bitselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (v128.bitselect (local.get $0) @@ -492,9 +448,32 @@ (local.get $2) ) ) - (func $v128.any_true (param $0 v128) (result i32) - (v128.any_true + (func $v8x16.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v8x16.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v16x8.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v16x8.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v32x4.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v32x4.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v64x2.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v64x2.signselect (local.get $0) + (local.get $1) + (local.get $2) ) ) (func $v128.load8_lane (param $0 i32) (param $1 v128) (result v128) @@ -581,23 +560,8 @@ (local.get $1) ) ) - (func $v128.load32_zero (param $0 i32) (result v128) - (v128.load32_zero - (local.get $0) - ) - ) - (func $v128.load64_zero (param $0 i32) (result v128) - (v128.load64_zero - (local.get $0) - ) - ) - (func $f32x4.demote_f64x2_zero (param $0 v128) (result v128) - (f32x4.demote_f64x2_zero - (local.get $0) - ) - ) - (func $f64x2.promote_low_f32x4 (param $0 v128) (result v128) - (f64x2.promote_low_f32x4 + (func $i8x16.popcnt (param $0 v128) (result v128) + (i8x16.popcnt (local.get $0) ) ) @@ -611,8 +575,8 @@ (local.get $0) ) ) - (func $i8x16.popcnt (param $0 v128) (result v128) - (i8x16.popcnt + (func $i8x16.any_true (param $0 v128) (result i32) + (i8x16.any_true (local.get $0) ) ) @@ -626,38 +590,6 @@ (local.get $0) ) ) - (func $i8x16.narrow_i16x8_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_s - (local.get $0) - (local.get $1) - ) - ) - (func $i8x16.narrow_i16x8_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_u - (local.get $0) - (local.get $1) - ) - ) - (func $f32x4.ceil (param $0 v128) (result v128) - (f32x4.ceil - (local.get $0) - ) - ) - (func $f32x4.floor (param $0 v128) (result v128) - (f32x4.floor - (local.get $0) - ) - ) - (func $f32x4.trunc (param $0 v128) (result v128) - (f32x4.trunc - (local.get $0) - ) - ) - (func $f32x4.nearest (param $0 v128) (result v128) - (f32x4.nearest - (local.get $0) - ) - ) (func $i8x16.shl (param $0 v128) (param $1 i32) (result v128) (i8x16.shl (local.get $0) @@ -682,14 +614,14 @@ (local.get $1) ) ) - (func $i8x16.add_sat_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_s + (func $i8x16.add_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $i8x16.add_sat_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_u + (func $i8x16.add_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_u (local.get $0) (local.get $1) ) @@ -700,26 +632,22 @@ (local.get $1) ) ) - (func $i8x16.sub_sat_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_s + (func $i8x16.sub_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $i8x16.sub_sat_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_u + (func $i8x16.sub_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $f64x2.ceil (param $0 v128) (result v128) - (f64x2.ceil - (local.get $0) - ) - ) - (func $f64x2.floor (param $0 v128) (result v128) - (f64x2.floor + (func $i8x16.mul (param $0 v128) (param $1 v128) (result v128) + (i8x16.mul (local.get $0) + (local.get $1) ) ) (func $i8x16.min_s (param $0 v128) (param $1 v128) (result v128) @@ -746,37 +674,12 @@ (local.get $1) ) ) - (func $f64x2.trunc (param $0 v128) (result v128) - (f64x2.trunc - (local.get $0) - ) - ) (func $i8x16.avgr_u (param $0 v128) (param $1 v128) (result v128) (i8x16.avgr_u (local.get $0) (local.get $1) ) ) - (func $i16x8.extadd_pairwise_i8x16_s (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extadd_pairwise_i8x16_u (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_u - (local.get $0) - ) - ) - (func $i32x4.extadd_pairwise_i16x8_s (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extadd_pairwise_i16x8_u (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_u - (local.get $0) - ) - ) (func $i16x8.abs (param $0 v128) (result v128) (i16x8.abs (local.get $0) @@ -787,10 +690,9 @@ (local.get $0) ) ) - (func $i16x8.q15mulr_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.q15mulr_sat_s + (func $i16x8.any_true (param $0 v128) (result i32) + (i16x8.any_true (local.get $0) - (local.get $1) ) ) (func $i16x8.all_true (param $0 v128) (result i32) @@ -803,38 +705,6 @@ (local.get $0) ) ) - (func $i16x8.narrow_i32x4_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_s - (local.get $0) - (local.get $1) - ) - ) - (func $i16x8.narrow_i32x4_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_u - (local.get $0) - (local.get $1) - ) - ) - (func $i16x8.extend_low_i8x16_s (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extend_high_i8x16_s (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extend_low_i8x16_u (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_u - (local.get $0) - ) - ) - (func $i16x8.extend_high_i8x16_u (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_u - (local.get $0) - ) - ) (func $i16x8.shl (param $0 v128) (param $1 i32) (result v128) (i16x8.shl (local.get $0) @@ -859,14 +729,14 @@ (local.get $1) ) ) - (func $i16x8.add_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_s + (func $i16x8.add_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $i16x8.add_sat_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_u + (func $i16x8.add_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_u (local.get $0) (local.get $1) ) @@ -877,23 +747,18 @@ (local.get $1) ) ) - (func $i16x8.sub_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_s + (func $i16x8.sub_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $i16x8.sub_sat_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_u + (func $i16x8.sub_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $f64x2.nearest (param $0 v128) (result v128) - (f64x2.nearest - (local.get $0) - ) - ) (func $i16x8.mul (param $0 v128) (param $1 v128) (result v128) (i16x8.mul (local.get $0) @@ -930,6 +795,12 @@ (local.get $1) ) ) + (func $i16x8.q15mulr_sat_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.q15mulr_sat_s + (local.get $0) + (local.get $1) + ) + ) (func $i16x8.extmul_low_i8x16_s (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_low_i8x16_s (local.get $0) @@ -964,6 +835,11 @@ (local.get $0) ) ) + (func $i32x4.any_true (param $0 v128) (result i32) + (i32x4.any_true + (local.get $0) + ) + ) (func $i32x4.all_true (param $0 v128) (result i32) (i32x4.all_true (local.get $0) @@ -974,26 +850,6 @@ (local.get $0) ) ) - (func $i32x4.extend_low_i16x8_s (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extend_high_i16x8_s (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extend_low_i16x8_u (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_u - (local.get $0) - ) - ) - (func $i32x4.extend_high_i16x8_u (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_u - (local.get $0) - ) - ) (func $i32x4.shl (param $0 v128) (param $1 i32) (result v128) (i32x4.shl (local.get $0) @@ -1084,50 +940,20 @@ (local.get $1) ) ) - (func $i64x2.abs (param $0 v128) (result v128) - (i64x2.abs - (local.get $0) - ) - ) (func $i64x2.neg (param $0 v128) (result v128) (i64x2.neg (local.get $0) ) ) - (func $i64x2.all_true (param $0 v128) (result i32) - (i64x2.all_true - (local.get $0) - ) - ) (func $i64x2.bitmask (param $0 v128) (result i32) (i64x2.bitmask (local.get $0) ) ) - (func $i64x2.extend_low_i32x4_s (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_s + (func $i64x2.shl (param $0 v128) (param $1 i32) (result v128) + (i64x2.shl (local.get $0) - ) - ) - (func $i64x2.extend_high_i32x4_s (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_s - (local.get $0) - ) - ) - (func $i64x2.extend_low_i32x4_u (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_u - (local.get $0) - ) - ) - (func $i64x2.extend_high_i32x4_u (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_u - (local.get $0) - ) - ) - (func $i64x2.shl (param $0 v128) (param $1 i32) (result v128) - (i64x2.shl - (local.get $0) - (local.get $1) + (local.get $1) ) ) (func $i64x2.shr_s (param $0 v128) (param $1 i32) (result v128) @@ -1160,42 +986,6 @@ (local.get $1) ) ) - (func $i64x2.eq (param $0 v128) (param $1 v128) (result v128) - (i64x2.eq - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.ne (param $0 v128) (param $1 v128) (result v128) - (i64x2.ne - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.lt_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.lt_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.gt_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.gt_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.le_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.le_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.ge_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.ge_s - (local.get $0) - (local.get $1) - ) - ) (func $i64x2.extmul_low_i32x4_s (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_low_i32x4_s (local.get $0) @@ -1220,21 +1010,6 @@ (local.get $1) ) ) - (func $f32x4.abs (param $0 v128) (result v128) - (f32x4.abs - (local.get $0) - ) - ) - (func $f32x4.neg (param $0 v128) (result v128) - (f32x4.neg - (local.get $0) - ) - ) - (func $f32x4.sqrt (param $0 v128) (result v128) - (f32x4.sqrt - (local.get $0) - ) - ) (func $f32x4.add (param $0 v128) (param $1 v128) (result v128) (f32x4.add (local.get $0) @@ -1283,21 +1058,55 @@ (local.get $1) ) ) - (func $f64x2.abs (param $0 v128) (result v128) - (f64x2.abs + (func $f32x4.ceil (param $0 v128) (result v128) + (f32x4.ceil (local.get $0) ) ) - (func $f64x2.neg (param $0 v128) (result v128) - (f64x2.neg + (func $f32x4.floor (param $0 v128) (result v128) + (f32x4.floor (local.get $0) ) ) - (func $f64x2.sqrt (param $0 v128) (result v128) - (f64x2.sqrt + (func $f32x4.trunc (param $0 v128) (result v128) + (f32x4.trunc (local.get $0) ) ) + (func $f32x4.nearest (param $0 v128) (result v128) + (f32x4.nearest + (local.get $0) + ) + ) + (func $f32x4.abs (param $0 v128) (result v128) + (f32x4.abs + (local.get $0) + ) + ) + (func $f32x4.neg (param $0 v128) (result v128) + (f32x4.neg + (local.get $0) + ) + ) + (func $f32x4.sqrt (param $0 v128) (result v128) + (f32x4.sqrt + (local.get $0) + ) + ) + (func $f32x4.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfma + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $f32x4.qfms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfms + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) (func $f64x2.add (param $0 v128) (param $1 v128) (result v128) (f64x2.add (local.get $0) @@ -1346,6 +1155,75 @@ (local.get $1) ) ) + (func $f64x2.ceil (param $0 v128) (result v128) + (f64x2.ceil + (local.get $0) + ) + ) + (func $f64x2.floor (param $0 v128) (result v128) + (f64x2.floor + (local.get $0) + ) + ) + (func $f64x2.trunc (param $0 v128) (result v128) + (f64x2.trunc + (local.get $0) + ) + ) + (func $f64x2.nearest (param $0 v128) (result v128) + (f64x2.nearest + (local.get $0) + ) + ) + (func $f64x2.abs (param $0 v128) (result v128) + (f64x2.abs + (local.get $0) + ) + ) + (func $f64x2.neg (param $0 v128) (result v128) + (f64x2.neg + (local.get $0) + ) + ) + (func $f64x2.sqrt (param $0 v128) (result v128) + (f64x2.sqrt + (local.get $0) + ) + ) + (func $f64x2.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfma + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $f64x2.qfms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfms + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $i16x8.extadd_pairwise_i8x16_s (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.extadd_pairwise_i8x16_u (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_u + (local.get $0) + ) + ) + (func $i32x4.extadd_pairwise_i16x8_s (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.extadd_pairwise_i16x8_u (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_u + (local.get $0) + ) + ) (func $i32x4.trunc_sat_f32x4_s (param $0 v128) (result v128) (i32x4.trunc_sat_f32x4_s (local.get $0) @@ -1356,6 +1234,16 @@ (local.get $0) ) ) + (func $i64x2.trunc_sat_f64x2_s (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_s + (local.get $0) + ) + ) + (func $i64x2.trunc_sat_f64x2_u (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_u + (local.get $0) + ) + ) (func $f32x4.convert_i32x4_s (param $0 v128) (result v128) (f32x4.convert_i32x4_s (local.get $0) @@ -1366,23 +1254,173 @@ (local.get $0) ) ) - (func $i32x4.trunc_sat_f64x2_s_zero (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_s_zero + (func $f64x2.convert_i64x2_s (param $0 v128) (result v128) + (f64x2.convert_i64x2_s + (local.get $0) + ) + ) + (func $f64x2.convert_i64x2_u (param $0 v128) (result v128) + (f64x2.convert_i64x2_u + (local.get $0) + ) + ) + (func $v8x16.load_splat (param $0 i32) (result v128) + (v8x16.load_splat + (local.get $0) + ) + ) + (func $v16x8.load_splat (param $0 i32) (result v128) + (v16x8.load_splat + (local.get $0) + ) + ) + (func $v32x4.load_splat (param $0 i32) (result v128) + (v32x4.load_splat + (local.get $0) + ) + ) + (func $v64x2.load_splat (param $0 i32) (result v128) + (v64x2.load_splat + (local.get $0) + ) + ) + (func $i8x16.narrow_i16x8_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.narrow_i16x8_s + (local.get $0) + (local.get $1) + ) + ) + (func $i8x16.narrow_i16x8_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.narrow_i16x8_u + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.narrow_i32x4_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_s + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.narrow_i32x4_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_u + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.widen_low_i8x16_s (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.widen_high_i8x16_s (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.widen_low_i8x16_u (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_u + (local.get $0) + ) + ) + (func $i16x8.widen_high_i8x16_u (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_u + (local.get $0) + ) + ) + (func $i32x4.widen_low_i16x8_s (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.widen_high_i16x8_s (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.widen_low_i16x8_u (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_u + (local.get $0) + ) + ) + (func $i32x4.widen_high_i16x8_u (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_u + (local.get $0) + ) + ) + (func $i64x2.widen_low_i32x4_s (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_s + (local.get $0) + ) + ) + (func $i64x2.widen_high_i32x4_s (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_s + (local.get $0) + ) + ) + (func $i64x2.widen_low_i32x4_u (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_u + (local.get $0) + ) + ) + (func $i64x2.widen_high_i32x4_u (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_u + (local.get $0) + ) + ) + (func $i16x8.load8x8_u (param $0 i32) (result v128) + (i16x8.load8x8_u + (local.get $0) + ) + ) + (func $i16x8.load8x8_s (param $0 i32) (result v128) + (i16x8.load8x8_s + (local.get $0) + ) + ) + (func $i32x4.load16x4_s (param $0 i32) (result v128) + (i32x4.load16x4_s + (local.get $0) + ) + ) + (func $i32x4.load16x4_u (param $0 i32) (result v128) + (i32x4.load16x4_u (local.get $0) ) ) - (func $i32x4.trunc_sat_f64x2_u_zero (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_u_zero + (func $i64x2.load32x2_s (param $0 i32) (result v128) + (i64x2.load32x2_s (local.get $0) ) ) - (func $f64x2.convert_low_i32x4_s (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_s + (func $i64x2.load32x2_u (param $0 i32) (result v128) + (i64x2.load32x2_u + (local.get $0) + ) + ) + (func $v128.load32_zero (param $0 i32) (result v128) + (v128.load32_zero + (local.get $0) + ) + ) + (func $v128.load64_zero (param $0 i32) (result v128) + (v128.load64_zero + (local.get $0) + ) + ) + (func $v8x16.swizzle (param $0 v128) (param $1 v128) (result v128) + (v8x16.swizzle + (local.get $0) + (local.get $1) + ) + ) + (func $prefetch.t (param $0 i32) + (prefetch.t offset=3 align=2 (local.get $0) ) ) - (func $f64x2.convert_low_i32x4_u (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_u + (func $prefetch.nt (param $0 i32) + (prefetch.nt offset=3 align=2 (local.get $0) ) ) diff -Nru binaryen-108/test/simd.wast.fromBinary.noDebugInfo binaryen-99/test/simd.wast.fromBinary.noDebugInfo --- binaryen-108/test/simd.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -2,1387 +2,1425 @@ (type $v128_v128_=>_v128 (func (param v128 v128) (result v128))) (type $v128_=>_v128 (func (param v128) (result v128))) (type $i32_=>_v128 (func (param i32) (result v128))) - (type $v128_i32_=>_v128 (func (param v128 i32) (result v128))) (type $v128_=>_i32 (func (param v128) (result i32))) + (type $v128_i32_=>_v128 (func (param v128 i32) (result v128))) + (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) (type $i32_v128_=>_none (func (param i32 v128))) (type $i32_v128_=>_v128 (func (param i32 v128) (result v128))) (type $none_=>_v128 (func (result v128))) + (type $i32_=>_none (func (param i32))) + (type $v128_=>_i64 (func (param v128) (result i64))) + (type $v128_=>_f32 (func (param v128) (result f32))) + (type $v128_=>_f64 (func (param v128) (result f64))) (type $f32_=>_v128 (func (param f32) (result v128))) (type $f64_=>_v128 (func (param f64) (result v128))) - (type $v128_=>_i64 (func (param v128) (result i64))) (type $v128_i64_=>_v128 (func (param v128 i64) (result v128))) - (type $v128_=>_f32 (func (param v128) (result f32))) (type $v128_f32_=>_v128 (func (param v128 f32) (result v128))) - (type $v128_=>_f64 (func (param v128) (result f64))) (type $v128_f64_=>_v128 (func (param v128 f64) (result v128))) - (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) (memory $0 1 1) (func $0 (param $0 i32) (result v128) (v128.load (local.get $0) ) ) - (func $1 (param $0 i32) (result v128) - (v128.load8x8_s - (local.get $0) - ) - ) - (func $2 (param $0 i32) (result v128) - (v128.load8x8_u - (local.get $0) - ) - ) - (func $3 (param $0 i32) (result v128) - (v128.load16x4_s - (local.get $0) - ) - ) - (func $4 (param $0 i32) (result v128) - (v128.load16x4_u - (local.get $0) - ) - ) - (func $5 (param $0 i32) (result v128) - (v128.load32x2_s - (local.get $0) - ) - ) - (func $6 (param $0 i32) (result v128) - (v128.load32x2_u - (local.get $0) - ) - ) - (func $7 (param $0 i32) (result v128) - (v128.load8_splat - (local.get $0) - ) - ) - (func $8 (param $0 i32) (result v128) - (v128.load16_splat - (local.get $0) - ) - ) - (func $9 (param $0 i32) (result v128) - (v128.load32_splat - (local.get $0) - ) - ) - (func $10 (param $0 i32) (result v128) - (v128.load64_splat - (local.get $0) - ) - ) - (func $11 (param $0 i32) (param $1 v128) + (func $1 (param $0 i32) (param $1 v128) (v128.store (local.get $0) (local.get $1) ) ) - (func $12 (result v128) + (func $2 (result v128) (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d) ) - (func $13 (result v128) + (func $3 (result v128) (v128.const i32x4 0x00020001 0x00040003 0x00060005 0x00080007) ) - (func $14 (result v128) + (func $4 (result v128) (v128.const i32x4 0x00000001 0x00000002 0x00000003 0x00000004) ) - (func $15 (result v128) + (func $5 (result v128) (v128.const i32x4 0x00000001 0x00000000 0x00000002 0x00000000) ) - (func $16 (result v128) + (func $6 (result v128) (v128.const i32x4 0x3f800000 0x40000000 0x40400000 0x40800000) ) - (func $17 (result v128) + (func $7 (result v128) (v128.const i32x4 0x00000000 0x3ff00000 0x00000000 0x40000000) ) - (func $18 (param $0 v128) (param $1 v128) (result v128) - (i8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 - (local.get $0) - (local.get $1) - ) - ) - (func $19 (param $0 v128) (param $1 v128) (result v128) - (i8x16.swizzle + (func $8 (param $0 v128) (param $1 v128) (result v128) + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 (local.get $0) (local.get $1) ) ) - (func $20 (param $0 i32) (result v128) + (func $9 (param $0 i32) (result v128) (i8x16.splat (local.get $0) ) ) - (func $21 (param $0 i32) (result v128) - (i16x8.splat - (local.get $0) - ) - ) - (func $22 (param $0 f32) (result v128) - (f32x4.splat - (local.get $0) - ) - ) - (func $23 (param $0 f64) (result v128) - (f64x2.splat - (local.get $0) - ) - ) - (func $24 (param $0 v128) (result i32) + (func $10 (param $0 v128) (result i32) (i8x16.extract_lane_s 0 (local.get $0) ) ) - (func $25 (param $0 v128) (result i32) + (func $11 (param $0 v128) (result i32) (i8x16.extract_lane_u 0 (local.get $0) ) ) - (func $26 (param $0 v128) (param $1 i32) (result v128) + (func $12 (param $0 v128) (param $1 i32) (result v128) (i8x16.replace_lane 0 (local.get $0) (local.get $1) ) ) - (func $27 (param $0 v128) (result i32) + (func $13 (param $0 i32) (result v128) + (i16x8.splat + (local.get $0) + ) + ) + (func $14 (param $0 v128) (result i32) (i16x8.extract_lane_s 0 (local.get $0) ) ) - (func $28 (param $0 v128) (result i32) + (func $15 (param $0 v128) (result i32) (i16x8.extract_lane_u 0 (local.get $0) ) ) - (func $29 (param $0 v128) (param $1 i32) (result v128) + (func $16 (param $0 v128) (param $1 i32) (result v128) (i16x8.replace_lane 0 (local.get $0) (local.get $1) ) ) - (func $30 (param $0 v128) (result i32) + (func $17 (param $0 i32) (result v128) + (i32x4.splat + (local.get $0) + ) + ) + (func $18 (param $0 v128) (result i32) (i32x4.extract_lane 0 (local.get $0) ) ) - (func $31 (param $0 v128) (param $1 i32) (result v128) + (func $19 (param $0 v128) (param $1 i32) (result v128) (i32x4.replace_lane 0 (local.get $0) (local.get $1) ) ) - (func $32 (param $0 v128) (result i64) + (func $20 (param $0 v128) (result i64) (i64x2.extract_lane 0 (local.get $0) ) ) - (func $33 (param $0 v128) (param $1 i64) (result v128) + (func $21 (param $0 v128) (param $1 i64) (result v128) (i64x2.replace_lane 0 (local.get $0) (local.get $1) ) ) - (func $34 (param $0 v128) (result f32) + (func $22 (param $0 f32) (result v128) + (f32x4.splat + (local.get $0) + ) + ) + (func $23 (param $0 v128) (result f32) (f32x4.extract_lane 0 (local.get $0) ) ) - (func $35 (param $0 v128) (param $1 f32) (result v128) + (func $24 (param $0 v128) (param $1 f32) (result v128) (f32x4.replace_lane 0 (local.get $0) (local.get $1) ) ) - (func $36 (param $0 v128) (result f64) + (func $25 (param $0 f64) (result v128) + (f64x2.splat + (local.get $0) + ) + ) + (func $26 (param $0 v128) (result f64) (f64x2.extract_lane 0 (local.get $0) ) ) - (func $37 (param $0 v128) (param $1 f64) (result v128) + (func $27 (param $0 v128) (param $1 f64) (result v128) (f64x2.replace_lane 0 (local.get $0) (local.get $1) ) ) - (func $38 (param $0 v128) (param $1 v128) (result v128) + (func $28 (param $0 v128) (param $1 v128) (result v128) (i8x16.eq (local.get $0) (local.get $1) ) ) - (func $39 (param $0 v128) (param $1 v128) (result v128) + (func $29 (param $0 v128) (param $1 v128) (result v128) (i8x16.ne (local.get $0) (local.get $1) ) ) - (func $40 (param $0 v128) (param $1 v128) (result v128) + (func $30 (param $0 v128) (param $1 v128) (result v128) (i8x16.lt_s (local.get $0) (local.get $1) ) ) - (func $41 (param $0 v128) (param $1 v128) (result v128) + (func $31 (param $0 v128) (param $1 v128) (result v128) (i8x16.lt_u (local.get $0) (local.get $1) ) ) - (func $42 (param $0 v128) (param $1 v128) (result v128) + (func $32 (param $0 v128) (param $1 v128) (result v128) (i8x16.gt_s (local.get $0) (local.get $1) ) ) - (func $43 (param $0 v128) (param $1 v128) (result v128) + (func $33 (param $0 v128) (param $1 v128) (result v128) (i8x16.gt_u (local.get $0) (local.get $1) ) ) - (func $44 (param $0 v128) (param $1 v128) (result v128) + (func $34 (param $0 v128) (param $1 v128) (result v128) (i8x16.le_s (local.get $0) (local.get $1) ) ) - (func $45 (param $0 v128) (param $1 v128) (result v128) + (func $35 (param $0 v128) (param $1 v128) (result v128) (i8x16.le_u (local.get $0) (local.get $1) ) ) - (func $46 (param $0 v128) (param $1 v128) (result v128) + (func $36 (param $0 v128) (param $1 v128) (result v128) (i8x16.ge_s (local.get $0) (local.get $1) ) ) - (func $47 (param $0 v128) (param $1 v128) (result v128) + (func $37 (param $0 v128) (param $1 v128) (result v128) (i8x16.ge_u (local.get $0) (local.get $1) ) ) - (func $48 (param $0 v128) (param $1 v128) (result v128) + (func $38 (param $0 v128) (param $1 v128) (result v128) (i16x8.eq (local.get $0) (local.get $1) ) ) - (func $49 (param $0 v128) (param $1 v128) (result v128) + (func $39 (param $0 v128) (param $1 v128) (result v128) (i16x8.ne (local.get $0) (local.get $1) ) ) - (func $50 (param $0 v128) (param $1 v128) (result v128) + (func $40 (param $0 v128) (param $1 v128) (result v128) (i16x8.lt_s (local.get $0) (local.get $1) ) ) - (func $51 (param $0 v128) (param $1 v128) (result v128) + (func $41 (param $0 v128) (param $1 v128) (result v128) (i16x8.lt_u (local.get $0) (local.get $1) ) ) - (func $52 (param $0 v128) (param $1 v128) (result v128) + (func $42 (param $0 v128) (param $1 v128) (result v128) (i16x8.gt_s (local.get $0) (local.get $1) ) ) - (func $53 (param $0 v128) (param $1 v128) (result v128) + (func $43 (param $0 v128) (param $1 v128) (result v128) (i16x8.gt_u (local.get $0) (local.get $1) ) ) - (func $54 (param $0 v128) (param $1 v128) (result v128) + (func $44 (param $0 v128) (param $1 v128) (result v128) (i16x8.le_s (local.get $0) (local.get $1) ) ) - (func $55 (param $0 v128) (param $1 v128) (result v128) + (func $45 (param $0 v128) (param $1 v128) (result v128) (i16x8.le_u (local.get $0) (local.get $1) ) ) - (func $56 (param $0 v128) (param $1 v128) (result v128) + (func $46 (param $0 v128) (param $1 v128) (result v128) (i16x8.ge_s (local.get $0) (local.get $1) ) ) - (func $57 (param $0 v128) (param $1 v128) (result v128) + (func $47 (param $0 v128) (param $1 v128) (result v128) (i16x8.ge_u (local.get $0) (local.get $1) ) ) - (func $58 (param $0 v128) (param $1 v128) (result v128) + (func $48 (param $0 v128) (param $1 v128) (result v128) (i32x4.eq (local.get $0) (local.get $1) ) ) - (func $59 (param $0 v128) (param $1 v128) (result v128) + (func $49 (param $0 v128) (param $1 v128) (result v128) (i32x4.ne (local.get $0) (local.get $1) ) ) - (func $60 (param $0 v128) (param $1 v128) (result v128) + (func $50 (param $0 v128) (param $1 v128) (result v128) (i32x4.lt_s (local.get $0) (local.get $1) ) ) - (func $61 (param $0 v128) (param $1 v128) (result v128) + (func $51 (param $0 v128) (param $1 v128) (result v128) (i32x4.lt_u (local.get $0) (local.get $1) ) ) - (func $62 (param $0 v128) (param $1 v128) (result v128) + (func $52 (param $0 v128) (param $1 v128) (result v128) (i32x4.gt_s (local.get $0) (local.get $1) ) ) - (func $63 (param $0 v128) (param $1 v128) (result v128) + (func $53 (param $0 v128) (param $1 v128) (result v128) (i32x4.gt_u (local.get $0) (local.get $1) ) ) - (func $64 (param $0 v128) (param $1 v128) (result v128) + (func $54 (param $0 v128) (param $1 v128) (result v128) (i32x4.le_s (local.get $0) (local.get $1) ) ) - (func $65 (param $0 v128) (param $1 v128) (result v128) + (func $55 (param $0 v128) (param $1 v128) (result v128) (i32x4.le_u (local.get $0) (local.get $1) ) ) - (func $66 (param $0 v128) (param $1 v128) (result v128) + (func $56 (param $0 v128) (param $1 v128) (result v128) (i32x4.ge_s (local.get $0) (local.get $1) ) ) - (func $67 (param $0 v128) (param $1 v128) (result v128) + (func $57 (param $0 v128) (param $1 v128) (result v128) (i32x4.ge_u (local.get $0) (local.get $1) ) ) - (func $68 (param $0 v128) (param $1 v128) (result v128) + (func $58 (param $0 v128) (param $1 v128) (result v128) + (i64x2.eq + (local.get $0) + (local.get $1) + ) + ) + (func $59 (param $0 v128) (param $1 v128) (result v128) (f32x4.eq (local.get $0) (local.get $1) ) ) - (func $69 (param $0 v128) (param $1 v128) (result v128) + (func $60 (param $0 v128) (param $1 v128) (result v128) (f32x4.ne (local.get $0) (local.get $1) ) ) - (func $70 (param $0 v128) (param $1 v128) (result v128) + (func $61 (param $0 v128) (param $1 v128) (result v128) (f32x4.lt (local.get $0) (local.get $1) ) ) - (func $71 (param $0 v128) (param $1 v128) (result v128) + (func $62 (param $0 v128) (param $1 v128) (result v128) (f32x4.gt (local.get $0) (local.get $1) ) ) - (func $72 (param $0 v128) (param $1 v128) (result v128) + (func $63 (param $0 v128) (param $1 v128) (result v128) (f32x4.le (local.get $0) (local.get $1) ) ) - (func $73 (param $0 v128) (param $1 v128) (result v128) + (func $64 (param $0 v128) (param $1 v128) (result v128) (f32x4.ge (local.get $0) (local.get $1) ) ) - (func $74 (param $0 v128) (param $1 v128) (result v128) + (func $65 (param $0 v128) (param $1 v128) (result v128) (f64x2.eq (local.get $0) (local.get $1) ) ) - (func $75 (param $0 v128) (param $1 v128) (result v128) + (func $66 (param $0 v128) (param $1 v128) (result v128) (f64x2.ne (local.get $0) (local.get $1) ) ) - (func $76 (param $0 v128) (param $1 v128) (result v128) + (func $67 (param $0 v128) (param $1 v128) (result v128) (f64x2.lt (local.get $0) (local.get $1) ) ) - (func $77 (param $0 v128) (param $1 v128) (result v128) + (func $68 (param $0 v128) (param $1 v128) (result v128) (f64x2.gt (local.get $0) (local.get $1) ) ) - (func $78 (param $0 v128) (param $1 v128) (result v128) + (func $69 (param $0 v128) (param $1 v128) (result v128) (f64x2.le (local.get $0) (local.get $1) ) ) - (func $79 (param $0 v128) (param $1 v128) (result v128) + (func $70 (param $0 v128) (param $1 v128) (result v128) (f64x2.ge (local.get $0) (local.get $1) ) ) - (func $80 (param $0 v128) (result v128) + (func $71 (param $0 v128) (result v128) (v128.not (local.get $0) ) ) - (func $81 (param $0 v128) (param $1 v128) (result v128) + (func $72 (param $0 v128) (param $1 v128) (result v128) (v128.and (local.get $0) (local.get $1) ) ) - (func $82 (param $0 v128) (param $1 v128) (result v128) - (v128.andnot + (func $73 (param $0 v128) (param $1 v128) (result v128) + (v128.or (local.get $0) (local.get $1) ) ) - (func $83 (param $0 v128) (param $1 v128) (result v128) - (v128.or + (func $74 (param $0 v128) (param $1 v128) (result v128) + (v128.xor (local.get $0) (local.get $1) ) ) - (func $84 (param $0 v128) (param $1 v128) (result v128) - (v128.xor + (func $75 (param $0 v128) (param $1 v128) (result v128) + (v128.andnot (local.get $0) (local.get $1) ) ) - (func $85 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (func $76 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (v128.bitselect (local.get $0) (local.get $1) (local.get $2) ) ) - (func $86 (param $0 v128) (result i32) - (v128.any_true + (func $77 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v8x16.signselect (local.get $0) + (local.get $1) + (local.get $2) ) ) - (func $87 (param $0 i32) (param $1 v128) (result v128) + (func $78 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v16x8.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $79 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v32x4.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $80 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v64x2.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $81 (param $0 i32) (param $1 v128) (result v128) (v128.load8_lane 0 (local.get $0) (local.get $1) ) ) - (func $88 (param $0 i32) (param $1 v128) (result v128) + (func $82 (param $0 i32) (param $1 v128) (result v128) (v128.load16_lane 0 (local.get $0) (local.get $1) ) ) - (func $89 (param $0 i32) (param $1 v128) (result v128) + (func $83 (param $0 i32) (param $1 v128) (result v128) (v128.load32_lane 0 (local.get $0) (local.get $1) ) ) - (func $90 (param $0 i32) (param $1 v128) (result v128) + (func $84 (param $0 i32) (param $1 v128) (result v128) (v128.load64_lane 0 (local.get $0) (local.get $1) ) ) - (func $91 (param $0 i32) (param $1 v128) (result v128) + (func $85 (param $0 i32) (param $1 v128) (result v128) (v128.load64_lane align=1 0 (local.get $0) (local.get $1) ) ) - (func $92 (param $0 i32) (param $1 v128) (result v128) + (func $86 (param $0 i32) (param $1 v128) (result v128) (v128.load64_lane offset=32 0 (local.get $0) (local.get $1) ) ) - (func $93 (param $0 i32) (param $1 v128) (result v128) + (func $87 (param $0 i32) (param $1 v128) (result v128) (v128.load64_lane offset=32 align=1 0 (local.get $0) (local.get $1) ) ) - (func $94 (param $0 i32) (param $1 v128) + (func $88 (param $0 i32) (param $1 v128) (v128.store8_lane 0 (local.get $0) (local.get $1) ) ) - (func $95 (param $0 i32) (param $1 v128) + (func $89 (param $0 i32) (param $1 v128) (v128.store16_lane 0 (local.get $0) (local.get $1) ) ) - (func $96 (param $0 i32) (param $1 v128) + (func $90 (param $0 i32) (param $1 v128) (v128.store32_lane 0 (local.get $0) (local.get $1) ) ) - (func $97 (param $0 i32) (param $1 v128) + (func $91 (param $0 i32) (param $1 v128) (v128.store64_lane 0 (local.get $0) (local.get $1) ) ) - (func $98 (param $0 i32) (param $1 v128) + (func $92 (param $0 i32) (param $1 v128) (v128.store64_lane align=1 0 (local.get $0) (local.get $1) ) ) - (func $99 (param $0 i32) (param $1 v128) + (func $93 (param $0 i32) (param $1 v128) (v128.store64_lane offset=32 0 (local.get $0) (local.get $1) ) ) - (func $100 (param $0 i32) (param $1 v128) + (func $94 (param $0 i32) (param $1 v128) (v128.store64_lane offset=32 align=1 0 (local.get $0) (local.get $1) ) ) - (func $101 (param $0 i32) (result v128) - (v128.load32_zero - (local.get $0) - ) - ) - (func $102 (param $0 i32) (result v128) - (v128.load64_zero - (local.get $0) - ) - ) - (func $103 (param $0 v128) (result v128) - (f32x4.demote_f64x2_zero - (local.get $0) - ) - ) - (func $104 (param $0 v128) (result v128) - (f64x2.promote_low_f32x4 + (func $95 (param $0 v128) (result v128) + (i8x16.popcnt (local.get $0) ) ) - (func $105 (param $0 v128) (result v128) + (func $96 (param $0 v128) (result v128) (i8x16.abs (local.get $0) ) ) - (func $106 (param $0 v128) (result v128) + (func $97 (param $0 v128) (result v128) (i8x16.neg (local.get $0) ) ) - (func $107 (param $0 v128) (result v128) - (i8x16.popcnt + (func $98 (param $0 v128) (result i32) + (i8x16.any_true (local.get $0) ) ) - (func $108 (param $0 v128) (result i32) + (func $99 (param $0 v128) (result i32) (i8x16.all_true (local.get $0) ) ) - (func $109 (param $0 v128) (result i32) + (func $100 (param $0 v128) (result i32) (i8x16.bitmask (local.get $0) ) ) - (func $110 (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_s - (local.get $0) - (local.get $1) - ) - ) - (func $111 (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_u - (local.get $0) - (local.get $1) - ) - ) - (func $112 (param $0 v128) (result v128) - (f32x4.ceil - (local.get $0) - ) - ) - (func $113 (param $0 v128) (result v128) - (f32x4.floor - (local.get $0) - ) - ) - (func $114 (param $0 v128) (result v128) - (f32x4.trunc - (local.get $0) - ) - ) - (func $115 (param $0 v128) (result v128) - (f32x4.nearest - (local.get $0) - ) - ) - (func $116 (param $0 v128) (param $1 i32) (result v128) + (func $101 (param $0 v128) (param $1 i32) (result v128) (i8x16.shl (local.get $0) (local.get $1) ) ) - (func $117 (param $0 v128) (param $1 i32) (result v128) + (func $102 (param $0 v128) (param $1 i32) (result v128) (i8x16.shr_s (local.get $0) (local.get $1) ) ) - (func $118 (param $0 v128) (param $1 i32) (result v128) + (func $103 (param $0 v128) (param $1 i32) (result v128) (i8x16.shr_u (local.get $0) (local.get $1) ) ) - (func $119 (param $0 v128) (param $1 v128) (result v128) + (func $104 (param $0 v128) (param $1 v128) (result v128) (i8x16.add (local.get $0) (local.get $1) ) ) - (func $120 (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_s + (func $105 (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $121 (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_u + (func $106 (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_u (local.get $0) (local.get $1) ) ) - (func $122 (param $0 v128) (param $1 v128) (result v128) + (func $107 (param $0 v128) (param $1 v128) (result v128) (i8x16.sub (local.get $0) (local.get $1) ) ) - (func $123 (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_s + (func $108 (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $124 (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_u + (func $109 (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $125 (param $0 v128) (result v128) - (f64x2.ceil - (local.get $0) - ) - ) - (func $126 (param $0 v128) (result v128) - (f64x2.floor + (func $110 (param $0 v128) (param $1 v128) (result v128) + (i8x16.mul (local.get $0) + (local.get $1) ) ) - (func $127 (param $0 v128) (param $1 v128) (result v128) + (func $111 (param $0 v128) (param $1 v128) (result v128) (i8x16.min_s (local.get $0) (local.get $1) ) ) - (func $128 (param $0 v128) (param $1 v128) (result v128) + (func $112 (param $0 v128) (param $1 v128) (result v128) (i8x16.min_u (local.get $0) (local.get $1) ) ) - (func $129 (param $0 v128) (param $1 v128) (result v128) + (func $113 (param $0 v128) (param $1 v128) (result v128) (i8x16.max_s (local.get $0) (local.get $1) ) ) - (func $130 (param $0 v128) (param $1 v128) (result v128) + (func $114 (param $0 v128) (param $1 v128) (result v128) (i8x16.max_u (local.get $0) (local.get $1) ) ) - (func $131 (param $0 v128) (result v128) - (f64x2.trunc - (local.get $0) - ) - ) - (func $132 (param $0 v128) (param $1 v128) (result v128) + (func $115 (param $0 v128) (param $1 v128) (result v128) (i8x16.avgr_u (local.get $0) (local.get $1) ) ) - (func $133 (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_s + (func $116 (param $0 v128) (result v128) + (i16x8.abs (local.get $0) ) ) - (func $134 (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_u + (func $117 (param $0 v128) (result v128) + (i16x8.neg (local.get $0) ) ) - (func $135 (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_s + (func $118 (param $0 v128) (result i32) + (i16x8.any_true (local.get $0) ) ) - (func $136 (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_u + (func $119 (param $0 v128) (result i32) + (i16x8.all_true (local.get $0) ) ) - (func $137 (param $0 v128) (result v128) - (i16x8.abs + (func $120 (param $0 v128) (result i32) + (i16x8.bitmask (local.get $0) ) ) - (func $138 (param $0 v128) (result v128) - (i16x8.neg + (func $121 (param $0 v128) (param $1 i32) (result v128) + (i16x8.shl (local.get $0) + (local.get $1) ) ) - (func $139 (param $0 v128) (param $1 v128) (result v128) - (i16x8.q15mulr_sat_s + (func $122 (param $0 v128) (param $1 i32) (result v128) + (i16x8.shr_s (local.get $0) (local.get $1) ) ) - (func $140 (param $0 v128) (result i32) - (i16x8.all_true + (func $123 (param $0 v128) (param $1 i32) (result v128) + (i16x8.shr_u (local.get $0) + (local.get $1) ) ) - (func $141 (param $0 v128) (result i32) - (i16x8.bitmask + (func $124 (param $0 v128) (param $1 v128) (result v128) + (i16x8.add (local.get $0) + (local.get $1) ) ) - (func $142 (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_s + (func $125 (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $143 (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_u + (func $126 (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_u (local.get $0) (local.get $1) ) ) - (func $144 (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_s + (func $127 (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub (local.get $0) + (local.get $1) ) ) - (func $145 (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_s + (func $128 (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_s (local.get $0) + (local.get $1) ) ) - (func $146 (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_u + (func $129 (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_u (local.get $0) + (local.get $1) ) ) - (func $147 (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_u + (func $130 (param $0 v128) (param $1 v128) (result v128) + (i16x8.mul (local.get $0) + (local.get $1) ) ) - (func $148 (param $0 v128) (param $1 i32) (result v128) - (i16x8.shl + (func $131 (param $0 v128) (param $1 v128) (result v128) + (i16x8.min_s (local.get $0) (local.get $1) ) ) - (func $149 (param $0 v128) (param $1 i32) (result v128) - (i16x8.shr_s + (func $132 (param $0 v128) (param $1 v128) (result v128) + (i16x8.min_u (local.get $0) (local.get $1) ) ) - (func $150 (param $0 v128) (param $1 i32) (result v128) - (i16x8.shr_u + (func $133 (param $0 v128) (param $1 v128) (result v128) + (i16x8.max_s (local.get $0) (local.get $1) ) ) - (func $151 (param $0 v128) (param $1 v128) (result v128) - (i16x8.add + (func $134 (param $0 v128) (param $1 v128) (result v128) + (i16x8.max_u (local.get $0) (local.get $1) ) ) - (func $152 (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_s + (func $135 (param $0 v128) (param $1 v128) (result v128) + (i16x8.avgr_u (local.get $0) (local.get $1) ) ) - (func $153 (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_u + (func $136 (param $0 v128) (param $1 v128) (result v128) + (i16x8.q15mulr_sat_s (local.get $0) (local.get $1) ) ) - (func $154 (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub + (func $137 (param $0 v128) (param $1 v128) (result v128) + (i16x8.extmul_low_i8x16_s (local.get $0) (local.get $1) ) ) - (func $155 (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_s + (func $138 (param $0 v128) (param $1 v128) (result v128) + (i16x8.extmul_high_i8x16_s (local.get $0) (local.get $1) ) ) - (func $156 (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_u + (func $139 (param $0 v128) (param $1 v128) (result v128) + (i16x8.extmul_low_i8x16_u (local.get $0) (local.get $1) ) ) - (func $157 (param $0 v128) (result v128) - (f64x2.nearest + (func $140 (param $0 v128) (param $1 v128) (result v128) + (i16x8.extmul_high_i8x16_u (local.get $0) + (local.get $1) ) ) - (func $158 (param $0 v128) (param $1 v128) (result v128) - (i16x8.mul + (func $141 (param $0 v128) (result v128) + (i32x4.abs + (local.get $0) + ) + ) + (func $142 (param $0 v128) (result v128) + (i32x4.neg + (local.get $0) + ) + ) + (func $143 (param $0 v128) (result i32) + (i32x4.any_true + (local.get $0) + ) + ) + (func $144 (param $0 v128) (result i32) + (i32x4.all_true + (local.get $0) + ) + ) + (func $145 (param $0 v128) (result i32) + (i32x4.bitmask + (local.get $0) + ) + ) + (func $146 (param $0 v128) (param $1 i32) (result v128) + (i32x4.shl (local.get $0) (local.get $1) ) ) - (func $159 (param $0 v128) (param $1 v128) (result v128) - (i16x8.min_s + (func $147 (param $0 v128) (param $1 i32) (result v128) + (i32x4.shr_s (local.get $0) (local.get $1) ) ) - (func $160 (param $0 v128) (param $1 v128) (result v128) - (i16x8.min_u + (func $148 (param $0 v128) (param $1 i32) (result v128) + (i32x4.shr_u (local.get $0) (local.get $1) ) ) - (func $161 (param $0 v128) (param $1 v128) (result v128) - (i16x8.max_s + (func $149 (param $0 v128) (param $1 v128) (result v128) + (i32x4.add (local.get $0) (local.get $1) ) ) - (func $162 (param $0 v128) (param $1 v128) (result v128) - (i16x8.max_u + (func $150 (param $0 v128) (param $1 v128) (result v128) + (i32x4.sub (local.get $0) (local.get $1) ) ) - (func $163 (param $0 v128) (param $1 v128) (result v128) - (i16x8.avgr_u + (func $151 (param $0 v128) (param $1 v128) (result v128) + (i32x4.mul (local.get $0) (local.get $1) ) ) - (func $164 (param $0 v128) (param $1 v128) (result v128) - (i16x8.extmul_low_i8x16_s + (func $152 (param $0 v128) (param $1 v128) (result v128) + (i32x4.min_s (local.get $0) (local.get $1) ) ) - (func $165 (param $0 v128) (param $1 v128) (result v128) - (i16x8.extmul_high_i8x16_s + (func $153 (param $0 v128) (param $1 v128) (result v128) + (i32x4.min_u (local.get $0) (local.get $1) ) ) - (func $166 (param $0 v128) (param $1 v128) (result v128) - (i16x8.extmul_low_i8x16_u + (func $154 (param $0 v128) (param $1 v128) (result v128) + (i32x4.max_s (local.get $0) (local.get $1) ) ) - (func $167 (param $0 v128) (param $1 v128) (result v128) - (i16x8.extmul_high_i8x16_u + (func $155 (param $0 v128) (param $1 v128) (result v128) + (i32x4.max_u (local.get $0) (local.get $1) ) ) - (func $168 (param $0 v128) (result v128) - (i32x4.abs + (func $156 (param $0 v128) (param $1 v128) (result v128) + (i32x4.dot_i16x8_s (local.get $0) + (local.get $1) ) ) - (func $169 (param $0 v128) (result v128) - (i32x4.neg + (func $157 (param $0 v128) (param $1 v128) (result v128) + (i32x4.extmul_low_i16x8_s (local.get $0) + (local.get $1) ) ) - (func $170 (param $0 v128) (result i32) - (i32x4.all_true + (func $158 (param $0 v128) (param $1 v128) (result v128) + (i32x4.extmul_high_i16x8_s (local.get $0) + (local.get $1) ) ) - (func $171 (param $0 v128) (result i32) - (i32x4.bitmask + (func $159 (param $0 v128) (param $1 v128) (result v128) + (i32x4.extmul_low_i16x8_u (local.get $0) + (local.get $1) ) ) - (func $172 (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_s + (func $160 (param $0 v128) (param $1 v128) (result v128) + (i32x4.extmul_high_i16x8_u (local.get $0) + (local.get $1) ) ) - (func $173 (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_s + (func $161 (param $0 v128) (result v128) + (i64x2.neg (local.get $0) ) ) - (func $174 (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_u + (func $162 (param $0 v128) (result i32) + (i64x2.bitmask (local.get $0) ) ) - (func $175 (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_u + (func $163 (param $0 v128) (param $1 i32) (result v128) + (i64x2.shl (local.get $0) + (local.get $1) ) ) - (func $176 (param $0 v128) (param $1 i32) (result v128) - (i32x4.shl + (func $164 (param $0 v128) (param $1 i32) (result v128) + (i64x2.shr_s (local.get $0) (local.get $1) ) ) - (func $177 (param $0 v128) (param $1 i32) (result v128) - (i32x4.shr_s + (func $165 (param $0 v128) (param $1 i32) (result v128) + (i64x2.shr_u (local.get $0) (local.get $1) ) ) - (func $178 (param $0 v128) (param $1 i32) (result v128) - (i32x4.shr_u + (func $166 (param $0 v128) (param $1 v128) (result v128) + (i64x2.add (local.get $0) (local.get $1) ) ) - (func $179 (param $0 v128) (param $1 v128) (result v128) - (i32x4.add + (func $167 (param $0 v128) (param $1 v128) (result v128) + (i64x2.sub (local.get $0) (local.get $1) ) ) - (func $180 (param $0 v128) (param $1 v128) (result v128) - (i32x4.sub + (func $168 (param $0 v128) (param $1 v128) (result v128) + (i64x2.mul (local.get $0) (local.get $1) ) ) - (func $181 (param $0 v128) (param $1 v128) (result v128) - (i32x4.mul + (func $169 (param $0 v128) (param $1 v128) (result v128) + (i64x2.extmul_low_i32x4_s (local.get $0) (local.get $1) ) ) - (func $182 (param $0 v128) (param $1 v128) (result v128) - (i32x4.min_s + (func $170 (param $0 v128) (param $1 v128) (result v128) + (i64x2.extmul_high_i32x4_s (local.get $0) (local.get $1) ) ) - (func $183 (param $0 v128) (param $1 v128) (result v128) - (i32x4.min_u + (func $171 (param $0 v128) (param $1 v128) (result v128) + (i64x2.extmul_low_i32x4_u (local.get $0) (local.get $1) ) ) - (func $184 (param $0 v128) (param $1 v128) (result v128) - (i32x4.max_s + (func $172 (param $0 v128) (param $1 v128) (result v128) + (i64x2.extmul_high_i32x4_u (local.get $0) (local.get $1) ) ) - (func $185 (param $0 v128) (param $1 v128) (result v128) - (i32x4.max_u + (func $173 (param $0 v128) (param $1 v128) (result v128) + (f32x4.add (local.get $0) (local.get $1) ) ) - (func $186 (param $0 v128) (param $1 v128) (result v128) - (i32x4.dot_i16x8_s + (func $174 (param $0 v128) (param $1 v128) (result v128) + (f32x4.sub (local.get $0) (local.get $1) ) ) - (func $187 (param $0 v128) (param $1 v128) (result v128) - (i32x4.extmul_low_i16x8_s + (func $175 (param $0 v128) (param $1 v128) (result v128) + (f32x4.mul (local.get $0) (local.get $1) ) ) - (func $188 (param $0 v128) (param $1 v128) (result v128) - (i32x4.extmul_high_i16x8_s + (func $176 (param $0 v128) (param $1 v128) (result v128) + (f32x4.div (local.get $0) (local.get $1) ) ) - (func $189 (param $0 v128) (param $1 v128) (result v128) - (i32x4.extmul_low_i16x8_u + (func $177 (param $0 v128) (param $1 v128) (result v128) + (f32x4.min (local.get $0) (local.get $1) ) ) - (func $190 (param $0 v128) (param $1 v128) (result v128) - (i32x4.extmul_high_i16x8_u + (func $178 (param $0 v128) (param $1 v128) (result v128) + (f32x4.max (local.get $0) (local.get $1) ) ) - (func $191 (param $0 v128) (result v128) - (i64x2.abs + (func $179 (param $0 v128) (param $1 v128) (result v128) + (f32x4.pmin (local.get $0) + (local.get $1) ) ) - (func $192 (param $0 v128) (result v128) - (i64x2.neg + (func $180 (param $0 v128) (param $1 v128) (result v128) + (f32x4.pmax (local.get $0) + (local.get $1) ) ) - (func $193 (param $0 v128) (result i32) - (i64x2.all_true + (func $181 (param $0 v128) (result v128) + (f32x4.ceil (local.get $0) ) ) - (func $194 (param $0 v128) (result i32) - (i64x2.bitmask + (func $182 (param $0 v128) (result v128) + (f32x4.floor (local.get $0) ) ) - (func $195 (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_s + (func $183 (param $0 v128) (result v128) + (f32x4.trunc (local.get $0) ) ) - (func $196 (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_s + (func $184 (param $0 v128) (result v128) + (f32x4.nearest (local.get $0) ) ) - (func $197 (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_u + (func $185 (param $0 v128) (result v128) + (f32x4.abs (local.get $0) ) ) - (func $198 (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_u + (func $186 (param $0 v128) (result v128) + (f32x4.neg (local.get $0) ) ) - (func $199 (param $0 v128) (param $1 i32) (result v128) - (i64x2.shl + (func $187 (param $0 v128) (result v128) + (f32x4.sqrt (local.get $0) - (local.get $1) ) ) - (func $200 (param $0 v128) (param $1 i32) (result v128) - (i64x2.shr_s + (func $188 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfma (local.get $0) (local.get $1) + (local.get $2) ) ) - (func $201 (param $0 v128) (param $1 i32) (result v128) - (i64x2.shr_u + (func $189 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfms (local.get $0) (local.get $1) + (local.get $2) ) ) - (func $202 (param $0 v128) (param $1 v128) (result v128) - (i64x2.add + (func $190 (param $0 v128) (param $1 v128) (result v128) + (f64x2.add (local.get $0) (local.get $1) ) ) - (func $203 (param $0 v128) (param $1 v128) (result v128) - (i64x2.sub + (func $191 (param $0 v128) (param $1 v128) (result v128) + (f64x2.sub (local.get $0) (local.get $1) ) ) - (func $204 (param $0 v128) (param $1 v128) (result v128) - (i64x2.mul + (func $192 (param $0 v128) (param $1 v128) (result v128) + (f64x2.mul (local.get $0) (local.get $1) ) ) - (func $205 (param $0 v128) (param $1 v128) (result v128) - (i64x2.eq + (func $193 (param $0 v128) (param $1 v128) (result v128) + (f64x2.div (local.get $0) (local.get $1) ) ) - (func $206 (param $0 v128) (param $1 v128) (result v128) - (i64x2.ne + (func $194 (param $0 v128) (param $1 v128) (result v128) + (f64x2.min (local.get $0) (local.get $1) ) ) - (func $207 (param $0 v128) (param $1 v128) (result v128) - (i64x2.lt_s + (func $195 (param $0 v128) (param $1 v128) (result v128) + (f64x2.max (local.get $0) (local.get $1) ) ) - (func $208 (param $0 v128) (param $1 v128) (result v128) - (i64x2.gt_s + (func $196 (param $0 v128) (param $1 v128) (result v128) + (f64x2.pmin (local.get $0) (local.get $1) ) ) - (func $209 (param $0 v128) (param $1 v128) (result v128) - (i64x2.le_s + (func $197 (param $0 v128) (param $1 v128) (result v128) + (f64x2.pmax (local.get $0) (local.get $1) ) ) - (func $210 (param $0 v128) (param $1 v128) (result v128) - (i64x2.ge_s + (func $198 (param $0 v128) (result v128) + (f64x2.ceil (local.get $0) - (local.get $1) ) ) - (func $211 (param $0 v128) (param $1 v128) (result v128) - (i64x2.extmul_low_i32x4_s + (func $199 (param $0 v128) (result v128) + (f64x2.floor (local.get $0) - (local.get $1) ) ) - (func $212 (param $0 v128) (param $1 v128) (result v128) - (i64x2.extmul_high_i32x4_s + (func $200 (param $0 v128) (result v128) + (f64x2.trunc (local.get $0) - (local.get $1) ) ) - (func $213 (param $0 v128) (param $1 v128) (result v128) - (i64x2.extmul_low_i32x4_u + (func $201 (param $0 v128) (result v128) + (f64x2.nearest + (local.get $0) + ) + ) + (func $202 (param $0 v128) (result v128) + (f64x2.abs + (local.get $0) + ) + ) + (func $203 (param $0 v128) (result v128) + (f64x2.neg + (local.get $0) + ) + ) + (func $204 (param $0 v128) (result v128) + (f64x2.sqrt + (local.get $0) + ) + ) + (func $205 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfma (local.get $0) (local.get $1) + (local.get $2) ) ) - (func $214 (param $0 v128) (param $1 v128) (result v128) - (i64x2.extmul_high_i32x4_u + (func $206 (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfms (local.get $0) (local.get $1) + (local.get $2) + ) + ) + (func $207 (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_s + (local.get $0) + ) + ) + (func $208 (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_u + (local.get $0) + ) + ) + (func $209 (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_s + (local.get $0) + ) + ) + (func $210 (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_u + (local.get $0) + ) + ) + (func $211 (param $0 v128) (result v128) + (i32x4.trunc_sat_f32x4_s + (local.get $0) + ) + ) + (func $212 (param $0 v128) (result v128) + (i32x4.trunc_sat_f32x4_u + (local.get $0) + ) + ) + (func $213 (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_s + (local.get $0) + ) + ) + (func $214 (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_u + (local.get $0) ) ) (func $215 (param $0 v128) (result v128) - (f32x4.abs + (f32x4.convert_i32x4_s (local.get $0) ) ) (func $216 (param $0 v128) (result v128) - (f32x4.neg + (f32x4.convert_i32x4_u (local.get $0) ) ) (func $217 (param $0 v128) (result v128) - (f32x4.sqrt + (f64x2.convert_i64x2_s (local.get $0) ) ) - (func $218 (param $0 v128) (param $1 v128) (result v128) - (f32x4.add + (func $218 (param $0 v128) (result v128) + (f64x2.convert_i64x2_u (local.get $0) - (local.get $1) ) ) - (func $219 (param $0 v128) (param $1 v128) (result v128) - (f32x4.sub + (func $219 (param $0 i32) (result v128) + (v8x16.load_splat (local.get $0) - (local.get $1) ) ) - (func $220 (param $0 v128) (param $1 v128) (result v128) - (f32x4.mul + (func $220 (param $0 i32) (result v128) + (v16x8.load_splat (local.get $0) - (local.get $1) ) ) - (func $221 (param $0 v128) (param $1 v128) (result v128) - (f32x4.div + (func $221 (param $0 i32) (result v128) + (v32x4.load_splat (local.get $0) - (local.get $1) ) ) - (func $222 (param $0 v128) (param $1 v128) (result v128) - (f32x4.min + (func $222 (param $0 i32) (result v128) + (v64x2.load_splat (local.get $0) - (local.get $1) ) ) (func $223 (param $0 v128) (param $1 v128) (result v128) - (f32x4.max + (i8x16.narrow_i16x8_s (local.get $0) (local.get $1) ) ) (func $224 (param $0 v128) (param $1 v128) (result v128) - (f32x4.pmin + (i8x16.narrow_i16x8_u (local.get $0) (local.get $1) ) ) (func $225 (param $0 v128) (param $1 v128) (result v128) - (f32x4.pmax + (i16x8.narrow_i32x4_s (local.get $0) (local.get $1) ) ) - (func $226 (param $0 v128) (result v128) - (f64x2.abs + (func $226 (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_u (local.get $0) + (local.get $1) ) ) (func $227 (param $0 v128) (result v128) - (f64x2.neg + (i16x8.widen_low_i8x16_s (local.get $0) ) ) (func $228 (param $0 v128) (result v128) - (f64x2.sqrt + (i16x8.widen_high_i8x16_s (local.get $0) ) ) - (func $229 (param $0 v128) (param $1 v128) (result v128) - (f64x2.add + (func $229 (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_u (local.get $0) - (local.get $1) ) ) - (func $230 (param $0 v128) (param $1 v128) (result v128) - (f64x2.sub + (func $230 (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_u (local.get $0) - (local.get $1) ) ) - (func $231 (param $0 v128) (param $1 v128) (result v128) - (f64x2.mul + (func $231 (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_s (local.get $0) - (local.get $1) ) ) - (func $232 (param $0 v128) (param $1 v128) (result v128) - (f64x2.div + (func $232 (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_s (local.get $0) - (local.get $1) ) ) - (func $233 (param $0 v128) (param $1 v128) (result v128) - (f64x2.min + (func $233 (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_u (local.get $0) - (local.get $1) ) ) - (func $234 (param $0 v128) (param $1 v128) (result v128) - (f64x2.max + (func $234 (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_u (local.get $0) - (local.get $1) ) ) - (func $235 (param $0 v128) (param $1 v128) (result v128) - (f64x2.pmin + (func $235 (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_s (local.get $0) - (local.get $1) ) ) - (func $236 (param $0 v128) (param $1 v128) (result v128) - (f64x2.pmax + (func $236 (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_s (local.get $0) - (local.get $1) ) ) (func $237 (param $0 v128) (result v128) - (i32x4.trunc_sat_f32x4_s + (i64x2.widen_low_i32x4_u (local.get $0) ) ) (func $238 (param $0 v128) (result v128) - (i32x4.trunc_sat_f32x4_u + (i64x2.widen_high_i32x4_u (local.get $0) ) ) - (func $239 (param $0 v128) (result v128) - (f32x4.convert_i32x4_s + (func $239 (param $0 i32) (result v128) + (i16x8.load8x8_u (local.get $0) ) ) - (func $240 (param $0 v128) (result v128) - (f32x4.convert_i32x4_u + (func $240 (param $0 i32) (result v128) + (i16x8.load8x8_s + (local.get $0) + ) + ) + (func $241 (param $0 i32) (result v128) + (i32x4.load16x4_s + (local.get $0) + ) + ) + (func $242 (param $0 i32) (result v128) + (i32x4.load16x4_u (local.get $0) ) ) - (func $241 (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_s_zero + (func $243 (param $0 i32) (result v128) + (i64x2.load32x2_s (local.get $0) ) ) - (func $242 (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_u_zero + (func $244 (param $0 i32) (result v128) + (i64x2.load32x2_u (local.get $0) ) ) - (func $243 (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_s + (func $245 (param $0 i32) (result v128) + (v128.load32_zero + (local.get $0) + ) + ) + (func $246 (param $0 i32) (result v128) + (v128.load64_zero + (local.get $0) + ) + ) + (func $247 (param $0 v128) (param $1 v128) (result v128) + (v8x16.swizzle + (local.get $0) + (local.get $1) + ) + ) + (func $248 (param $0 i32) + (prefetch.t offset=3 align=2 (local.get $0) ) ) - (func $244 (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_u + (func $249 (param $0 i32) + (prefetch.nt offset=3 align=2 (local.get $0) ) ) diff -Nru binaryen-108/test/simd.wast.from-wast binaryen-99/test/simd.wast.from-wast --- binaryen-108/test/simd.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/simd.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,76 +2,27 @@ (type $v128_v128_=>_v128 (func (param v128 v128) (result v128))) (type $v128_=>_v128 (func (param v128) (result v128))) (type $i32_=>_v128 (func (param i32) (result v128))) - (type $v128_i32_=>_v128 (func (param v128 i32) (result v128))) (type $v128_=>_i32 (func (param v128) (result i32))) + (type $v128_i32_=>_v128 (func (param v128 i32) (result v128))) + (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) (type $i32_v128_=>_none (func (param i32 v128))) (type $i32_v128_=>_v128 (func (param i32 v128) (result v128))) (type $none_=>_v128 (func (result v128))) + (type $i32_=>_none (func (param i32))) + (type $v128_=>_i64 (func (param v128) (result i64))) + (type $v128_=>_f32 (func (param v128) (result f32))) + (type $v128_=>_f64 (func (param v128) (result f64))) (type $f32_=>_v128 (func (param f32) (result v128))) (type $f64_=>_v128 (func (param f64) (result v128))) - (type $v128_=>_i64 (func (param v128) (result i64))) (type $v128_i64_=>_v128 (func (param v128 i64) (result v128))) - (type $v128_=>_f32 (func (param v128) (result f32))) (type $v128_f32_=>_v128 (func (param v128 f32) (result v128))) - (type $v128_=>_f64 (func (param v128) (result f64))) (type $v128_f64_=>_v128 (func (param v128 f64) (result v128))) - (type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128))) (memory $0 1 1) (func $v128.load (param $0 i32) (result v128) (v128.load (local.get $0) ) ) - (func $v128.load8x8_s (param $0 i32) (result v128) - (v128.load8x8_s - (local.get $0) - ) - ) - (func $v128.load8x8_u (param $0 i32) (result v128) - (v128.load8x8_u - (local.get $0) - ) - ) - (func $v128.load16x4_s (param $0 i32) (result v128) - (v128.load16x4_s - (local.get $0) - ) - ) - (func $v128.load16x4_u (param $0 i32) (result v128) - (v128.load16x4_u - (local.get $0) - ) - ) - (func $v128.load32x2_s (param $0 i32) (result v128) - (v128.load32x2_s - (local.get $0) - ) - ) - (func $v128.load32x2_u (param $0 i32) (result v128) - (v128.load32x2_u - (local.get $0) - ) - ) - (func $v128.load8_splat (param $0 i32) (result v128) - (v128.load8_splat - (local.get $0) - ) - ) - (func $v128.load16_splat (param $0 i32) (result v128) - (v128.load16_splat - (local.get $0) - ) - ) - (func $v128.load32_splat (param $0 i32) (result v128) - (v128.load32_splat - (local.get $0) - ) - ) - (func $v128.load64_splat (param $0 i32) (result v128) - (v128.load64_splat - (local.get $0) - ) - ) (func $v128.store (param $0 i32) (param $1 v128) (v128.store (local.get $0) @@ -96,14 +47,8 @@ (func $v128.const.f64x2 (result v128) (v128.const i32x4 0x00000000 0x3ff00000 0x00000000 0x40000000) ) - (func $i8x16.shuffle (param $0 v128) (param $1 v128) (result v128) - (i8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 - (local.get $0) - (local.get $1) - ) - ) - (func $i8x16.swizzle (param $0 v128) (param $1 v128) (result v128) - (i8x16.swizzle + (func $v128.shuffle (param $0 v128) (param $1 v128) (result v128) + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 (local.get $0) (local.get $1) ) @@ -113,21 +58,6 @@ (local.get $0) ) ) - (func $i16x8.splat (param $0 i32) (result v128) - (i16x8.splat - (local.get $0) - ) - ) - (func $f32x4.splat (param $0 f32) (result v128) - (f32x4.splat - (local.get $0) - ) - ) - (func $f64x2.splat (param $0 f64) (result v128) - (f64x2.splat - (local.get $0) - ) - ) (func $i8x16.extract_lane_s (param $0 v128) (result i32) (i8x16.extract_lane_s 0 (local.get $0) @@ -144,6 +74,11 @@ (local.get $1) ) ) + (func $i16x8.splat (param $0 i32) (result v128) + (i16x8.splat + (local.get $0) + ) + ) (func $i16x8.extract_lane_s (param $0 v128) (result i32) (i16x8.extract_lane_s 0 (local.get $0) @@ -160,6 +95,11 @@ (local.get $1) ) ) + (func $i32x4.splat (param $0 i32) (result v128) + (i32x4.splat + (local.get $0) + ) + ) (func $i32x4.extract_lane (param $0 v128) (result i32) (i32x4.extract_lane 0 (local.get $0) @@ -182,6 +122,11 @@ (local.get $1) ) ) + (func $f32x4.splat (param $0 f32) (result v128) + (f32x4.splat + (local.get $0) + ) + ) (func $f32x4.extract_lane (param $0 v128) (result f32) (f32x4.extract_lane 0 (local.get $0) @@ -193,6 +138,11 @@ (local.get $1) ) ) + (func $f64x2.splat (param $0 f64) (result v128) + (f64x2.splat + (local.get $0) + ) + ) (func $f64x2.extract_lane (param $0 v128) (result f64) (f64x2.extract_lane 0 (local.get $0) @@ -384,6 +334,12 @@ (local.get $1) ) ) + (func $i64x2.eq (param $0 v128) (param $1 v128) (result v128) + (i64x2.eq + (local.get $0) + (local.get $1) + ) + ) (func $f32x4.eq (param $0 v128) (param $1 v128) (result v128) (f32x4.eq (local.get $0) @@ -467,12 +423,6 @@ (local.get $1) ) ) - (func $v128.andnot (param $0 v128) (param $1 v128) (result v128) - (v128.andnot - (local.get $0) - (local.get $1) - ) - ) (func $v128.or (param $0 v128) (param $1 v128) (result v128) (v128.or (local.get $0) @@ -485,6 +435,12 @@ (local.get $1) ) ) + (func $v128.andnot (param $0 v128) (param $1 v128) (result v128) + (v128.andnot + (local.get $0) + (local.get $1) + ) + ) (func $v128.bitselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (v128.bitselect (local.get $0) @@ -492,9 +448,32 @@ (local.get $2) ) ) - (func $v128.any_true (param $0 v128) (result i32) - (v128.any_true + (func $v8x16.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v8x16.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v16x8.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v16x8.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v32x4.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v32x4.signselect + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $v64x2.signselect (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v64x2.signselect (local.get $0) + (local.get $1) + (local.get $2) ) ) (func $v128.load8_lane (param $0 i32) (param $1 v128) (result v128) @@ -581,23 +560,8 @@ (local.get $1) ) ) - (func $v128.load32_zero (param $0 i32) (result v128) - (v128.load32_zero - (local.get $0) - ) - ) - (func $v128.load64_zero (param $0 i32) (result v128) - (v128.load64_zero - (local.get $0) - ) - ) - (func $f32x4.demote_f64x2_zero (param $0 v128) (result v128) - (f32x4.demote_f64x2_zero - (local.get $0) - ) - ) - (func $f64x2.promote_low_f32x4 (param $0 v128) (result v128) - (f64x2.promote_low_f32x4 + (func $i8x16.popcnt (param $0 v128) (result v128) + (i8x16.popcnt (local.get $0) ) ) @@ -611,8 +575,8 @@ (local.get $0) ) ) - (func $i8x16.popcnt (param $0 v128) (result v128) - (i8x16.popcnt + (func $i8x16.any_true (param $0 v128) (result i32) + (i8x16.any_true (local.get $0) ) ) @@ -626,38 +590,6 @@ (local.get $0) ) ) - (func $i8x16.narrow_i16x8_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_s - (local.get $0) - (local.get $1) - ) - ) - (func $i8x16.narrow_i16x8_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.narrow_i16x8_u - (local.get $0) - (local.get $1) - ) - ) - (func $f32x4.ceil (param $0 v128) (result v128) - (f32x4.ceil - (local.get $0) - ) - ) - (func $f32x4.floor (param $0 v128) (result v128) - (f32x4.floor - (local.get $0) - ) - ) - (func $f32x4.trunc (param $0 v128) (result v128) - (f32x4.trunc - (local.get $0) - ) - ) - (func $f32x4.nearest (param $0 v128) (result v128) - (f32x4.nearest - (local.get $0) - ) - ) (func $i8x16.shl (param $0 v128) (param $1 i32) (result v128) (i8x16.shl (local.get $0) @@ -682,14 +614,14 @@ (local.get $1) ) ) - (func $i8x16.add_sat_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_s + (func $i8x16.add_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $i8x16.add_sat_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.add_sat_u + (func $i8x16.add_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.add_saturate_u (local.get $0) (local.get $1) ) @@ -700,26 +632,22 @@ (local.get $1) ) ) - (func $i8x16.sub_sat_s (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_s + (func $i8x16.sub_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $i8x16.sub_sat_u (param $0 v128) (param $1 v128) (result v128) - (i8x16.sub_sat_u + (func $i8x16.sub_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $f64x2.ceil (param $0 v128) (result v128) - (f64x2.ceil - (local.get $0) - ) - ) - (func $f64x2.floor (param $0 v128) (result v128) - (f64x2.floor + (func $i8x16.mul (param $0 v128) (param $1 v128) (result v128) + (i8x16.mul (local.get $0) + (local.get $1) ) ) (func $i8x16.min_s (param $0 v128) (param $1 v128) (result v128) @@ -746,37 +674,12 @@ (local.get $1) ) ) - (func $f64x2.trunc (param $0 v128) (result v128) - (f64x2.trunc - (local.get $0) - ) - ) (func $i8x16.avgr_u (param $0 v128) (param $1 v128) (result v128) (i8x16.avgr_u (local.get $0) (local.get $1) ) ) - (func $i16x8.extadd_pairwise_i8x16_s (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extadd_pairwise_i8x16_u (param $0 v128) (result v128) - (i16x8.extadd_pairwise_i8x16_u - (local.get $0) - ) - ) - (func $i32x4.extadd_pairwise_i16x8_s (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extadd_pairwise_i16x8_u (param $0 v128) (result v128) - (i32x4.extadd_pairwise_i16x8_u - (local.get $0) - ) - ) (func $i16x8.abs (param $0 v128) (result v128) (i16x8.abs (local.get $0) @@ -787,10 +690,9 @@ (local.get $0) ) ) - (func $i16x8.q15mulr_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.q15mulr_sat_s + (func $i16x8.any_true (param $0 v128) (result i32) + (i16x8.any_true (local.get $0) - (local.get $1) ) ) (func $i16x8.all_true (param $0 v128) (result i32) @@ -803,38 +705,6 @@ (local.get $0) ) ) - (func $i16x8.narrow_i32x4_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_s - (local.get $0) - (local.get $1) - ) - ) - (func $i16x8.narrow_i32x4_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.narrow_i32x4_u - (local.get $0) - (local.get $1) - ) - ) - (func $i16x8.extend_low_i8x16_s (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extend_high_i8x16_s (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_s - (local.get $0) - ) - ) - (func $i16x8.extend_low_i8x16_u (param $0 v128) (result v128) - (i16x8.extend_low_i8x16_u - (local.get $0) - ) - ) - (func $i16x8.extend_high_i8x16_u (param $0 v128) (result v128) - (i16x8.extend_high_i8x16_u - (local.get $0) - ) - ) (func $i16x8.shl (param $0 v128) (param $1 i32) (result v128) (i16x8.shl (local.get $0) @@ -859,14 +729,14 @@ (local.get $1) ) ) - (func $i16x8.add_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_s + (func $i16x8.add_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_s (local.get $0) (local.get $1) ) ) - (func $i16x8.add_sat_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.add_sat_u + (func $i16x8.add_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.add_saturate_u (local.get $0) (local.get $1) ) @@ -877,23 +747,18 @@ (local.get $1) ) ) - (func $i16x8.sub_sat_s (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_s + (func $i16x8.sub_saturate_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_s (local.get $0) (local.get $1) ) ) - (func $i16x8.sub_sat_u (param $0 v128) (param $1 v128) (result v128) - (i16x8.sub_sat_u + (func $i16x8.sub_saturate_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.sub_saturate_u (local.get $0) (local.get $1) ) ) - (func $f64x2.nearest (param $0 v128) (result v128) - (f64x2.nearest - (local.get $0) - ) - ) (func $i16x8.mul (param $0 v128) (param $1 v128) (result v128) (i16x8.mul (local.get $0) @@ -930,6 +795,12 @@ (local.get $1) ) ) + (func $i16x8.q15mulr_sat_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.q15mulr_sat_s + (local.get $0) + (local.get $1) + ) + ) (func $i16x8.extmul_low_i8x16_s (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_low_i8x16_s (local.get $0) @@ -964,6 +835,11 @@ (local.get $0) ) ) + (func $i32x4.any_true (param $0 v128) (result i32) + (i32x4.any_true + (local.get $0) + ) + ) (func $i32x4.all_true (param $0 v128) (result i32) (i32x4.all_true (local.get $0) @@ -974,26 +850,6 @@ (local.get $0) ) ) - (func $i32x4.extend_low_i16x8_s (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extend_high_i16x8_s (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_s - (local.get $0) - ) - ) - (func $i32x4.extend_low_i16x8_u (param $0 v128) (result v128) - (i32x4.extend_low_i16x8_u - (local.get $0) - ) - ) - (func $i32x4.extend_high_i16x8_u (param $0 v128) (result v128) - (i32x4.extend_high_i16x8_u - (local.get $0) - ) - ) (func $i32x4.shl (param $0 v128) (param $1 i32) (result v128) (i32x4.shl (local.get $0) @@ -1084,50 +940,20 @@ (local.get $1) ) ) - (func $i64x2.abs (param $0 v128) (result v128) - (i64x2.abs - (local.get $0) - ) - ) (func $i64x2.neg (param $0 v128) (result v128) (i64x2.neg (local.get $0) ) ) - (func $i64x2.all_true (param $0 v128) (result i32) - (i64x2.all_true - (local.get $0) - ) - ) (func $i64x2.bitmask (param $0 v128) (result i32) (i64x2.bitmask (local.get $0) ) ) - (func $i64x2.extend_low_i32x4_s (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_s + (func $i64x2.shl (param $0 v128) (param $1 i32) (result v128) + (i64x2.shl (local.get $0) - ) - ) - (func $i64x2.extend_high_i32x4_s (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_s - (local.get $0) - ) - ) - (func $i64x2.extend_low_i32x4_u (param $0 v128) (result v128) - (i64x2.extend_low_i32x4_u - (local.get $0) - ) - ) - (func $i64x2.extend_high_i32x4_u (param $0 v128) (result v128) - (i64x2.extend_high_i32x4_u - (local.get $0) - ) - ) - (func $i64x2.shl (param $0 v128) (param $1 i32) (result v128) - (i64x2.shl - (local.get $0) - (local.get $1) + (local.get $1) ) ) (func $i64x2.shr_s (param $0 v128) (param $1 i32) (result v128) @@ -1160,42 +986,6 @@ (local.get $1) ) ) - (func $i64x2.eq (param $0 v128) (param $1 v128) (result v128) - (i64x2.eq - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.ne (param $0 v128) (param $1 v128) (result v128) - (i64x2.ne - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.lt_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.lt_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.gt_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.gt_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.le_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.le_s - (local.get $0) - (local.get $1) - ) - ) - (func $i64x2.ge_s (param $0 v128) (param $1 v128) (result v128) - (i64x2.ge_s - (local.get $0) - (local.get $1) - ) - ) (func $i64x2.extmul_low_i32x4_s (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_low_i32x4_s (local.get $0) @@ -1220,21 +1010,6 @@ (local.get $1) ) ) - (func $f32x4.abs (param $0 v128) (result v128) - (f32x4.abs - (local.get $0) - ) - ) - (func $f32x4.neg (param $0 v128) (result v128) - (f32x4.neg - (local.get $0) - ) - ) - (func $f32x4.sqrt (param $0 v128) (result v128) - (f32x4.sqrt - (local.get $0) - ) - ) (func $f32x4.add (param $0 v128) (param $1 v128) (result v128) (f32x4.add (local.get $0) @@ -1283,21 +1058,55 @@ (local.get $1) ) ) - (func $f64x2.abs (param $0 v128) (result v128) - (f64x2.abs + (func $f32x4.ceil (param $0 v128) (result v128) + (f32x4.ceil (local.get $0) ) ) - (func $f64x2.neg (param $0 v128) (result v128) - (f64x2.neg + (func $f32x4.floor (param $0 v128) (result v128) + (f32x4.floor (local.get $0) ) ) - (func $f64x2.sqrt (param $0 v128) (result v128) - (f64x2.sqrt + (func $f32x4.trunc (param $0 v128) (result v128) + (f32x4.trunc (local.get $0) ) ) + (func $f32x4.nearest (param $0 v128) (result v128) + (f32x4.nearest + (local.get $0) + ) + ) + (func $f32x4.abs (param $0 v128) (result v128) + (f32x4.abs + (local.get $0) + ) + ) + (func $f32x4.neg (param $0 v128) (result v128) + (f32x4.neg + (local.get $0) + ) + ) + (func $f32x4.sqrt (param $0 v128) (result v128) + (f32x4.sqrt + (local.get $0) + ) + ) + (func $f32x4.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfma + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $f32x4.qfms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f32x4.qfms + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) (func $f64x2.add (param $0 v128) (param $1 v128) (result v128) (f64x2.add (local.get $0) @@ -1346,6 +1155,75 @@ (local.get $1) ) ) + (func $f64x2.ceil (param $0 v128) (result v128) + (f64x2.ceil + (local.get $0) + ) + ) + (func $f64x2.floor (param $0 v128) (result v128) + (f64x2.floor + (local.get $0) + ) + ) + (func $f64x2.trunc (param $0 v128) (result v128) + (f64x2.trunc + (local.get $0) + ) + ) + (func $f64x2.nearest (param $0 v128) (result v128) + (f64x2.nearest + (local.get $0) + ) + ) + (func $f64x2.abs (param $0 v128) (result v128) + (f64x2.abs + (local.get $0) + ) + ) + (func $f64x2.neg (param $0 v128) (result v128) + (f64x2.neg + (local.get $0) + ) + ) + (func $f64x2.sqrt (param $0 v128) (result v128) + (f64x2.sqrt + (local.get $0) + ) + ) + (func $f64x2.qfma (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfma + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $f64x2.qfms (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (f64x2.qfms + (local.get $0) + (local.get $1) + (local.get $2) + ) + ) + (func $i16x8.extadd_pairwise_i8x16_s (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.extadd_pairwise_i8x16_u (param $0 v128) (result v128) + (i16x8.extadd_pairwise_i8x16_u + (local.get $0) + ) + ) + (func $i32x4.extadd_pairwise_i16x8_s (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.extadd_pairwise_i16x8_u (param $0 v128) (result v128) + (i32x4.extadd_pairwise_i16x8_u + (local.get $0) + ) + ) (func $i32x4.trunc_sat_f32x4_s (param $0 v128) (result v128) (i32x4.trunc_sat_f32x4_s (local.get $0) @@ -1356,6 +1234,16 @@ (local.get $0) ) ) + (func $i64x2.trunc_sat_f64x2_s (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_s + (local.get $0) + ) + ) + (func $i64x2.trunc_sat_f64x2_u (param $0 v128) (result v128) + (i64x2.trunc_sat_f64x2_u + (local.get $0) + ) + ) (func $f32x4.convert_i32x4_s (param $0 v128) (result v128) (f32x4.convert_i32x4_s (local.get $0) @@ -1366,23 +1254,173 @@ (local.get $0) ) ) - (func $i32x4.trunc_sat_f64x2_s_zero (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_s_zero + (func $f64x2.convert_i64x2_s (param $0 v128) (result v128) + (f64x2.convert_i64x2_s + (local.get $0) + ) + ) + (func $f64x2.convert_i64x2_u (param $0 v128) (result v128) + (f64x2.convert_i64x2_u + (local.get $0) + ) + ) + (func $v8x16.load_splat (param $0 i32) (result v128) + (v8x16.load_splat + (local.get $0) + ) + ) + (func $v16x8.load_splat (param $0 i32) (result v128) + (v16x8.load_splat + (local.get $0) + ) + ) + (func $v32x4.load_splat (param $0 i32) (result v128) + (v32x4.load_splat + (local.get $0) + ) + ) + (func $v64x2.load_splat (param $0 i32) (result v128) + (v64x2.load_splat + (local.get $0) + ) + ) + (func $i8x16.narrow_i16x8_s (param $0 v128) (param $1 v128) (result v128) + (i8x16.narrow_i16x8_s + (local.get $0) + (local.get $1) + ) + ) + (func $i8x16.narrow_i16x8_u (param $0 v128) (param $1 v128) (result v128) + (i8x16.narrow_i16x8_u + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.narrow_i32x4_s (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_s + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.narrow_i32x4_u (param $0 v128) (param $1 v128) (result v128) + (i16x8.narrow_i32x4_u + (local.get $0) + (local.get $1) + ) + ) + (func $i16x8.widen_low_i8x16_s (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.widen_high_i8x16_s (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_s + (local.get $0) + ) + ) + (func $i16x8.widen_low_i8x16_u (param $0 v128) (result v128) + (i16x8.widen_low_i8x16_u + (local.get $0) + ) + ) + (func $i16x8.widen_high_i8x16_u (param $0 v128) (result v128) + (i16x8.widen_high_i8x16_u + (local.get $0) + ) + ) + (func $i32x4.widen_low_i16x8_s (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.widen_high_i16x8_s (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_s + (local.get $0) + ) + ) + (func $i32x4.widen_low_i16x8_u (param $0 v128) (result v128) + (i32x4.widen_low_i16x8_u + (local.get $0) + ) + ) + (func $i32x4.widen_high_i16x8_u (param $0 v128) (result v128) + (i32x4.widen_high_i16x8_u + (local.get $0) + ) + ) + (func $i64x2.widen_low_i32x4_s (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_s + (local.get $0) + ) + ) + (func $i64x2.widen_high_i32x4_s (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_s + (local.get $0) + ) + ) + (func $i64x2.widen_low_i32x4_u (param $0 v128) (result v128) + (i64x2.widen_low_i32x4_u + (local.get $0) + ) + ) + (func $i64x2.widen_high_i32x4_u (param $0 v128) (result v128) + (i64x2.widen_high_i32x4_u + (local.get $0) + ) + ) + (func $i16x8.load8x8_u (param $0 i32) (result v128) + (i16x8.load8x8_u + (local.get $0) + ) + ) + (func $i16x8.load8x8_s (param $0 i32) (result v128) + (i16x8.load8x8_s + (local.get $0) + ) + ) + (func $i32x4.load16x4_s (param $0 i32) (result v128) + (i32x4.load16x4_s + (local.get $0) + ) + ) + (func $i32x4.load16x4_u (param $0 i32) (result v128) + (i32x4.load16x4_u (local.get $0) ) ) - (func $i32x4.trunc_sat_f64x2_u_zero (param $0 v128) (result v128) - (i32x4.trunc_sat_f64x2_u_zero + (func $i64x2.load32x2_s (param $0 i32) (result v128) + (i64x2.load32x2_s (local.get $0) ) ) - (func $f64x2.convert_low_i32x4_s (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_s + (func $i64x2.load32x2_u (param $0 i32) (result v128) + (i64x2.load32x2_u + (local.get $0) + ) + ) + (func $v128.load32_zero (param $0 i32) (result v128) + (v128.load32_zero + (local.get $0) + ) + ) + (func $v128.load64_zero (param $0 i32) (result v128) + (v128.load64_zero + (local.get $0) + ) + ) + (func $v8x16.swizzle (param $0 v128) (param $1 v128) (result v128) + (v8x16.swizzle + (local.get $0) + (local.get $1) + ) + ) + (func $prefetch.t (param $0 i32) + (prefetch.t offset=3 align=2 (local.get $0) ) ) - (func $f64x2.convert_low_i32x4_u (param $0 v128) (result v128) - (f64x2.convert_low_i32x4_u + (func $prefetch.nt (param $0 i32) + (prefetch.nt offset=3 align=2 (local.get $0) ) ) diff -Nru binaryen-108/test/spec/address64.wast binaryen-99/test/spec/address64.wast --- binaryen-108/test/spec/address64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/address64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,7 +2,7 @@ (module (memory i64 1) - (data (i64.const 0) "abcdefghijklmnopqrstuvwxyz") + (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz") (func (export "8u_good1") (param $i i64) (result i32) (i32.load8_u offset=0 (local.get $i)) ;; 97 'a' @@ -215,7 +215,7 @@ (module (memory i64 1) - (data (i64.const 0) "abcdefghijklmnopqrstuvwxyz") + (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz") (func (export "8u_good1") (param $i i64) (result i64) (i64.load8_u offset=0 (local.get $i)) ;; 97 'a' @@ -498,7 +498,7 @@ (module (memory i64 1) - (data (i64.const 0) "\00\00\00\00\00\00\a0\7f\01\00\d0\7f") + (data (i32.const 0) "\00\00\00\00\00\00\a0\7f\01\00\d0\7f") (func (export "32_good1") (param $i i64) (result f32) (f32.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00' @@ -545,7 +545,7 @@ (module (memory i64 1) - (data (i64.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\f4\7f\01\00\00\00\00\00\fc\7f") + (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\f4\7f\01\00\00\00\00\00\fc\7f") (func (export "64_good1") (param $i i64) (result f64) (f64.load offset=0 (local.get $i)) ;; 0.0 '\00\00\00\00\00\00\00\00' diff -Nru binaryen-108/test/spec/array.wast binaryen-99/test/spec/array.wast --- binaryen-108/test/spec/array.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/array.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -;; XXX BINARYEN: rename array.new_default => array.new_default_with_rtt - -;; Type syntax - -(module - (type (array i8)) - (type (array i16)) - (type (array i32)) - (type (array i64)) - (type (array f32)) - (type (array f64)) - (type (array anyref)) - (type (array (ref data))) - (type (array (ref 0))) - (type (array (ref null 1))) - (type (array (rtt 1))) - (type (array (rtt 10 1))) - (type (array (mut i8))) - (type (array (mut i16))) - (type (array (mut i32))) - (type (array (mut i64))) - (type (array (mut i32))) - (type (array (mut i64))) - (type (array (mut anyref))) - (type (array (mut (ref data)))) - (type (array (mut (ref 0)))) - (type (array (mut (ref null i31)))) - (type (array (mut (rtt 0)))) - (type (array (mut (rtt 10 0)))) -) - - -(assert_invalid - (module - (type (array (mut (ref null 10)))) - ) - "unknown type" -) - - -;; Binding structure - -(module - (type $s0 (array (ref $s1))) - (type $s1 (array (ref $s0))) - - (func (param (ref $forward))) - - (type $forward (array i32)) -) - -(assert_invalid - (module (type (array (ref 1)))) - "unknown type" -) -(assert_invalid - (module (type (array (mut (ref 1))))) - "unknown type" -) - - -;; Basic instructions - -(module - (type $vec (array f32)) - (type $mvec (array (mut f32))) - - (func $get (param $i i32) (param $v (ref $vec)) (result f32) - (array.get $vec (local.get $v) (local.get $i)) - ) - (func (export "get") (param $i i32) (result f32) - (call $get (local.get $i) - (array.new_default_with_rtt $vec (i32.const 3) (rtt.canon $vec)) - ) - ) - - (func $set_get (param $i i32) (param $v (ref $mvec)) (param $y f32) (result f32) - (array.set $mvec (local.get $v) (local.get $i) (local.get $y)) - (array.get $mvec (local.get $v) (local.get $i)) - ) - (func (export "set_get") (param $i i32) (param $y f32) (result f32) - (call $set_get (local.get $i) - (array.new_default_with_rtt $mvec (i32.const 3) (rtt.canon $mvec)) - (local.get $y) - ) - ) - - (func $len (param $v (ref $vec)) (result i32) - (array.len $vec (local.get $v)) - ) - (func (export "len") (result i32) - (call $len (array.new_default_with_rtt $vec (i32.const 3) (rtt.canon $vec))) - ) -) - -(assert_return (invoke "get" (i32.const 0)) (f32.const 0)) -(assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) -(assert_return (invoke "len") (i32.const 3)) - -(assert_trap (invoke "get" (i32.const 10)) "out of bounds") -(assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds") - -(assert_invalid - (module - (type $a (array i64)) - (func (export "array.set-immutable") (param $a (ref $a)) - (array.set $a (local.get $a) (i32.const 0) (i64.const 1)) - ) - ) - "array is immutable" -) - - -;; Null dereference - -(module - (type $t (array (mut i32))) - (func (export "array.get-null") - (local (ref null $t)) (drop (array.get $t (local.get 0) (i32.const 0))) - ) - (func (export "array.set-null") - (local (ref null $t)) (array.set $t (local.get 0) (i32.const 0) (i32.const 0)) - ) -) - -(assert_trap (invoke "array.get-null") "null array") -(assert_trap (invoke "array.set-null") "null array") - -(assert_invalid - (module - (type $t (array i32)) - (func (export "array.new-null") - (local (ref null (rtt $t))) (drop (array.new_default_with_rtt $t (i32.const 1) (i32.const 3) (local.get 0))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (type $t (array (mut i32))) - (func (export "array.new_default_with_rtt-null") - (local (ref null (rtt $t))) (drop (array.new_default_with_rtt $t (i32.const 3) (local.get 0))) - ) - ) - "type mismatch" -) diff -Nru binaryen-108/test/spec/br_on_null.wast binaryen-99/test/spec/br_on_null.wast --- binaryen-108/test/spec/br_on_null.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/br_on_null.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -(module - (type $t (func (result i32))) - - (func $nn (param $r (ref $t)) (result i32) - (block $l - (return (call_ref (br_on_null $l (local.get $r)))) - ) - (i32.const -1) - ) - (func $n (param $r (ref null $t)) (result i32) - (block $l - (return (call_ref (br_on_null $l (local.get $r)))) - ) - (i32.const -1) - ) - - (func $f (result i32) (i32.const 7)) - - (func (export "nullable-null") (result i32) (call $n (ref.null $t))) - (func (export "nonnullable-f") (result i32) (call $nn (ref.func $f))) - (func (export "nullable-f") (result i32) (call $n (ref.func $f))) - - (func (export "unreachable") (result i32) - (block $l - (return (call_ref (br_on_null $l (unreachable)))) - ) - (i32.const -1) - ) -) - -(assert_trap (invoke "unreachable") "unreachable") - -(assert_return (invoke "nullable-null") (i32.const -1)) -(assert_return (invoke "nonnullable-f") (i32.const 7)) -(assert_return (invoke "nullable-f") (i32.const 7)) - -(module - (type $t (func)) - (func (param $r (ref $t)) (drop (br_on_null 0 (local.get $r)))) - (func (param $r (ref func)) (drop (br_on_null 0 (local.get $r)))) - (func (param $r (ref extern)) (drop (br_on_null 0 (local.get $r)))) -) - -(assert_invalid - ;; the same module as the first one in this file, but with a type added to - ;; the block - (module - (type $t (func (result i32))) - - (func $nn (param $r (ref $t)) (result i32) - (block $l (ref null $t) ;; br_on_null sends no value; a br to here is bad - (return (call_ref (br_on_null $l (local.get $r)))) - ) - (i32.const -1) - ) - ) - "bad break type" -) diff -Nru binaryen-108/test/spec/bulk-memory64.wast binaryen-99/test/spec/bulk-memory64.wast --- binaryen-108/test/spec/bulk-memory64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/bulk-memory64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ ;; Passive segment syntax (module (memory i64 1) - (data "foo")) + (data passive "foo")) ;; memory.fill (module @@ -46,7 +46,7 @@ ;; memory.copy (module (memory i64 1 1) - (data (i64.const 0) "\aa\bb\cc\dd") + (data (i32.const 0) "\aa\bb\cc\dd") (func (export "copy") (param i64 i64 i64) (memory.copy @@ -112,7 +112,7 @@ ;; memory.init (module (memory i64 1) - (data "\aa\bb\cc\dd") + (data passive "\aa\bb\cc\dd") (func (export "init") (param i64 i32 i32) (memory.init 0 @@ -152,8 +152,8 @@ ;; data.drop (module (memory i64 1) - (data "") - (data (i64.const 0) "") + (data passive "") + (data (i32.const 0) "") (func (export "drop_passive") (data.drop 0)) (func (export "init_passive") diff -Nru binaryen-108/test/spec/bulk-memory.wast binaryen-99/test/spec/bulk-memory.wast --- binaryen-108/test/spec/bulk-memory.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/bulk-memory.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ ;; Passive segment syntax (module (memory 1) - (data "foo")) + (data passive "foo")) ;; memory.fill (module @@ -112,7 +112,7 @@ ;; memory.init (module (memory 1) - (data "\aa\bb\cc\dd") + (data passive "\aa\bb\cc\dd") (func (export "init") (param i32 i32 i32) (memory.init 0 @@ -152,7 +152,7 @@ ;; data.drop (module (memory 1) - (data "") + (data passive "") (data (i32.const 0) "") (func (export "drop_passive") (data.drop 0)) diff -Nru binaryen-108/test/spec/call_indirect_refnull.wast binaryen-99/test/spec/call_indirect_refnull.wast --- binaryen-108/test/spec/call_indirect_refnull.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/call_indirect_refnull.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -(module - (table $t 1 1 funcref) - (elem (table $t) (i32.const 0) funcref (ref.null func)) - - (func $call-refnull (export "call-refnull") (result f32) - (call_indirect (result f32) (i32.const 0)) - ) -) -(assert_trap - (invoke "call-refnull") - "uninitialized table element" -) \ No newline at end of file diff -Nru binaryen-108/test/spec/call_indirect_sig_mismatch.wast binaryen-99/test/spec/call_indirect_sig_mismatch.wast --- binaryen-108/test/spec/call_indirect_sig_mismatch.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/call_indirect_sig_mismatch.wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,7 +2,7 @@ (type $funcref_=>_none (func (param funcref))) (table funcref (elem $callee)) (export "sig_mismatch" (func $sig_mismatch)) - (func $callee (param $0 externref)) + (func $callee (param $0 exnref)) (func $sig_mismatch (call_indirect (type $funcref_=>_none) (ref.null func) diff -Nru binaryen-108/test/spec/call_ref.wast binaryen-99/test/spec/call_ref.wast --- binaryen-108/test/spec/call_ref.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/call_ref.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -(module - (type $ii (func (param i32) (result i32))) - - (func $apply (param $f (ref $ii)) (param $x i32) (result i32) - (call_ref (local.get $x) (local.get $f)) - ) - - (func $f (type $ii) (i32.mul (local.get 0) (local.get 0))) - (func $g (type $ii) (i32.sub (i32.const 0) (local.get 0))) - - (elem declare func $f $g) - - (func (export "run") (param $x i32) (result i32) - (local $rf (ref null $ii)) - (local $rg (ref null $ii)) - (local.set $rf (ref.func $f)) - (local.set $rg (ref.func $g)) - (call_ref (call_ref (local.get $x) (local.get $rf)) (local.get $rg)) - ) - - (func (export "null") (result i32) - (call_ref (i32.const 1) (ref.null $ii)) - ) - - ;; Recursion - - (type $ll (func (param i64) (result i64))) - (type $lll (func (param i64 i64) (result i64))) - - (elem declare func $fac) - (global $fac (ref $ll) (ref.func $fac)) - - (func $fac (export "fac") (type $ll) - (if (result i64) (i64.eqz (local.get 0)) - (then (i64.const 1)) - (else - (i64.mul - (local.get 0) - (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $fac)) - ) - ) - ) - ) - - (elem declare func $fac-acc) - (global $fac-acc (ref $lll) (ref.func $fac-acc)) - - (func $fac-acc (export "fac-acc") (type $lll) - (if (result i64) (i64.eqz (local.get 0)) - (then (local.get 1)) - (else - (call_ref - (i64.sub (local.get 0) (i64.const 1)) - (i64.mul (local.get 0) (local.get 1)) - (global.get $fac-acc) - ) - ) - ) - ) - - (elem declare func $fib) - (global $fib (ref $ll) (ref.func $fib)) - - (func $fib (export "fib") (type $ll) - (if (result i64) (i64.le_u (local.get 0) (i64.const 1)) - (then (i64.const 1)) - (else - (i64.add - (call_ref (i64.sub (local.get 0) (i64.const 2)) (global.get $fib)) - (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $fib)) - ) - ) - ) - ) - - (elem declare func $even $odd) - (global $even (ref $ll) (ref.func $even)) - (global $odd (ref $ll) (ref.func $odd)) - - (func $even (export "even") (type $ll) - (if (result i64) (i64.eqz (local.get 0)) - (then (i64.const 44)) - (else (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $odd))) - ) - ) - (func $odd (export "odd") (type $ll) - (if (result i64) (i64.eqz (local.get 0)) - (then (i64.const 99)) - (else (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $even))) - ) - ) -) - -(assert_return (invoke "run" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "run" (i32.const 3)) (i32.const -9)) - -(assert_trap (invoke "null") "null function") - -(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) -(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) -(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) -(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) -(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) -(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) -(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) -(assert_return - (invoke "fac-acc" (i64.const 25) (i64.const 1)) - (i64.const 7034535277573963776) -) - -(assert_return (invoke "fib" (i64.const 0)) (i64.const 1)) -(assert_return (invoke "fib" (i64.const 1)) (i64.const 1)) -(assert_return (invoke "fib" (i64.const 2)) (i64.const 2)) -(assert_return (invoke "fib" (i64.const 5)) (i64.const 8)) -(assert_return (invoke "fib" (i64.const 20)) (i64.const 10946)) - -(assert_return (invoke "even" (i64.const 0)) (i64.const 44)) -(assert_return (invoke "even" (i64.const 1)) (i64.const 99)) -(assert_return (invoke "even" (i64.const 100)) (i64.const 44)) -(assert_return (invoke "even" (i64.const 77)) (i64.const 99)) -(assert_return (invoke "odd" (i64.const 0)) (i64.const 99)) -(assert_return (invoke "odd" (i64.const 1)) (i64.const 44)) -(assert_return (invoke "odd" (i64.const 200)) (i64.const 99)) -(assert_return (invoke "odd" (i64.const 77)) (i64.const 44)) - - - -(assert_invalid - (module - (func $f (param $r externref) - (call_ref (local.get $r)) - ) - ) - "type mismatch" -) diff -Nru binaryen-108/test/spec/data.wast binaryen-99/test/spec/data.wast --- binaryen-108/test/spec/data.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/data.wast 2021-01-07 20:01:06.000000000 +0000 @@ -8,26 +8,14 @@ (data (i32.const 1) "a" "" "bcd") (data (offset (i32.const 0))) (data (offset (i32.const 0)) "" "a" "bc" "") - (data (memory 0) (i32.const 0)) - (data (memory 0x0) (i32.const 1) "a" "" "bcd") - (data (memory 0x000) (offset (i32.const 0))) - (data (memory 0) (offset (i32.const 0)) "" "a" "bc" "") - (data (memory $m) (i32.const 0)) - (data (memory $m) (i32.const 1) "a" "" "bcd") - (data (memory $m) (offset (i32.const 0))) - (data (memory $m) (offset (i32.const 0)) "" "a" "bc" "") - (data $d1 (i32.const 0)) - (data $d2 (i32.const 1) "a" "" "bcd") - (data $d3 (offset (i32.const 0))) - (data $d4 (offset (i32.const 0)) "" "a" "bc" "") - (data $d5 (memory 0) (i32.const 0)) - (data $d6 (memory 0x0) (i32.const 1) "a" "" "bcd") - (data $d7 (memory 0x000) (offset (i32.const 0))) - (data $d8 (memory 0) (offset (i32.const 0)) "" "a" "bc" "") - (data $d9 (memory $m) (i32.const 0)) - (data $d10 (memory $m) (i32.const 1) "a" "" "bcd") - (data $d11 (memory $m) (offset (i32.const 0))) - (data $d12 (memory $m) (offset (i32.const 0)) "" "a" "bc" "") + (data 0 (i32.const 0)) + (data 0x0 (i32.const 1) "a" "" "bcd") + (data 0x000 (offset (i32.const 0))) + (data 0 (offset (i32.const 0)) "" "a" "bc" "") + (data $m (i32.const 0)) + (data $m (i32.const 1) "a" "" "bcd") + (data $m (offset (i32.const 0))) + (data $m (offset (i32.const 0)) "" "a" "bc" "") ) ;; Basic use @@ -136,76 +124,78 @@ (data (i32.const 0) "" "") ) -;; (module -;; (import "spectest" "memory" (memory 0)) -;; (data (i32.const 0) "a") -;; ) +(module + (import "spectest" "memory" (memory 0)) + (data (i32.const 0) "a") +) -;; (module -;; (import "spectest" "memory" (memory 0 3)) -;; (data (i32.const 0) "a") -;; ) +(module + (import "spectest" "memory" (memory 0 3)) + (data (i32.const 0) "a") +) -;; (module -;; (global (import "spectest" "global_i32") i32) -;; (import "spectest" "memory" (memory 0)) -;; (data (global.get 0) "a") -;; ) +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 0)) + (data (global.get 0) "a") +) -;; (module -;; (global (import "spectest" "global_i32") i32) -;; (import "spectest" "memory" (memory 0 3)) -;; (data (global.get 0) "a") -;; ) +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 0 3)) + (data (global.get 0) "a") +) -;; (module -;; (import "spectest" "memory" (memory 0)) -;; (data (i32.const 1) "a") -;; ) +(module + (import "spectest" "memory" (memory 0)) + (data (i32.const 1) "a") +) -;; (module -;; (import "spectest" "memory" (memory 0 3)) -;; (data (i32.const 1) "a") -;; ) +(module + (import "spectest" "memory" (memory 0 3)) + (data (i32.const 1) "a") +) ;; Invalid bounds for data -(assert_trap +(assert_unlinkable (module (memory 0) (data (i32.const 0) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 0 0) (data (i32.const 0) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 0 1) (data (i32.const 0) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap + +(assert_unlinkable (module (memory 0) (data (i32.const 1)) ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap + +(assert_unlinkable (module (memory 0 1) (data (i32.const 1)) ) - "out of bounds memory access" + "data segment does not fit" ) ;; This seems to cause a time-out on Travis. @@ -214,77 +204,77 @@ (memory 0x10000) (data (i32.const 0xffffffff) "ab") ) - "" ;; either out of memory or out of bounds + "" ;; either out of memory or segment does not fit ;) -(assert_trap +(assert_unlinkable (module (global (import "spectest" "global_i32") i32) (memory 0) (data (global.get 0) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 1 2) (data (i32.const 0x1_0000) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (import "spectest" "memory" (memory 1)) (data (i32.const 0x1_0000) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 2) (data (i32.const 0x2_0000) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 2 3) (data (i32.const 0x2_0000) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 1) (data (i32.const -1) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (import "spectest" "memory" (memory 1)) (data (i32.const -1) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (memory 2) (data (i32.const -100) "a") ) - "out of bounds memory access" + "data segment does not fit" ) -(assert_trap +(assert_unlinkable (module (import "spectest" "memory" (memory 1)) (data (i32.const -100) "a") ) - "out of bounds memory access" + "data segment does not fit" ) ;; Data without memory @@ -296,82 +286,6 @@ "unknown memory" ) -;; Data segment with memory index 1 (only memory 0 available) -(assert_invalid - (module binary - "\00asm" "\01\00\00\00" - "\05\03\01" ;; memory section - "\00\00" ;; memory 0 - "\0b\07\01" ;; data section - "\02\01\41\00\0b" ;; active data segment 0 for memory 1 - "\00" ;; empty vec(byte) - ) - "unknown memory 1" -) - -;; Data segment with memory index 0 (no memory section) -(assert_invalid - (module binary - "\00asm" "\01\00\00\00" - "\0b\06\01" ;; data section - "\00\41\00\0b" ;; active data segment 0 for memory 0 - "\00" ;; empty vec(byte) - ) - "unknown memory 0" -) - -;; Data segment with memory index 1 (no memory section) -(assert_invalid - (module binary - "\00asm" "\01\00\00\00" - "\0b\07\01" ;; data section - "\02\01\41\00\0b" ;; active data segment 0 for memory 1 - "\00" ;; empty vec(byte) - ) - "unknown memory 1" -) - -;; Data segment with memory index 1 and vec(byte) as above, -;; only memory 0 available. -(assert_invalid - (module binary - "\00asm" "\01\00\00\00" - "\05\03\01" ;; memory section - "\00\00" ;; memory 0 - "\0b\45\01" ;; data section - "\02" ;; active segment - "\01" ;; memory index - "\41\00\0b" ;; offset constant expression - "\3e" ;; vec(byte) length - "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f" - "\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" - "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f" - "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d" - ) - "unknown memory 1" -) - -;; Data segment with memory index 1 and specially crafted vec(byte) after. -;; This is to detect incorrect validation where memory index is interpreted -;; as a flag followed by "\41" interpreted as the size of vec(byte) -;; with the expected number of bytes following. -(assert_invalid - (module binary - "\00asm" "\01\00\00\00" - "\0b\45\01" ;; data section - "\02" ;; active segment - "\01" ;; memory index - "\41\00\0b" ;; offset constant expression - "\3e" ;; vec(byte) length - "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f" - "\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" - "\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f" - "\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d" - ) - "unknown memory 1" -) - - ;; Invalid offsets (assert_invalid @@ -383,40 +297,6 @@ ) (assert_invalid - (module - (memory 1) - (data (offset (;empty instruction sequence;))) - ) - "type mismatch" -) - -(assert_invalid - (module - (memory 1) - (data (offset (i32.const 0) (i32.const 0))) - ) - "type mismatch" -) - -(assert_invalid - (module - (global (import "test" "global-i32") i32) - (memory 1) - (data (offset (global.get 0) (global.get 0))) - ) - "type mismatch" -) - -(assert_invalid - (module - (global (import "test" "global-i32") i32) - (memory 1) - (data (offset (global.get 0) (i32.const 0))) - ) - "type mismatch" -) - -(assert_invalid (module (memory 1) (data (i32.ctz (i32.const 0))) @@ -453,29 +333,3 @@ ;; (module (memory 1) (data (global.get $g)) (global $g (mut i32) (i32.const 0))) ;; "constant expression required" ;; ) - -(assert_invalid - (module - (memory 1) - (data (global.get 0)) - ) - "unknown global 0" -) - -(assert_invalid - (module - (global (import "test" "global-i32") i32) - (memory 1) - (data (global.get 1)) - ) - "unknown global 1" -) - -(assert_invalid - (module - (global (import "test" "global-mut-i32") (mut i32)) - (memory 1) - (data (global.get 0)) - ) - "constant expression required" -) \ No newline at end of file diff -Nru binaryen-108/test/spec/elem_reftypes.wast binaryen-99/test/spec/elem_reftypes.wast --- binaryen-108/test/spec/elem_reftypes.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/elem_reftypes.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,263 +0,0 @@ -;; Test the element section - -;; Syntax -(module - (table $t 10 funcref) - (func $f) - (func $g) - - ;; Passive - (elem funcref) - (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null func)) (ref.func $g)) - (elem func) - (elem func $f $f $g $g) - - (elem $p1 funcref) - (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) - (elem $p3 func) - (elem $p4 func $f $f $g $g) - - ;; Active - (elem (table $t) (i32.const 0) funcref) - (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) - (elem (table $t) (i32.const 0) func) - (elem (table $t) (i32.const 0) func $f $g) - (elem (table $t) (offset (i32.const 0)) funcref) - (elem (table $t) (offset (i32.const 0)) func $f $g) - (elem (table 0) (i32.const 0) func) - ;; (elem (table 0x0) (i32.const 0) func $f $f) - ;; (elem (table 0x000) (offset (i32.const 0)) func) - (elem (table 0) (offset (i32.const 0)) func $f $f) - (elem (table $t) (i32.const 0) func) - (elem (table $t) (i32.const 0) func $f $f) - (elem (table $t) (offset (i32.const 0)) func) - (elem (table $t) (offset (i32.const 0)) func $f $f) - (elem (offset (i32.const 0))) - (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) - (elem (offset (i32.const 0)) func $f $f) - (elem (offset (i32.const 0)) $f $f) - (elem (i32.const 0)) - (elem (i32.const 0) funcref (ref.func $f) (ref.null func)) - (elem (i32.const 0) func $f $f) - (elem (i32.const 0) $f $f) - - (elem $a1 (table $t) (i32.const 0) funcref) - (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) - (elem $a3 (table $t) (i32.const 0) func) - (elem $a4 (table $t) (i32.const 0) func $f $g) - (elem $a9 (table $t) (offset (i32.const 0)) funcref) - (elem $a10 (table $t) (offset (i32.const 0)) func $f $g) - (elem $a11 (table 0) (i32.const 0) func) - ;; (elem $a12 (table 0x0) (i32.const 0) func $f $f) - ;; (elem $a13 (table 0x000) (offset (i32.const 0)) func) - (elem $a14 (table 0) (offset (i32.const 0)) func $f $f) - (elem $a15 (table $t) (i32.const 0) func) - (elem $a16 (table $t) (i32.const 0) func $f $f) - (elem $a17 (table $t) (offset (i32.const 0)) func) - (elem $a18 (table $t) (offset (i32.const 0)) func $f $f) - (elem $a19 (offset (i32.const 0))) - (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) - (elem $a21 (offset (i32.const 0)) func $f $f) - (elem $a22 (offset (i32.const 0)) $f $f) - (elem $a23 (i32.const 0)) - (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null func)) - (elem $a25 (i32.const 0) func $f $f) - (elem $a26 (i32.const 0) $f $f) - - ;; Declarative - (elem declare funcref) - (elem declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) - (elem declare func) - (elem declare func $f $f $g $g) - - (elem $d1 declare funcref) - (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) - (elem $d3 declare func) - (elem $d4 declare func $f $f $g $g) -) - -(module - (func $f) - (func $g) - - (table $t1 funcref (elem (ref.func $f) (ref.null func) (ref.func $g))) - (table $t2 (ref null func) (elem (ref.func $f) (ref.null func) (ref.func $g))) -) - - -;; Basic use - -(module - (table 10 funcref) - (func $f) - (elem (i32.const 0) $f) -) -(module - (import "spectest" "table" (table 10 funcref)) - (func $f) - (elem (i32.const 0) $f) -) - -(module - (table 10 funcref) - (func $f) - (elem (i32.const 0) $f) - (elem (i32.const 3) $f) - (elem (i32.const 7) $f) - (elem (i32.const 5) $f) - (elem (i32.const 3) $f) -) -(module - (import "spectest" "table" (table 10 funcref)) - (func $f) - (elem (i32.const 9) $f) - (elem (i32.const 3) $f) - (elem (i32.const 7) $f) - (elem (i32.const 3) $f) - (elem (i32.const 5) $f) -) - -(module - (global (import "spectest" "global_i32") i32) - (table 1000 funcref) - (func $f) - (elem (global.get 0) $f) -) - -(module - (global $g (import "spectest" "global_i32") i32) - (table 1000 funcref) - (func $f) - (elem (global.get $g) $f) -) - -(module - (type $out-i32 (func (result i32))) - (table 10 funcref) - (elem (i32.const 7) $const-i32-a) - (elem (i32.const 9) $const-i32-b) - (func $const-i32-a (type $out-i32) (i32.const 65)) - (func $const-i32-b (type $out-i32) (i32.const 66)) - (func (export "call-7") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 7)) - ) - (func (export "call-9") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 9)) - ) -) -(assert_return (invoke "call-7") (i32.const 65)) -(assert_return (invoke "call-9") (i32.const 66)) - -;; Corner cases - -(module - (table 10 funcref) - (func $f) - (elem (i32.const 9) $f) -) -(module - (import "spectest" "table" (table 10 funcref)) - (func $f) - (elem (i32.const 9) $f) -) - -(module - (table 0 funcref) - (elem (i32.const 0)) -) -(module - (import "spectest" "table" (table 0 funcref)) - (elem (i32.const 0)) -) - -(module - (table 0 0 funcref) - (elem (i32.const 0)) -) - -(module - (table 20 funcref) - (elem (i32.const 20)) -) - -;;; We cannot enable these yet since we check table bounds at validation stage, -;;; which is incorrect for imported tables. -;; (module -;; (import "spectest" "table" (table 0 funcref)) -;; (func $f) -;; (elem (i32.const 0) $f) -;; ) - -;; (module -;; (import "spectest" "table" (table 0 100 funcref)) -;; (func $f) -;; (elem (i32.const 0) $f) -;; ) - -;; (module -;; (import "spectest" "table" (table 0 funcref)) -;; (func $f) -;; (elem (i32.const 1) $f) -;; ) - -;; (module -;; (import "spectest" "table" (table 0 30 funcref)) -;; (func $f) -;; (elem (i32.const 1) $f) -;; ) - -;; Two elements target the same slot - -(module - (type $out-i32 (func (result i32))) - (table 10 funcref) - (elem (i32.const 9) $const-i32-a) - (elem (i32.const 9) $const-i32-b) - (func $const-i32-a (type $out-i32) (i32.const 65)) - (func $const-i32-b (type $out-i32) (i32.const 66)) - (func (export "call-overwritten") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 9)) - ) -) -(assert_return (invoke "call-overwritten") (i32.const 66)) - -(module - (type $out-i32 (func (result i32))) - (import "spectest" "table" (table 10 funcref)) - (elem (i32.const 9) $const-i32-a) - (elem (i32.const 9) $const-i32-b) - (func $const-i32-a (type $out-i32) (i32.const 65)) - (func $const-i32-b (type $out-i32) (i32.const 66)) - (func (export "call-overwritten-element") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 9)) - ) -) -(assert_return (invoke "call-overwritten-element") (i32.const 66)) - -;; Element sections across multiple modules change the same table - -(module $module1 - (type $out-i32 (func (result i32))) - (table (export "shared-table") 10 funcref) - (elem (i32.const 8) $const-i32-a) - (elem (i32.const 9) $const-i32-b) - (func $const-i32-a (type $out-i32) (i32.const 65)) - (func $const-i32-b (type $out-i32) (i32.const 66)) - (func (export "call-7") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 7)) - ) - (func (export "call-8") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 8)) - ) - (func (export "call-9") (type $out-i32) - (call_indirect (type $out-i32) (i32.const 9)) - ) -) - -(assert_invalid - (module - (type $none_=>_none (func)) - (table 0 (ref null $none_=>_none)) - (elem (i32.const 0) funcref) - ) -) \ No newline at end of file diff -Nru binaryen-108/test/spec/elem.wast binaryen-99/test/spec/elem.wast --- binaryen-108/test/spec/elem.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/elem.wast 2021-01-07 20:01:06.000000000 +0000 @@ -8,10 +8,10 @@ (elem (i32.const 0) $f $f) (elem (offset (i32.const 0))) (elem (offset (i32.const 0)) $f $f) - (elem (i32.const 0)) + (elem 0 (i32.const 0)) (elem 0x0 (i32.const 0) $f $f) (elem 0x000 (offset (i32.const 0))) - (elem (offset (i32.const 0)) $f $f) + (elem 0 (offset (i32.const 0)) $f $f) (elem $t (i32.const 0)) (elem $t (i32.const 0) $f $f) (elem $t (offset (i32.const 0))) diff -Nru binaryen-108/test/spec/events.wast binaryen-99/test/spec/events.wast --- binaryen-108/test/spec/events.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/spec/events.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,33 @@ +;; Test events + +(module + (event (attr 0) (param i32)) + (event $e (attr 0) (param i32 f32)) + + (event $e-params0 (attr 0) (param i32 f32)) + (event $e-params1 (attr 0) (param i32) (param f32)) + + (event $e-export (export "ex0") (attr 0) (param i32)) + (event $e-import (import "env" "im0") (attr 0) (param i32)) + + (import "env" "im1" (event (attr 0) (param i32 f32))) + (export "ex1" (event $e)) +) + +(assert_invalid + (module (event $e (attr 0) (param i32) (result i32))) + "Event type's result type should be none" +) + +(assert_invalid + (module (event $e (attr 1) (param i32))) + "Currently only attribute 0 is supported" +) + +(assert_invalid + (module + (type $t (param i32)) + (event $e (attr 0) (type $t) (param i32 f32)) + ) + "type and param don't match" +) diff -Nru binaryen-108/test/spec/exception-handling.wast binaryen-99/test/spec/exception-handling.wast --- binaryen-108/test/spec/exception-handling.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/exception-handling.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,7 @@ (module - (tag $e-v) - (tag $e-i32 (param i32)) - (tag $e-f32 (param f32)) - (tag $e-i32-f32 (param i32 f32)) + (event $e-v (attr 0)) + (event $e-i32 (attr 0) (param i32)) + (event $e-i32-f32 (attr 0) (param i32 f32)) (func $throw_single_value (export "throw_single_value") (throw $e-i32 (i32.const 5)) @@ -12,13 +11,17 @@ (throw $e-i32-f32 (i32.const 3) (f32.const 3.5)) ) + (func (export "rethrow_null") + (rethrow (ref.null exn)) + ) + (func (export "try_nothrow") (result i32) (try (result i32) (do (i32.const 3) ) - (catch $e-i32 - (drop (pop i32)) + (catch + (drop (pop exnref)) (i32.const 0) ) ) @@ -29,35 +32,8 @@ (do (throw $e-i32 (i32.const 5)) ) - (catch $e-i32 - (drop (pop i32)) - (i32.const 3) - ) - ) - ) - - (func (export "try_throw_nocatch") (result i32) - (try (result i32) - (do - (throw $e-i32 (i32.const 5)) - ) - (catch $e-f32 - (drop (pop f32)) - (i32.const 3) - ) - ) - ) - - (func (export "try_throw_catchall") (result i32) - (try (result i32) - (do - (throw $e-i32 (i32.const 5)) - ) - (catch $e-f32 - (drop (pop f32)) - (i32.const 4) - ) - (catch_all + (catch + (drop (pop exnref)) (i32.const 3) ) ) @@ -69,248 +45,165 @@ (call $throw_single_value) (unreachable) ) - (catch $e-i32 - (pop i32) - ) - ) - ) - - (func (export "try_throw_multivalue_catch") (result i32) (local $x (i32 f32)) - (try (result i32) - (do - (throw $e-i32-f32 (i32.const 5) (f32.const 1.5)) - ) - (catch $e-i32-f32 - (local.set $x - (pop i32 f32) - ) - (tuple.extract 0 - (local.get $x) - ) + (catch + (drop (pop exnref)) + (i32.const 3) ) ) ) (func (export "try_throw_rethrow") - (try $l0 + (try (do (throw $e-i32 (i32.const 5)) ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l0) + (catch + (rethrow (pop exnref)) ) ) ) - (func (export "try_call_rethrow") - (try $l0 + (func $try_call_rethrow (export "try_call_rethrow") + (try (do (call $throw_single_value) ) - (catch_all - (rethrow $l0) + (catch + (rethrow (pop exnref)) ) ) ) - (func (export "rethrow_target_test1") (result i32) - (try (result i32) - (do - (try - (do - (throw $e-i32 (i32.const 1)) - ) - (catch_all - (try $l0 - (do - (throw $e-i32 (i32.const 2)) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l0) ;; rethrow (i32.const 2) - ) - ) - ) - ) - ) - (catch $e-i32 - (pop i32) ;; result is (i32.const 2) + (func (export "br_on_exn_null") (result i32) + (block $l0 (result i32) + (drop + (br_on_exn $l0 $e-i32 (ref.null exn)) ) + (i32.const 0) ) ) - ;; Can we handle rethrows with the depth > 0? - (func (export "rethrow_target_test2") (result i32) - (try (result i32) + (func (export "br_on_exn_match_no_value") (local $exn exnref) + (try (do - (try $l0 - (do - (throw $e-i32 (i32.const 1)) - ) - (catch_all - (try - (do - (throw $e-i32 (i32.const 2)) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow 1) ;; rethrow (i32.const 1) - ) - ) + (throw $e-v) + ) + (catch + (local.set $exn (pop exnref)) + (block $l0 + (rethrow + (br_on_exn $l0 $e-v (local.get $exn)) ) ) ) - (catch $e-i32 - (pop i32) ;; result is (i32.const 1) - ) ) ) - ;; Tests whether the exception stack is managed correctly after rethrows - (func (export "rethrow_target_test3") (result i32) + (func (export "br_on_exn_match_single_value") (result i32) (local $exn exnref) (try (result i32) (do - (try $l0 - (do - (try $l1 - (do - (throw $e-i32 (i32.const 1)) - ) - (catch_all - (try - (do - (throw $e-i32 (i32.const 2)) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l1) ;; rethrow (i32.const 1) - ) - ) - ) - ) - ) - (catch $e-i32 - (drop (pop i32)) - (rethrow $l0) ;; rethrow (i32.const 1) again + (throw $e-i32 (i32.const 5)) + ) + (catch + (local.set $exn (pop exnref)) + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e-i32 (local.get $exn)) ) ) ) - (catch $e-i32 - (pop i32) ;; result is (i32.const 1) - ) ) ) - (func (export "try_delegate_caught") (result i32) - (try $l0 (result i32) + (func (export "br_on_exn_match_multiple_values") (result i32 f32) + (local $exn exnref) + (try (result i32 f32) (do - (try (result i32) - (do - (try (result i32) - (do - (throw $e-i32 (i32.const 3)) - ) - (delegate $l0) - ) - ) - (catch_all - (i32.const 0) + (throw $e-i32-f32 (i32.const 3) (f32.const 3.5)) + ) + (catch + (local.set $exn (pop exnref)) + (block $l0 (result i32 f32) + (rethrow + (br_on_exn $l0 $e-i32-f32 (local.get $exn)) ) ) ) - (catch $e-i32 - (pop i32) - ) ) ) - (func (export "try_delegate_to_catchless_try") (result i32) - (try $l0 (result i32) + (func (export "br_on_exn_dont_match") (local $exn exnref) + (try (do - (try (result i32) - (do - (try (result i32) - (do - (throw $e-i32 (i32.const 3)) - ) - (delegate $l0) - ) - ) - (catch_all - (i32.const 0) + (throw $e-i32 (i32.const 5)) + ) + (catch + (local.set $exn (pop exnref)) + (block $l0 + (rethrow + (br_on_exn $l0 $e-v (local.get $exn)) ) ) ) ) ) - (func (export "try_delegate_to_delegate") (result i32) - (try $l0 (result i32) + (func (export "call_br_on_exn") (result i32) (local $exn exnref) + (try (result i32) (do - (try $l1 (result i32) - (do - (try (result i32) - (do - (throw $e-i32 (i32.const 3)) - ) - (delegate $l1) - ) + (call $throw_single_value) + (unreachable) + ) + (catch + (local.set $exn (pop exnref)) + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e-i32 (local.get $exn)) ) - (delegate $l0) ) ) - (catch $e-i32 - (pop i32) - ) ) ) - (func (export "try_delegate_to_caller") - (try $l0 + (func (export "call_rethrow_br_on_exn") (result i32) (local $exn exnref) + (try (result i32) (do - (try $l1 - (do - (try - (do - (throw $e-i32 (i32.const 3)) - ) - (delegate 2) ;; to caller - ) + (call $try_call_rethrow) + (unreachable) + ) + (catch + (local.set $exn (pop exnref)) + (block $l0 (result i32) + (rethrow + (br_on_exn $l0 $e-i32 (local.get $exn)) ) ) ) - (catch_all) ) ) ) (assert_trap (invoke "throw_single_value")) (assert_trap (invoke "throw_multiple_values")) +(assert_trap (invoke "rethrow_null")) (assert_return (invoke "try_nothrow") (i32.const 3)) (assert_return (invoke "try_throw_catch") (i32.const 3)) -(assert_trap (invoke "try_throw_nocatch")) -(assert_return (invoke "try_throw_catchall") (i32.const 3)) -(assert_return (invoke "try_call_catch") (i32.const 5)) -(assert_return (invoke "try_throw_multivalue_catch") (i32.const 5)) +(assert_return (invoke "try_call_catch") (i32.const 3)) (assert_trap (invoke "try_throw_rethrow")) (assert_trap (invoke "try_call_rethrow")) -(assert_return (invoke "rethrow_target_test1") (i32.const 2)) -(assert_return (invoke "rethrow_target_test2") (i32.const 1)) -(assert_return (invoke "rethrow_target_test3") (i32.const 1)) -(assert_return (invoke "try_delegate_caught") (i32.const 3)) -(assert_trap (invoke "try_delegate_to_catchless_try")) -(assert_return (invoke "try_delegate_to_delegate") (i32.const 3)) -(assert_trap (invoke "try_delegate_to_caller")) +(assert_trap (invoke "br_on_exn_null")) +(assert_return (invoke "br_on_exn_match_no_value")) +(assert_return (invoke "br_on_exn_match_single_value") (i32.const 5)) +(assert_return (invoke "br_on_exn_match_multiple_values") (tuple.make (i32.const 3) (f32.const 3.5))) +(assert_trap (invoke "br_on_exn_dont_match")) +(assert_return (invoke "call_rethrow_br_on_exn") (i32.const 5)) (assert_invalid (module (func $f0 (try (do (nop)) - (catch $e-i32 - (pop i32) - ) + (catch (i32.const 0)) ) ) ) @@ -319,299 +212,85 @@ (assert_invalid (module - (tag $e-i32 (param i32)) (func $f0 (try (do (i32.const 0)) - (catch $e-i32 - (pop i32) - ) + (catch (i32.const 0)) ) ) ) - "try's type does not match try body's type" + "try's type does not match try body's type" ) (assert_invalid (module - (tag $e-i32 (param i32)) + (event $e-i32 (attr 0) (param i32)) (func $f0 (throw $e-i32 (f32.const 0)) ) ) - "tag param types must match" + "event param types must match" ) (assert_invalid (module - (tag $e-i32 (param i32 f32)) + (event $e-i32 (attr 0) (param i32 f32)) (func $f0 (throw $e-i32 (f32.const 0)) ) ) - "tag's param numbers must match" -) - -(assert_invalid - (module - (func $f0 - (block $l0 - (try - (do - (try - (do) - (delegate $l0) ;; target is a block - ) - ) - (catch_all) - ) - ) - ) - ) - "all delegate targets must be valid" + "event's param numbers must match" ) (assert_invalid (module (func $f0 - (try $l0 - (do) - (catch_all - (try - (do) - (delegate $l0) ;; the target catch is above the delegate - ) - ) - ) + (rethrow (i32.const 0)) ) ) - "all delegate targets must be valid" -) - -(assert_invalid - (module - (func $f0 - (block $l0 - (try - (do) - (catch_all - (rethrow $l0) ;; target is a block - ) - ) - ) - ) - ) - "all rethrow targets must be valid" -) - -(assert_invalid - (module - (func $f0 - (try $l0 - (do - (rethrow $l0) ;; Not within the target try's catch - ) - (catch_all) - ) - ) - ) - "all rethrow targets must be valid" -) - -(assert_invalid - (module - (func $f0 - (try - (do) - (catch $e) - ) - ) - ) - "catch's tag name is invalid: e" -) - -(assert_invalid - (module - (tag $e-none (param)) - (func $f0 (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch $e-none - (pop i32) - ) - ) - ) - ) - "catch's tag (e-none) doesn't have any params, but there are pops" -) - -(assert_invalid - (module - (tag $e-i32 (param i32)) - (func $f0 - (try - (do) - (catch $e-i32) - ) - ) - ) - "catch's tag (e-i32) has params, so there should be a single pop within the catch body" -) - -(assert_invalid - (module - (tag $e-i32 (param i32)) - (func $f0 - (try - (do) - (catch $e-i32 - (drop - (pop i32) - ) - (drop - (pop i32) - ) - ) - ) - ) - ) - "catch's tag (e-i32) has params, so there should be a single pop within the catch body" + "rethrow's argument must be exnref type" ) (assert_invalid (module + (event $e-i32 (attr 0) (param i32)) (func $f0 (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch_all - (pop i32) - ) - ) - ) - ) - "catch_all's body should not have pops" -) - -(assert_invalid - (module - (tag $e-i32 (param i32)) - (func $f0 (result f32) - (try (result f32) - (do - (f32.const 0) - ) - (catch $e-i32 - (pop f32) - ) - ) - ) - ) - "catch's tag (e-i32)'s pop doesn't have the same type as the tag's params" -) - -(assert_invalid - (module - (tag $e-i32 (param i32)) - (func $f0 (result i32) - (try (result i32) - (do - (i32.const 0) - ) - (catch $e-i32 - (drop - (i32.const 0) - ) - (pop i32) ;; Not the first children within 'catch' - ) - ) - ) - ) - "catch's body (e-i32)'s pop's location is not valid" -) - -(assert_invalid - (module - (tag $e-i32 (param i32)) - (func $f0 - (try - (do) - (catch $e-i32 - (throw $e-i32 - (block (result i32) - (pop i32) ;; pop is within a block - ) - ) - ) - ) - ) - ) - "catch's body (e-i32)'s pop's location is not valid" -) - -(assert_invalid - (module - (tag $e-i32 (param i32)) - (func $f0 - (try - (do) - (catch $e-i32 - (throw $e-i32 - (loop (result i32) - (pop i32) ;; pop is within a loop - ) - ) + (block $l0 (result i32) + (drop + (br_on_exn $l0 $e-i32 (i32.const 0)) ) + (i32.const 0) ) ) ) - "catch's body (e-i32)'s pop's location is not valid" + "br_on_exn's argument must be unreachable or exnref type" ) (assert_invalid (module - (tag $e-i32 (param i32)) - (func $f0 - (try - (do) - (catch $e-i32 - (throw $e-i32 - (try (result i32) - (do - (pop i32) ;; pop is within a try - ) - (catch_all - (i32.const 0) - ) - ) - ) + (event $e-i32 (attr 0) (param i32)) + (func $f0 (result i32) (local $0 exnref) + (block $l0 (result i32) + (i32.eqz + (br_on_exn $l0 $e-i32 (local.get $0)) ) ) ) ) - "catch's body (e-i32)'s pop's location is not valid" + "i32.eqz input must be i32" ) (assert_invalid (module - (tag $e-i32 (param i32)) - (func $f0 - (try - (do) - (catch $e-i32 - (throw $e-i32 - (if (result i32) - (i32.const 0) - (pop i32) ;; pop is within an if true body - (i32.const 3) - ) - ) + (event $e-i32 (attr 0) (param i32)) + (func $f0 (result f32) (local $0 exnref) + (block $l0 (result f32) + (drop + (br_on_exn $l0 $e-i32 (local.get $0)) ) + (f32.const 0) ) ) ) - "catch's body (e-i32)'s pop's location is not valid" + "block+breaks must have right type if breaks return a value" ) diff -Nru binaryen-108/test/spec/i31.wast binaryen-99/test/spec/i31.wast --- binaryen-108/test/spec/i31.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/i31.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -(module - (func (export "new") (param $i i32) (result (ref i31)) - (i31.new (local.get $i)) - ) - - (func (export "get_u") (param $i i32) (result i32) - (i31.get_u (i31.new (local.get $i))) - ) - (func (export "get_s") (param $i i32) (result i32) - (i31.get_s (i31.new (local.get $i))) - ) -) - -(assert_return (invoke "get_u" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "get_u" (i32.const 100)) (i32.const 100)) -(assert_return (invoke "get_u" (i32.const -1)) (i32.const 0x7fffffff)) -(assert_return (invoke "get_u" (i32.const 0x3fffffff)) (i32.const 0x3fffffff)) -(assert_return (invoke "get_u" (i32.const 0x40000000)) (i32.const 0x40000000)) -(assert_return (invoke "get_u" (i32.const 0x7fffffff)) (i32.const 0x7fffffff)) -(assert_return (invoke "get_u" (i32.const 0xaaaaaaaa)) (i32.const 0x2aaaaaaa)) -(assert_return (invoke "get_u" (i32.const 0xcaaaaaaa)) (i32.const 0x4aaaaaaa)) - -(assert_return (invoke "get_s" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "get_s" (i32.const 100)) (i32.const 100)) -(assert_return (invoke "get_s" (i32.const -1)) (i32.const -1)) -(assert_return (invoke "get_s" (i32.const 0x3fffffff)) (i32.const 0x3fffffff)) -(assert_return (invoke "get_s" (i32.const 0x40000000)) (i32.const -0x40000000)) -(assert_return (invoke "get_s" (i32.const 0x7fffffff)) (i32.const -1)) -(assert_return (invoke "get_s" (i32.const 0xaaaaaaaa)) (i32.const 0x2aaaaaaa)) -(assert_return (invoke "get_s" (i32.const 0xcaaaaaaa)) (i32.const 0xcaaaaaaa)) diff -Nru binaryen-108/test/spec/imports.wast binaryen-99/test/spec/imports.wast --- binaryen-108/test/spec/imports.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/imports.wast 2021-01-07 20:01:06.000000000 +0000 @@ -10,13 +10,9 @@ (func (export "func-i64->i64") (param i64) (result i64) (local.get 0)) (global (export "global-i32") i32 (i32.const 55)) (global (export "global-f32") f32 (f32.const 44)) - ;;; FIXME: Exporting a mutable global is currently not supported. Make mutable - ;;; when support is added. - (global (export "global-mut-i64") i64 (i64.const 66)) (table (export "table-10-inf") 10 funcref) - (table (export "table-10-20") 10 20 funcref) + ;; (table (export "table-10-20") 10 20 funcref) (memory (export "memory-2-inf") 2) - ;; Multiple memories are not yet supported ;; (memory (export "memory-2-4") 2 4) ) @@ -47,13 +43,10 @@ (func (export "p1") (import "spectest" "print_i32") (param i32)) (func $p (export "p2") (import "spectest" "print_i32") (param i32)) - (func (import "spectest" "print_i32") (param i32)) + (func (export "p3") (export "p4") (import "spectest" "print_i32") (param i32)) (func (export "p5") (import "spectest" "print_i32") (type 0)) (func (export "p6") (import "spectest" "print_i32") (type 0) (param i32) (result)) - ;; (export "p3" (func $print_i32)) - ;; (export "p4" (func $print_i32)) - (import "spectest" "print_i32" (func (type $forward))) (func (import "spectest" "print_i32") (type $forward)) (type $forward (func (param i32))) @@ -102,26 +95,6 @@ "unknown type" ) -;; Export sharing name with import -(module - (import "spectest" "print_i32" (func $imported_print (param i32))) - (func (export "print_i32") (param $i i32) - (call $imported_print (local.get $i)) - ) -) - -(assert_return (invoke "print_i32" (i32.const 13))) - -;; Export sharing name with import -(module - (import "spectest" "print_i32" (func $imported_print (param i32))) - (func (export "print_i32") (param $i i32) (param $j i32) (result i32) - (i32.add (local.get $i) (local.get $j)) - ) -) - -(assert_return (invoke "print_i32" (i32.const 5) (i32.const 11)) (i32.const 16)) - (module (import "test" "func" (func))) (module (import "test" "func-i32" (func (param i32)))) (module (import "test" "func-f32" (func (param f32)))) @@ -257,7 +230,6 @@ (module (import "test" "global-i32" (global i32))) (module (import "test" "global-f32" (global f32))) -(module (import "test" "global-mut-i64" (global (mut i64)))) (assert_unlinkable (module (import "test" "unknown" (global i32))) @@ -269,55 +241,6 @@ ) (assert_unlinkable - (module (import "test" "global-i32" (global i64))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-i32" (global f32))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-i32" (global f64))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-i32" (global (mut i32)))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-f32" (global i32))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-f32" (global i64))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-f32" (global f64))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-f32" (global (mut f32)))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-mut-i64" (global (mut i32)))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-mut-i64" (global (mut f32)))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-mut-i64" (global (mut f64)))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "global-mut-i64" (global i64))) - "incompatible import type" -) - -(assert_unlinkable (module (import "test" "func" (global i32))) "incompatible import type" ) @@ -347,11 +270,11 @@ (module (type (func (result i32))) - (import "spectest" "table" (table $tab 10 20 funcref)) - (elem (table $tab) (i32.const 1) func $f $g) + (import "spectest" "table" (table 10 20 funcref)) + (elem 0 (i32.const 1) $f $g) (func (export "call") (param i32) (result i32) - (call_indirect $tab (type 0) (local.get 0)) + (call_indirect (type 0) (local.get 0)) ) (func $f (result i32) (i32.const 11)) (func $g (result i32) (i32.const 22)) @@ -366,11 +289,11 @@ (module (type (func (result i32))) - (table $tab (import "spectest" "table") 10 20 funcref) - (elem (table $tab) (i32.const 1) func $f $g) + (table (import "spectest" "table") 10 20 funcref) + (elem 0 (i32.const 1) $f $g) (func (export "call") (param i32) (result i32) - (call_indirect $tab (type 0) (local.get 0)) + (call_indirect (type 0) (local.get 0)) ) (func $f (result i32) (i32.const 11)) (func $g (result i32) (i32.const 22)) @@ -383,25 +306,22 @@ (assert_trap (invoke "call" (i32.const 100)) "undefined element") -(module - (import "spectest" "table" (table 0 funcref)) - (import "spectest" "table" (table 0 funcref)) - (table 10 funcref) - (table 10 funcref) +(assert_invalid + (module (import "" "" (table 10 funcref)) (import "" "" (table 10 funcref))) + "multiple tables" +) +(assert_invalid + (module (import "" "" (table 10 funcref)) (table 10 funcref)) + "multiple tables" +) +(assert_invalid + (module (table 10 funcref) (table 10 funcref)) + "multiple tables" ) (module (import "test" "table-10-inf" (table 10 funcref))) (module (import "test" "table-10-inf" (table 5 funcref))) (module (import "test" "table-10-inf" (table 0 funcref))) -(module (import "test" "table-10-20" (table 10 funcref))) -(module (import "test" "table-10-20" (table 5 funcref))) -(module (import "test" "table-10-20" (table 0 funcref))) -(module (import "test" "table-10-20" (table 10 20 funcref))) -(module (import "test" "table-10-20" (table 5 20 funcref))) -(module (import "test" "table-10-20" (table 0 20 funcref))) -(module (import "test" "table-10-20" (table 10 25 funcref))) -(module (import "test" "table-10-20" (table 5 25 funcref))) -(module (import "test" "table-10-20" (table 0 25 funcref))) (module (import "spectest" "table" (table 10 funcref))) (module (import "spectest" "table" (table 5 funcref))) (module (import "spectest" "table" (table 0 funcref))) @@ -429,14 +349,6 @@ "incompatible import type" ) (assert_unlinkable - (module (import "test" "table-10-20" (table 12 20 funcref))) - "incompatible import type" -) -(assert_unlinkable - (module (import "test" "table-10-20" (table 10 18 funcref))) - "incompatible import type" -) -(assert_unlinkable (module (import "spectest" "table" (table 12 funcref))) "incompatible import type" ) @@ -468,7 +380,7 @@ (module (import "spectest" "memory" (memory 1 2)) - (data (memory 0) (i32.const 10) "\10") + (data 0 (i32.const 10) "\10") (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) ) @@ -480,7 +392,7 @@ (module (memory (import "spectest" "memory") 1 2) - (data (memory 0) (i32.const 10) "\10") + (data 0 (i32.const 10) "\10") (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) ) @@ -582,27 +494,6 @@ (assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) (assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) -(module $Mgm - (memory (export "memory") 1) ;; initial size is 1 - (func (export "grow") (result i32) (memory.grow (i32.const 1))) -) -(register "grown-memory" $Mgm) -(assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2 -(module $Mgim1 - ;; imported memory limits should match, because external memory size is 2 now - (memory (import "grown-memory" "memory") 2) - (export "memory" (memory 0)) - (func (export "grow") (result i32) (memory.grow (i32.const 1))) -) -(register "grown-imported-memory" $Mgim1) -(assert_return (invoke $Mgim1 "grow") (i32.const 2)) ;; now size is 3 -(module $Mgim2 - ;; imported memory limits should match, because external memory size is 3 now - (import "grown-imported-memory" "memory" (memory 3)) - (func (export "size") (result i32) (memory.size)) -) -(assert_return (invoke $Mgim2 "size") (i32.const 3)) - ;; Syntax errors diff -Nru binaryen-108/test/spec/memory64.wast binaryen-99/test/spec/memory64.wast --- binaryen-108/test/spec/memory64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/memory64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -52,7 +52,7 @@ (module (memory i64 1) - (data (i64.const 0) "ABC\a7D") (data (i64.const 20) "WASM") + (data (i32.const 0) "ABC\a7D") (data (i32.const 20) "WASM") ;; Data section (func (export "data") (result i32) diff -Nru binaryen-108/test/spec/memory_trap64.wast binaryen-99/test/spec/memory_trap64.wast --- binaryen-108/test/spec/memory_trap64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/memory_trap64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -33,8 +33,8 @@ (module (memory i64 1) - (data (i64.const 0) "abcdefgh") - (data (i64.const 0xfff8) "abcdefgh") + (data (i32.const 0) "abcdefgh") + (data (i32.const 0xfff8) "abcdefgh") (func (export "i32.load") (param $a i64) (result i32) (i32.load (local.get $a)) diff -Nru binaryen-108/test/spec/old_address64.wast binaryen-99/test/spec/old_address64.wast --- binaryen-108/test/spec/old_address64.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/old_address64.wast 2021-01-07 20:01:06.000000000 +0000 @@ -2,7 +2,7 @@ (import "spectest" "print" (func $print (param i32))) (memory i64 1) - (data (i64.const 0) "abcdefghijklmnopqrstuvwxyz") + (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz") (func (export "good") (param $i i64) (call $print (i32.load8_u offset=0 (local.get $i))) ;; 97 'a' diff -Nru binaryen-108/test/spec/old_func.wast binaryen-99/test/spec/old_func.wast --- binaryen-108/test/spec/old_func.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/old_func.wast 2021-01-07 20:01:06.000000000 +0000 @@ -170,23 +170,19 @@ ) (func (export "signature-implicit-reused") - - ;; XXX: Use numeric indices in this test again once we have a - ;; spec-compliant text parser. Original comment follows. - ;; The implicit index 16 in this test depends on the function and ;; type definitions, and may need adapting if they change. - (call_indirect (type 2) ;; XXX: was `(type 16)` + (call_indirect (type 16) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) (i32.const 0) ) - (call_indirect (type 2) ;; XXX: was `(type 16)` + (call_indirect (type 16) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) (i32.const 2) ) - (call_indirect (type 2) ;; XXX: was `(type 16)` + (call_indirect (type 16) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) (i32.const 3) diff -Nru binaryen-108/test/spec/old_import.wast binaryen-99/test/spec/old_import.wast --- binaryen-108/test/spec/old_import.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/old_import.wast 2021-01-07 20:01:06.000000000 +0000 @@ -96,7 +96,7 @@ (module (type (func (result i32))) (import "spectest" "table" (table 10 20 funcref)) - (elem (i32.const 1) $f $g) + (elem 0 (i32.const 1) $f $g) (func (export "call") (param i32) (result i32) (call_indirect (type 0) (local.get 0))) (func $f (result i32) (i32.const 11)) @@ -113,7 +113,7 @@ (module (type (func (result i32))) (table (import "spectest" "table") 10 20 funcref) - (elem (i32.const 1) $f $g) + (elem 0 (i32.const 1) $f $g) (func (export "call") (param i32) (result i32) (call_indirect (type 0) (local.get 0))) (func $f (result i32) (i32.const 11)) @@ -135,6 +135,10 @@ (module (import "" "" (table 10 funcref)) (table 10 funcref)) "multiple tables" ) +(assert_invalid + (module (table 10 funcref) (table 10 funcref)) + "multiple tables" +) (assert_unlinkable (module (import "spectest" "unknown" (table 10 funcref))) @@ -158,7 +162,7 @@ (module (import "spectest" "memory" (memory 1 2)) - (data (i32.const 10) "\10") + (data 0 (i32.const 10) "\10") (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) ) @@ -170,7 +174,7 @@ (module (memory (import "spectest" "memory") 1 2) - (data (i32.const 10) "\10") + (data 0 (i32.const 10) "\10") (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) ) diff -Nru binaryen-108/test/spec/ref_as_non_null.wast binaryen-99/test/spec/ref_as_non_null.wast --- binaryen-108/test/spec/ref_as_non_null.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/ref_as_non_null.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -(module - (type $t (func (result i32))) - - (func $nn (param $r (ref $t)) (result i32) - (call_ref (ref.as_non_null (local.get $r))) - ) - (func $n (param $r (ref null $t)) (result i32) - (call_ref (ref.as_non_null (local.get $r))) - ) - - (elem func $f) - (func $f (result i32) (i32.const 7)) - - (func (export "nullable-null") (result i32) (call $n (ref.null $t))) - (func (export "nonnullable-f") (result i32) (call $nn (ref.func $f))) - (func (export "nullable-f") (result i32) (call $n (ref.func $f))) -) - -(assert_trap (invoke "nullable-null") "null reference") -(assert_return (invoke "nonnullable-f") (i32.const 7)) -(assert_return (invoke "nullable-f") (i32.const 7)) - -(module - (type $t (func)) - (func (param $r (ref $t)) (drop (ref.as_non_null (local.get $r)))) - (func (param $r (ref func)) (drop (ref.as_non_null (local.get $r)))) - (func (param $r (ref extern)) (drop (ref.as_non_null (local.get $r)))) -) diff -Nru binaryen-108/test/spec/ref_cast.wast binaryen-99/test/spec/ref_cast.wast --- binaryen-108/test/spec/ref_cast.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/ref_cast.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -(module - (type $t0 (struct)) - (type $t1 (struct (field i32))) - (type $t1' (struct (field i32))) - (type $t2 (struct (field i32) (field i32))) - (type $t2' (struct (field i32) (field i32))) - (type $t3 (struct (field i32) (field i32))) - - (global $t0 (rtt $t0) (rtt.canon $t0)) - (global $t0' (rtt $t0) (rtt.canon $t0)) - (global $t1 (rtt $t1) (rtt.sub $t1 (global.get $t0))) - (global $t1' (rtt $t1') (rtt.sub $t1' (global.get $t0))) - (global $t2 (rtt $t2) (rtt.sub $t2 (global.get $t1))) - (global $t2' (rtt $t2') (rtt.sub $t2' (global.get $t1'))) - (global $t3 (rtt $t3) (rtt.sub $t3 (global.get $t0))) - (global $t4 (rtt $t3) (rtt.sub $t3 (rtt.sub $t0 (global.get $t0)))) - - (global $tab.0 (mut (ref null data)) (ref.null data)) - (global $tab.1 (mut (ref null data)) (ref.null data)) - (global $tab.2 (mut (ref null data)) (ref.null data)) - (global $tab.3 (mut (ref null data)) (ref.null data)) - (global $tab.4 (mut (ref null data)) (ref.null data)) - (global $tab.10 (mut (ref null data)) (ref.null data)) - (global $tab.11 (mut (ref null data)) (ref.null data)) - (global $tab.12 (mut (ref null data)) (ref.null data)) - - (func $init - (global.set $tab.0 (struct.new_default_with_rtt $t0 (global.get $t0))) - (global.set $tab.10 (struct.new_default_with_rtt $t0 (global.get $t0'))) - (global.set $tab.1 (struct.new_default_with_rtt $t1 (global.get $t1))) - (global.set $tab.11 (struct.new_default_with_rtt $t1' (global.get $t1'))) - (global.set $tab.2 (struct.new_default_with_rtt $t2 (global.get $t2))) - (global.set $tab.12 (struct.new_default_with_rtt $t2' (global.get $t2'))) - (global.set $tab.3 (struct.new_default_with_rtt $t3 (global.get $t3))) - (global.set $tab.4 (struct.new_default_with_rtt $t3 (global.get $t4))) - ) - - (func (export "test-sub") - (call $init) - - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.0) (global.get $t0))) - (drop (ref.cast (global.get $tab.1) (global.get $t0))) - (drop (ref.cast (global.get $tab.2) (global.get $t0))) - (drop (ref.cast (global.get $tab.3) (global.get $t0))) - (drop (ref.cast (global.get $tab.4) (global.get $t0))) - - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.1) (global.get $t1))) - (drop (ref.cast (global.get $tab.2) (global.get $t1))) - - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.2) (global.get $t2))) - - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.3) (global.get $t3))) - - (drop (ref.cast (ref.null data) (global.get $t0))) - (drop (ref.cast (global.get $tab.4) (global.get $t4))) - ) - - (func (export "test-canon") - (call $init) - - (drop (ref.cast (global.get $tab.0) (global.get $t0'))) - (drop (ref.cast (global.get $tab.1) (global.get $t0'))) - (drop (ref.cast (global.get $tab.2) (global.get $t0'))) - (drop (ref.cast (global.get $tab.3) (global.get $t0'))) - (drop (ref.cast (global.get $tab.4) (global.get $t0'))) - - (drop (ref.cast (global.get $tab.10) (global.get $t0))) - (drop (ref.cast (global.get $tab.11) (global.get $t0))) - (drop (ref.cast (global.get $tab.12) (global.get $t0))) - - (drop (ref.cast (global.get $tab.1) (global.get $t1'))) - (drop (ref.cast (global.get $tab.2) (global.get $t1'))) - - (drop (ref.cast (global.get $tab.11) (global.get $t1))) - (drop (ref.cast (global.get $tab.12) (global.get $t1))) - - (drop (ref.cast (global.get $tab.2) (global.get $t2'))) - - (drop (ref.cast (global.get $tab.12) (global.get $t2))) - ) -) - -(invoke "test-sub") -(invoke "test-canon") diff -Nru binaryen-108/test/spec/ref_eq.wast binaryen-99/test/spec/ref_eq.wast --- binaryen-108/test/spec/ref_eq.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/ref_eq.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -(module - (func $compare (export "compare") (param $x eqref) (param $y eqref) (result i32) - (ref.eq - (local.get $x) - (local.get $y) - ) - ) -) - -;; All nulls compare equal, regardless of their type. -(assert_return (invoke "compare" (ref.null data) (ref.null eq)) (i32.const 1)) diff -Nru binaryen-108/test/spec/simd.wast binaryen-99/test/spec/simd.wast --- binaryen-108/test/spec/simd.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/simd.wast 2021-01-07 20:01:06.000000000 +0000 @@ -14,11 +14,11 @@ (func (export "v128.const.i64x2") (result v128) (v128.const i64x2 1 2)) (func (export "v128.const.f32x4") (result v128) (v128.const f32x4 1.0 2 3 4)) (func (export "v128.const.f64x2") (result v128) (v128.const f64x2 1.0 2)) - (func (export "i8x16.shuffle_interleave_bytes") (param $0 v128) (param $1 v128) (result v128) - (i8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 (local.get $0) (local.get $1)) + (func (export "v128.shuffle_interleave_bytes") (param $0 v128) (param $1 v128) (result v128) + (v8x16.shuffle 0 17 2 19 4 21 6 23 8 25 10 27 12 29 14 31 (local.get $0) (local.get $1)) ) - (func (export "i8x16.shuffle_reverse_i32s") (param $0 v128) (result v128) - (i8x16.shuffle 12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3 (local.get $0) (local.get $0)) + (func (export "v128.shuffle_reverse_i32s") (param $0 v128) (result v128) + (v8x16.shuffle 12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3 (local.get $0) (local.get $0)) ) (func (export "i8x16.splat") (param $0 i32) (result v128) (i8x16.splat (local.get $0))) (func (export "i8x16.extract_lane_s_first") (param $0 v128) (result i32) (i8x16.extract_lane_s 0 (local.get $0))) @@ -105,6 +105,18 @@ (func (export "v128.bitselect") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (v128.bitselect (local.get $0) (local.get $1) (local.get $2)) ) + (func (export "v8x16.signselect") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v8x16.signselect (local.get $0) (local.get $1) (local.get $2)) + ) + (func (export "v16x8.signselect") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v16x8.signselect (local.get $0) (local.get $1) (local.get $2)) + ) + (func (export "v32x4.signselect") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v32x4.signselect (local.get $0) (local.get $1) (local.get $2)) + ) + (func (export "v64x2.signselect") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) + (v64x2.signselect (local.get $0) (local.get $1) (local.get $2)) + ) (func (export "v128.load8_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load8_lane 0 (local.get $0) (local.get $1))) (func (export "v128.load16_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load16_lane 0 (local.get $0) (local.get $1))) (func (export "v128.load32_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load32_lane 0 (local.get $0) (local.get $1))) @@ -116,17 +128,19 @@ (func (export "i8x16.popcnt") (param $0 v128) (result v128) (i8x16.popcnt (local.get $0))) (func (export "i8x16.abs") (param $0 v128) (result v128) (i8x16.abs (local.get $0))) (func (export "i8x16.neg") (param $0 v128) (result v128) (i8x16.neg (local.get $0))) + (func (export "i8x16.any_true") (param $0 v128) (result i32) (i8x16.any_true (local.get $0))) (func (export "i8x16.all_true") (param $0 v128) (result i32) (i8x16.all_true (local.get $0))) (func (export "i8x16.bitmask") (param $0 v128) (result i32) (i8x16.bitmask (local.get $0))) (func (export "i8x16.shl") (param $0 v128) (param $1 i32) (result v128) (i8x16.shl (local.get $0) (local.get $1))) (func (export "i8x16.shr_s") (param $0 v128) (param $1 i32) (result v128) (i8x16.shr_s (local.get $0) (local.get $1))) (func (export "i8x16.shr_u") (param $0 v128) (param $1 i32) (result v128) (i8x16.shr_u (local.get $0) (local.get $1))) (func (export "i8x16.add") (param $0 v128) (param $1 v128) (result v128) (i8x16.add (local.get $0) (local.get $1))) - (func (export "i8x16.add_sat_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.add_sat_s (local.get $0) (local.get $1))) - (func (export "i8x16.add_sat_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.add_sat_u (local.get $0) (local.get $1))) + (func (export "i8x16.add_saturate_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.add_saturate_s (local.get $0) (local.get $1))) + (func (export "i8x16.add_saturate_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.add_saturate_u (local.get $0) (local.get $1))) (func (export "i8x16.sub") (param $0 v128) (param $1 v128) (result v128) (i8x16.sub (local.get $0) (local.get $1))) - (func (export "i8x16.sub_sat_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.sub_sat_s (local.get $0) (local.get $1))) - (func (export "i8x16.sub_sat_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.sub_sat_u (local.get $0) (local.get $1))) + (func (export "i8x16.sub_saturate_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.sub_saturate_s (local.get $0) (local.get $1))) + (func (export "i8x16.sub_saturate_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.sub_saturate_u (local.get $0) (local.get $1))) + (func (export "i8x16.mul") (param $0 v128) (param $1 v128) (result v128) (i8x16.mul (local.get $0) (local.get $1))) (func (export "i8x16.min_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.min_s (local.get $0) (local.get $1))) (func (export "i8x16.min_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.min_u (local.get $0) (local.get $1))) (func (export "i8x16.max_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.max_s (local.get $0) (local.get $1))) @@ -134,38 +148,29 @@ (func (export "i8x16.avgr_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.avgr_u (local.get $0) (local.get $1))) (func (export "i16x8.abs") (param $0 v128) (result v128) (i16x8.abs (local.get $0))) (func (export "i16x8.neg") (param $0 v128) (result v128) (i16x8.neg (local.get $0))) + (func (export "i16x8.any_true") (param $0 v128) (result i32) (i16x8.any_true (local.get $0))) (func (export "i16x8.all_true") (param $0 v128) (result i32) (i16x8.all_true (local.get $0))) (func (export "i16x8.bitmask") (param $0 v128) (result i32) (i16x8.bitmask (local.get $0))) (func (export "i16x8.shl") (param $0 v128) (param $1 i32) (result v128) (i16x8.shl (local.get $0) (local.get $1))) (func (export "i16x8.shr_s") (param $0 v128) (param $1 i32) (result v128) (i16x8.shr_s (local.get $0) (local.get $1))) (func (export "i16x8.shr_u") (param $0 v128) (param $1 i32) (result v128) (i16x8.shr_u (local.get $0) (local.get $1))) (func (export "i16x8.add") (param $0 v128) (param $1 v128) (result v128) (i16x8.add (local.get $0) (local.get $1))) - (func (export "i16x8.add_sat_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.add_sat_s (local.get $0) (local.get $1))) - (func (export "i16x8.add_sat_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.add_sat_u (local.get $0) (local.get $1))) + (func (export "i16x8.add_saturate_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.add_saturate_s (local.get $0) (local.get $1))) + (func (export "i16x8.add_saturate_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.add_saturate_u (local.get $0) (local.get $1))) (func (export "i16x8.sub") (param $0 v128) (param $1 v128) (result v128) (i16x8.sub (local.get $0) (local.get $1))) - (func (export "i16x8.sub_sat_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.sub_sat_s (local.get $0) (local.get $1))) - (func (export "i16x8.sub_sat_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.sub_sat_u (local.get $0) (local.get $1))) + (func (export "i16x8.sub_saturate_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.sub_saturate_s (local.get $0) (local.get $1))) + (func (export "i16x8.sub_saturate_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.sub_saturate_u (local.get $0) (local.get $1))) (func (export "i16x8.mul") (param $0 v128) (param $1 v128) (result v128) (i16x8.mul (local.get $0) (local.get $1))) (func (export "i16x8.min_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.min_s (local.get $0) (local.get $1))) (func (export "i16x8.min_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.min_u (local.get $0) (local.get $1))) (func (export "i16x8.max_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.max_s (local.get $0) (local.get $1))) (func (export "i16x8.max_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.max_u (local.get $0) (local.get $1))) (func (export "i16x8.avgr_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.avgr_u (local.get $0) (local.get $1))) - (func (export "i16x8.q15mulr_sat_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.q15mulr_sat_s (local.get $0) (local.get $1))) - (func (export "i16x8.extmul_low_i8x16_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_low_i8x16_s (local.get $0) (local.get $1))) - (func (export "i16x8.extmul_high_i8x16_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_high_i8x16_s (local.get $0) (local.get $1))) - (func (export "i16x8.extmul_low_i8x16_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_low_i8x16_u (local.get $0) (local.get $1))) - (func (export "i16x8.extmul_high_i8x16_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.extmul_high_i8x16_u (local.get $0) (local.get $1))) - (func (export "i32x4.extmul_low_i16x8_s") (param $0 v128) (param $1 v128) (result v128) (i32x4.extmul_low_i16x8_s (local.get $0) (local.get $1))) - (func (export "i32x4.extmul_high_i16x8_s") (param $0 v128) (param $1 v128) (result v128) (i32x4.extmul_high_i16x8_s (local.get $0) (local.get $1))) - (func (export "i32x4.extmul_low_i16x8_u") (param $0 v128) (param $1 v128) (result v128) (i32x4.extmul_low_i16x8_u (local.get $0) (local.get $1))) - (func (export "i32x4.extmul_high_i16x8_u") (param $0 v128) (param $1 v128) (result v128) (i32x4.extmul_high_i16x8_u (local.get $0) (local.get $1))) - (func (export "i64x2.extmul_low_i32x4_s") (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_low_i32x4_s (local.get $0) (local.get $1))) - (func (export "i64x2.extmul_high_i32x4_s") (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_high_i32x4_s (local.get $0) (local.get $1))) - (func (export "i64x2.extmul_low_i32x4_u") (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_low_i32x4_u (local.get $0) (local.get $1))) - (func (export "i64x2.extmul_high_i32x4_u") (param $0 v128) (param $1 v128) (result v128) (i64x2.extmul_high_i32x4_u (local.get $0) (local.get $1))) + ;; TODO: Q15 rounding, saturating multiplication + ;; TODO: extending multiplications (func (export "i32x4.abs") (param $0 v128) (result v128) (i32x4.abs (local.get $0))) (func (export "i32x4.neg") (param $0 v128) (result v128) (i32x4.neg (local.get $0))) + (func (export "i32x4.any_true") (param $0 v128) (result i32) (i32x4.any_true (local.get $0))) (func (export "i32x4.all_true") (param $0 v128) (result i32) (i32x4.all_true (local.get $0))) (func (export "i32x4.bitmask") (param $0 v128) (result i32) (i32x4.bitmask (local.get $0))) (func (export "i32x4.shl") (param $0 v128) (param $1 i32) (result v128) (i32x4.shl (local.get $0) (local.get $1))) @@ -190,6 +195,8 @@ (func (export "f32x4.abs") (param $0 v128) (result v128) (f32x4.abs (local.get $0))) (func (export "f32x4.neg") (param $0 v128) (result v128) (f32x4.neg (local.get $0))) (func (export "f32x4.sqrt") (param $0 v128) (result v128) (f32x4.sqrt (local.get $0))) + (func (export "f32x4.qfma") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (f32x4.qfma (local.get $0) (local.get $1) (local.get $2))) + (func (export "f32x4.qfms") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (f32x4.qfms (local.get $0) (local.get $1) (local.get $2))) (func (export "f32x4.add") (param $0 v128) (param $1 v128) (result v128) (f32x4.add (local.get $0) (local.get $1))) (func (export "f32x4.sub") (param $0 v128) (param $1 v128) (result v128) (f32x4.sub (local.get $0) (local.get $1))) (func (export "f32x4.mul") (param $0 v128) (param $1 v128) (result v128) (f32x4.mul (local.get $0) (local.get $1))) @@ -205,6 +212,8 @@ (func (export "f64x2.abs") (param $0 v128) (result v128) (f64x2.abs (local.get $0))) (func (export "f64x2.neg") (param $0 v128) (result v128) (f64x2.neg (local.get $0))) (func (export "f64x2.sqrt") (param $0 v128) (result v128) (f64x2.sqrt (local.get $0))) + (func (export "f64x2.qfma") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (f64x2.qfma (local.get $0) (local.get $1) (local.get $2))) + (func (export "f64x2.qfms") (param $0 v128) (param $1 v128) (param $2 v128) (result v128) (f64x2.qfms (local.get $0) (local.get $1) (local.get $2))) (func (export "f64x2.add") (param $0 v128) (param $1 v128) (result v128) (f64x2.add (local.get $0) (local.get $1))) (func (export "f64x2.sub") (param $0 v128) (param $1 v128) (result v128) (f64x2.sub (local.get $0) (local.get $1))) (func (export "f64x2.mul") (param $0 v128) (param $1 v128) (result v128) (f64x2.mul (local.get $0) (local.get $1))) @@ -217,59 +226,53 @@ (func (export "f64x2.floor") (param $0 v128) (result v128) (f64x2.floor (local.get $0))) (func (export "f64x2.trunc") (param $0 v128) (result v128) (f64x2.trunc (local.get $0))) (func (export "f64x2.nearest") (param $0 v128) (result v128) (f64x2.nearest (local.get $0))) - (func (export "i16x8.extadd_pairwise_i8x16_s") (param v128) (result v128) (i16x8.extadd_pairwise_i8x16_s (local.get 0))) - (func (export "i16x8.extadd_pairwise_i8x16_u") (param v128) (result v128) (i16x8.extadd_pairwise_i8x16_u (local.get 0))) - (func (export "i32x4.extadd_pairwise_i16x8_s") (param v128) (result v128) (i32x4.extadd_pairwise_i16x8_s (local.get 0))) - (func (export "i32x4.extadd_pairwise_i16x8_u") (param v128) (result v128) (i32x4.extadd_pairwise_i16x8_u (local.get 0))) + ;; TODO: Extending pairwise adds once they have interpreter support (func (export "i32x4.trunc_sat_f32x4_s") (param $0 v128) (result v128) (i32x4.trunc_sat_f32x4_s (local.get $0))) (func (export "i32x4.trunc_sat_f32x4_u") (param $0 v128) (result v128) (i32x4.trunc_sat_f32x4_u (local.get $0))) + (func (export "i64x2.trunc_sat_f64x2_s") (param $0 v128) (result v128) (i64x2.trunc_sat_f64x2_s (local.get $0))) + (func (export "i64x2.trunc_sat_f64x2_u") (param $0 v128) (result v128) (i64x2.trunc_sat_f64x2_u (local.get $0))) (func (export "f32x4.convert_i32x4_s") (param $0 v128) (result v128) (f32x4.convert_i32x4_s (local.get $0))) (func (export "f32x4.convert_i32x4_u") (param $0 v128) (result v128) (f32x4.convert_i32x4_u (local.get $0))) - (func (export "v128.load8_splat") (param $0 i32) (result v128) (v128.load8_splat (local.get $0))) - (func (export "v128.load16_splat") (param $0 i32) (result v128) (v128.load16_splat (local.get $0))) - (func (export "v128.load32_splat") (param $0 i32) (result v128) (v128.load32_splat (local.get $0))) - (func (export "v128.load64_splat") (param $0 i32) (result v128) (v128.load64_splat (local.get $0))) + (func (export "f64x2.convert_i64x2_s") (param $0 v128) (result v128) (f64x2.convert_i64x2_s (local.get $0))) + (func (export "f64x2.convert_i64x2_u") (param $0 v128) (result v128) (f64x2.convert_i64x2_u (local.get $0))) + (func (export "v8x16.load_splat") (param $0 i32) (result v128) (v8x16.load_splat (local.get $0))) + (func (export "v16x8.load_splat") (param $0 i32) (result v128) (v16x8.load_splat (local.get $0))) + (func (export "v32x4.load_splat") (param $0 i32) (result v128) (v32x4.load_splat (local.get $0))) + (func (export "v64x2.load_splat") (param $0 i32) (result v128) (v64x2.load_splat (local.get $0))) (func (export "i8x16.narrow_i16x8_s") (param $0 v128) (param $1 v128) (result v128) (i8x16.narrow_i16x8_s (local.get $0) (local.get $1))) (func (export "i8x16.narrow_i16x8_u") (param $0 v128) (param $1 v128) (result v128) (i8x16.narrow_i16x8_u (local.get $0) (local.get $1))) (func (export "i16x8.narrow_i32x4_s") (param $0 v128) (param $1 v128) (result v128) (i16x8.narrow_i32x4_s (local.get $0) (local.get $1))) (func (export "i16x8.narrow_i32x4_u") (param $0 v128) (param $1 v128) (result v128) (i16x8.narrow_i32x4_u (local.get $0) (local.get $1))) - (func (export "i16x8.extend_low_i8x16_s") (param $0 v128) (result v128) (i16x8.extend_low_i8x16_s (local.get $0))) - (func (export "i16x8.extend_high_i8x16_s") (param $0 v128) (result v128) (i16x8.extend_high_i8x16_s (local.get $0))) - (func (export "i16x8.extend_low_i8x16_u") (param $0 v128) (result v128) (i16x8.extend_low_i8x16_u (local.get $0))) - (func (export "i16x8.extend_high_i8x16_u") (param $0 v128) (result v128) (i16x8.extend_high_i8x16_u (local.get $0))) - (func (export "i32x4.extend_low_i16x8_s") (param $0 v128) (result v128) (i32x4.extend_low_i16x8_s (local.get $0))) - (func (export "i32x4.extend_high_i16x8_s") (param $0 v128) (result v128) (i32x4.extend_high_i16x8_s (local.get $0))) - (func (export "i32x4.extend_low_i16x8_u") (param $0 v128) (result v128) (i32x4.extend_low_i16x8_u (local.get $0))) - (func (export "i32x4.extend_high_i16x8_u") (param $0 v128) (result v128) (i32x4.extend_high_i16x8_u (local.get $0))) - (func (export "i64x2.extend_low_i32x4_s") (param $0 v128) (result v128) (i64x2.extend_low_i32x4_s (local.get $0))) - (func (export "i64x2.extend_high_i32x4_s") (param $0 v128) (result v128) (i64x2.extend_high_i32x4_s (local.get $0))) - (func (export "i64x2.extend_low_i32x4_u") (param $0 v128) (result v128) (i64x2.extend_low_i32x4_u (local.get $0))) - (func (export "i64x2.extend_high_i32x4_u") (param $0 v128) (result v128) (i64x2.extend_high_i32x4_u (local.get $0))) - (func (export "v128.load8x8_u") (param $0 i32) (result v128) (v128.load8x8_u (local.get $0))) - (func (export "v128.load8x8_s") (param $0 i32) (result v128) (v128.load8x8_s (local.get $0))) - (func (export "v128.load16x4_u") (param $0 i32) (result v128) (v128.load16x4_u (local.get $0))) - (func (export "v128.load16x4_s") (param $0 i32) (result v128) (v128.load16x4_s (local.get $0))) - (func (export "v128.load32x2_u") (param $0 i32) (result v128) (v128.load32x2_u (local.get $0))) - (func (export "v128.load32x2_s") (param $0 i32) (result v128) (v128.load32x2_s (local.get $0))) + (func (export "i16x8.widen_low_i8x16_s") (param $0 v128) (result v128) (i16x8.widen_low_i8x16_s (local.get $0))) + (func (export "i16x8.widen_high_i8x16_s") (param $0 v128) (result v128) (i16x8.widen_high_i8x16_s (local.get $0))) + (func (export "i16x8.widen_low_i8x16_u") (param $0 v128) (result v128) (i16x8.widen_low_i8x16_u (local.get $0))) + (func (export "i16x8.widen_high_i8x16_u") (param $0 v128) (result v128) (i16x8.widen_high_i8x16_u (local.get $0))) + (func (export "i32x4.widen_low_i16x8_s") (param $0 v128) (result v128) (i32x4.widen_low_i16x8_s (local.get $0))) + (func (export "i32x4.widen_high_i16x8_s") (param $0 v128) (result v128) (i32x4.widen_high_i16x8_s (local.get $0))) + (func (export "i32x4.widen_low_i16x8_u") (param $0 v128) (result v128) (i32x4.widen_low_i16x8_u (local.get $0))) + (func (export "i32x4.widen_high_i16x8_u") (param $0 v128) (result v128) (i32x4.widen_high_i16x8_u (local.get $0))) + (func (export "i64x2.widen_low_i32x4_s") (param $0 v128) (result v128) (i64x2.widen_low_i32x4_s (local.get $0))) + (func (export "i64x2.widen_high_i32x4_s") (param $0 v128) (result v128) (i64x2.widen_high_i32x4_s (local.get $0))) + (func (export "i64x2.widen_low_i32x4_u") (param $0 v128) (result v128) (i64x2.widen_low_i32x4_u (local.get $0))) + (func (export "i64x2.widen_high_i32x4_u") (param $0 v128) (result v128) (i64x2.widen_high_i32x4_u (local.get $0))) + (func (export "i16x8.load8x8_u") (param $0 i32) (result v128) (i16x8.load8x8_u (local.get $0))) + (func (export "i16x8.load8x8_s") (param $0 i32) (result v128) (i16x8.load8x8_s (local.get $0))) + (func (export "i32x4.load16x4_u") (param $0 i32) (result v128) (i32x4.load16x4_u (local.get $0))) + (func (export "i32x4.load16x4_s") (param $0 i32) (result v128) (i32x4.load16x4_s (local.get $0))) + (func (export "i64x2.load32x2_u") (param $0 i32) (result v128) (i64x2.load32x2_u (local.get $0))) + (func (export "i64x2.load32x2_s") (param $0 i32) (result v128) (i64x2.load32x2_s (local.get $0))) (func (export "v128.load32_zero") (param $0 i32) (result v128) (v128.load32_zero (local.get $0))) (func (export "v128.load64_zero") (param $0 i32) (result v128) (v128.load64_zero (local.get $0))) - (func (export "i8x16.swizzle") (param $0 v128) (param $1 v128) (result v128) (i8x16.swizzle (local.get $0) (local.get $1))) - (func (export "f64x2.convert_low_i32x4_s") (param $0 v128) (result v128) (f64x2.convert_low_i32x4_s (local.get $0))) - (func (export "f64x2.convert_low_i32x4_u") (param $0 v128) (result v128) (f64x2.convert_low_i32x4_u (local.get $0))) - (func (export "i32x4.trunc_sat_f64x2_s_zero") (param $0 v128) (result v128) (i32x4.trunc_sat_f64x2_s_zero (local.get $0))) - (func (export "i32x4.trunc_sat_f64x2_u_zero") (param $0 v128) (result v128) (i32x4.trunc_sat_f64x2_u_zero (local.get $0))) - (func (export "f32x4.demote_f64x2_zero") (param $0 v128) (result v128) (f32x4.demote_f64x2_zero (local.get $0))) - (func (export "f64x2.promote_low_f32x4") (param $0 v128) (result v128) (f64x2.promote_low_f32x4 (local.get $0))) + (func (export "v8x16.swizzle") (param $0 v128) (param $1 v128) (result v128) (v8x16.swizzle (local.get $0) (local.get $1))) ) -;; TODO: Additional f64x2 conversions if specified ;; Basic v128 manipulation (assert_return (invoke "v128.load" (i32.const 128)) (v128.const i8x16 87 65 83 77 83 73 77 68 71 79 69 83 70 65 83 84)) (assert_return (invoke "v128.store" (i32.const 16) (v128.const i32x4 1 2 3 4)) (v128.const i32x4 1 2 3 4)) -(assert_return (invoke "v128.load8_splat" (i32.const 128)) (v128.const i8x16 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87)) -(assert_return (invoke "v128.load16_splat" (i32.const 128)) (v128.const i8x16 87 65 87 65 87 65 87 65 87 65 87 65 87 65 87 65)) -(assert_return (invoke "v128.load32_splat" (i32.const 128)) (v128.const i8x16 87 65 83 77 87 65 83 77 87 65 83 77 87 65 83 77)) -(assert_return (invoke "v128.load64_splat" (i32.const 128)) (v128.const i8x16 87 65 83 77 83 73 77 68 87 65 83 77 83 73 77 68)) +(assert_return (invoke "v8x16.load_splat" (i32.const 128)) (v128.const i8x16 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87 87)) +(assert_return (invoke "v16x8.load_splat" (i32.const 128)) (v128.const i8x16 87 65 87 65 87 65 87 65 87 65 87 65 87 65 87 65)) +(assert_return (invoke "v32x4.load_splat" (i32.const 128)) (v128.const i8x16 87 65 83 77 87 65 83 77 87 65 83 77 87 65 83 77)) +(assert_return (invoke "v64x2.load_splat" (i32.const 128)) (v128.const i8x16 87 65 83 77 83 73 77 68 87 65 83 77 83 73 77 68)) (assert_return (invoke "v128.const.i8x16") (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)) (assert_return (invoke "v128.const.i16x8") (v128.const i8x16 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00)) (assert_return (invoke "v128.const.i32x4") (v128.const i8x16 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00)) @@ -277,13 +280,13 @@ (assert_return (invoke "v128.const.f32x4") (v128.const f32x4 1 2 3 4)) (assert_return (invoke "v128.const.f64x2") (v128.const f64x2 1 2)) (assert_return - (invoke "i8x16.shuffle_interleave_bytes" + (invoke "v128.shuffle_interleave_bytes" (v128.const i8x16 1 0 3 0 5 0 7 0 9 0 11 0 13 0 15 0) (v128.const i8x16 0 2 0 4 0 6 0 8 0 10 0 12 0 14 0 16) ) (v128.const i8x16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) ) -(assert_return (invoke "i8x16.shuffle_reverse_i32s" (v128.const i32x4 1 2 3 4)) (v128.const i32x4 4 3 2 1)) +(assert_return (invoke "v128.shuffle_reverse_i32s" (v128.const i32x4 1 2 3 4)) (v128.const i32x4 4 3 2 1)) ;; i8x16 lane accesses (assert_return (invoke "i8x16.splat" (i32.const 5)) (v128.const i8x16 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5)) @@ -600,6 +603,10 @@ (assert_return (invoke "i8x16.neg" (v128.const i32x4 0 1 42 -3 -56 127 -128 -126 0 -1 -42 3 56 -127 -128 126)) (v128.const i32x4 0 -1 -42 3 56 -127 -128 126 0 1 42 -3 -56 127 -128 -126) ) +(assert_return (invoke "i8x16.any_true" (v128.const i32x4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 0)) +(assert_return (invoke "i8x16.any_true" (v128.const i32x4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0)) (i32.const 1)) +(assert_return (invoke "i8x16.any_true" (v128.const i32x4 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1)) (i32.const 1)) +(assert_return (invoke "i8x16.any_true" (v128.const i32x4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)) (i32.const 1)) (assert_return (invoke "i8x16.all_true" (v128.const i32x4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 0)) (assert_return (invoke "i8x16.all_true" (v128.const i32x4 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0)) (i32.const 0)) (assert_return (invoke "i8x16.all_true" (v128.const i32x4 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1)) (i32.const 0)) @@ -631,14 +638,14 @@ (v128.const i32x4 3 17 0 0 0 135 109 46 145 225 48 184 17 249 128 215) ) (assert_return - (invoke "i8x16.add_sat_s" + (invoke "i8x16.add_saturate_s" (v128.const i32x4 0 42 255 128 127 129 6 29 103 196 231 142 17 250 1 73) (v128.const i32x4 3 231 1 128 129 6 103 17 42 29 73 42 0 255 127 142) ) (v128.const i32x4 3 17 0 128 0 135 109 46 127 225 48 184 17 249 127 215) ) (assert_return - (invoke "i8x16.add_sat_u" + (invoke "i8x16.add_saturate_u" (v128.const i32x4 0 42 255 128 127 129 6 29 103 196 231 142 17 250 1 73) (v128.const i32x4 3 231 1 128 129 6 103 17 42 29 73 42 0 255 127 142) ) @@ -652,20 +659,27 @@ (v128.const i32x4 253 67 254 0 254 123 159 12 61 167 158 100 17 251 130 187) ) (assert_return - (invoke "i8x16.sub_sat_s" + (invoke "i8x16.sub_saturate_s" (v128.const i32x4 0 42 255 128 127 129 6 29 103 196 231 142 17 250 1 73) (v128.const i32x4 3 231 1 128 129 6 103 17 42 29 73 42 0 255 127 142) ) (v128.const i32x4 253 67 254 0 127 128 159 12 61 167 158 128 17 251 130 127) ) (assert_return - (invoke "i8x16.sub_sat_u" + (invoke "i8x16.sub_saturate_u" (v128.const i32x4 0 42 255 128 127 129 6 29 103 196 231 142 17 250 1 73) (v128.const i32x4 3 231 1 128 129 6 103 17 42 29 73 42 0 255 127 142) ) (v128.const i32x4 0 0 254 0 0 123 0 12 61 167 158 100 17 0 0 0) ) (assert_return + (invoke "i8x16.mul" + (v128.const i32x4 0 42 255 128 127 129 6 29 103 196 231 142 17 250 1 73) + (v128.const i32x4 3 231 1 128 129 6 103 17 42 29 73 42 0 255 127 142) + ) + (v128.const i32x4 0 230 255 0 255 6 106 237 230 52 223 76 0 6 127 126) +) +(assert_return (invoke "i8x16.min_s" (v128.const i32x4 0 42 255 128 127 129 6 29 103 196 231 142 17 250 1 73) (v128.const i32x4 3 231 1 128 129 6 103 17 42 29 73 42 0 255 127 142) @@ -708,6 +722,10 @@ (assert_return (invoke "i16x8.neg" (v128.const i32x4 0 1 42 -3 -56 32767 -32768 32766)) (v128.const i32x4 0 -1 -42 3 56 -32767 -32768 -32766) ) +(assert_return (invoke "i16x8.any_true" (v128.const i32x4 0 0 0 0 0 0 0 0)) (i32.const 0)) +(assert_return (invoke "i16x8.any_true" (v128.const i32x4 0 0 1 0 0 0 0 0)) (i32.const 1)) +(assert_return (invoke "i16x8.any_true" (v128.const i32x4 1 1 1 1 1 0 1 1)) (i32.const 1)) +(assert_return (invoke "i16x8.any_true" (v128.const i32x4 1 1 1 1 1 1 1 1)) (i32.const 1)) (assert_return (invoke "i16x8.all_true" (v128.const i32x4 0 0 0 0 0 0 0 0)) (i32.const 0)) (assert_return (invoke "i16x8.all_true" (v128.const i32x4 0 0 1 0 0 0 0 0)) (i32.const 0)) (assert_return (invoke "i16x8.all_true" (v128.const i32x4 1 1 1 1 1 0 1 1)) (i32.const 0)) @@ -727,14 +745,14 @@ (v128.const i32x4 768 65281 0 0 34560 12288 63744 32768) ) (assert_return - (invoke "i16x8.add_sat_s" + (invoke "i16x8.add_saturate_s" (v128.const i32x4 0 65280 32768 32512 33024 59136 64000 32766) (v128.const i32x4 768 1 32768 33024 1536 18688 65280 2) ) (v128.const i32x4 768 65281 32768 0 34560 12288 63744 32767) ) (assert_return - (invoke "i16x8.add_sat_u" + (invoke "i16x8.add_saturate_u" (v128.const i32x4 0 65280 32768 32512 33024 59136 64000 32766) (v128.const i32x4 768 1 32768 33024 1536 18688 65280 2) ) @@ -748,14 +766,14 @@ (v128.const i32x4 64768 65279 0 65024 31488 40448 64256 32764) ) (assert_return - (invoke "i16x8.sub_sat_s" + (invoke "i16x8.sub_saturate_s" (v128.const i32x4 0 65280 32768 32512 33024 59136 64000 32766) (v128.const i32x4 768 1 32768 33024 1536 18688 65280 2) ) (v128.const i32x4 64768 65279 0 32767 32768 40448 64256 32764) ) (assert_return - (invoke "i16x8.sub_sat_u" + (invoke "i16x8.sub_saturate_u" (v128.const i32x4 0 65280 32768 32512 33024 59136 64000 32766) (v128.const i32x4 768 1 32768 33024 1536 18688 65280 2) ) @@ -803,105 +821,14 @@ ) (v128.const i16x8 384 32641 32768 32768 17280 38912 64640 16384) ) -(assert_return - (invoke "i16x8.q15mulr_sat_s" - (v128.const i16x8 -1 -16383 32765 65535 -32768 65535 -16385 -32768) - (v128.const i16x8 -1 -16384 1 -32768 -32768 1 -16384 -1) - ) - (v128.const i16x8 0 8192 1 1 32767 0 8193 1) -) - - -(assert_return - (invoke "i16x8.extmul_low_i8x16_s" - (v128.const i8x16 63 -63 128 -127 -128 -128 255 255 0 0 0 0 0 0 0 0) - (v128.const i8x16 64 -64 1 -1 -1 -127 1 255 0 0 0 0 0 0 0 0) - ) - (v128.const i16x8 4032 4032 -128 127 128 16256 -1 1) -) -(assert_return - (invoke "i16x8.extmul_high_i8x16_s" - (v128.const i8x16 0 0 0 0 0 0 0 0 63 -63 128 -127 -128 -128 255 255) - (v128.const i8x16 0 0 0 0 0 0 0 0 64 -64 1 -1 -1 -127 1 255) - ) - (v128.const i16x8 4032 4032 -128 127 128 16256 -1 1) -) -(assert_return - (invoke "i16x8.extmul_low_i8x16_u" - (v128.const i8x16 1 -1 63 -65 -126 -128 255 255 0 0 0 0 0 0 0 0) - (v128.const i8x16 -1 -1 64 -64 -1 -128 -128 255 0 0 0 0 0 0 0 0) - ) - (v128.const i16x8 255 -511 4032 -28864 -32386 16384 32640 -511) -) -(assert_return - (invoke "i16x8.extmul_high_i8x16_u" - (v128.const i8x16 0 0 0 0 0 0 0 0 1 -1 63 -65 -126 -128 255 255) - (v128.const i8x16 0 0 0 0 0 0 0 0 -1 -1 64 -64 -1 -128 -128 255) - ) - (v128.const i16x8 255 -511 4032 -28864 -32386 16384 32640 -511) -) - -(assert_return - (invoke "i32x4.extmul_low_i16x8_s" - (v128.const i16x8 1 16384 -32766 65535 0 0 0 0) - (v128.const i16x8 -1 16384 -1 -1 0 0 0 0) - ) - (v128.const i32x4 -1 268435456 32766 1) -) -(assert_return - (invoke "i32x4.extmul_high_i16x8_s" - (v128.const i16x8 0 0 0 0 16383 32768 -32766 65535) - (v128.const i16x8 0 0 0 0 16384 1 -1 -32768) - ) - (v128.const i32x4 268419072 -32768 32766 32768) -) -(assert_return - (invoke "i32x4.extmul_low_i16x8_u" - (v128.const i16x8 16383 -16383 -32768 65535 0 0 0 0) - (v128.const i16x8 16384 -16384 -1 65535 0 0 0 0) - ) - (v128.const i32x4 268419072 -1878999040 2147450880 -131071) -) -(assert_return - (invoke "i32x4.extmul_high_i16x8_u" - (v128.const i16x8 0 0 0 0 16383 -16383 -32768 65535) - (v128.const i16x8 0 0 0 0 16384 -16384 -1 65535) - ) - (v128.const i32x4 268419072 -1878999040 2147450880 -131071) -) - -(assert_return - (invoke "i64x2.extmul_low_i32x4_s" - (v128.const i32x4 1073741823 -2147483648 0 0) - (v128.const i32x4 1073741824 -1 0 0) - ) - (v128.const i64x2 1152921503533105152 2147483648) -) -(assert_return - (invoke "i64x2.extmul_high_i32x4_s" - (v128.const i32x4 0 0 -1073741825 4294967295) - (v128.const i32x4 0 0 -1073741824 4294967295) - ) - (v128.const i64x2 1152921505680588800 1) -) -(assert_return - (invoke "i64x2.extmul_low_i32x4_u" - (v128.const i32x4 -1 -1073741825 0 0) - (v128.const i32x4 -1 -1073741824 0 0) - ) - (v128.const i64x2 -8589934591 -8070450535469154304) -) -(assert_return - (invoke "i64x2.extmul_high_i32x4_u" - (v128.const i32x4 0 0 -2147483648 4294967295) - (v128.const i32x4 0 0 -1 4294967295) - ) - (v128.const i64x2 9223372034707292160 -8589934591) -) ;; i32x4 arithmetic (assert_return (invoke "i32x4.abs" (v128.const i32x4 0 1 0x80000000 0x80000001)) (v128.const i32x4 0 1 0x80000000 0x7fffffff)) (assert_return (invoke "i32x4.neg" (v128.const i32x4 0 1 0x80000000 0x80000001)) (v128.const i32x4 0 -1 0x80000000 0x7fffffff)) +(assert_return (invoke "i32x4.any_true" (v128.const i32x4 0 0 0 0)) (i32.const 0)) +(assert_return (invoke "i32x4.any_true" (v128.const i32x4 0 0 1 0)) (i32.const 1)) +(assert_return (invoke "i32x4.any_true" (v128.const i32x4 1 0 1 1)) (i32.const 1)) +(assert_return (invoke "i32x4.any_true" (v128.const i32x4 1 1 1 1)) (i32.const 1)) (assert_return (invoke "i32x4.all_true" (v128.const i32x4 0 0 0 0)) (i32.const 0)) (assert_return (invoke "i32x4.all_true" (v128.const i32x4 0 0 1 0)) (i32.const 0)) (assert_return (invoke "i32x4.all_true" (v128.const i32x4 1 0 1 1)) (i32.const 0)) @@ -939,8 +866,7 @@ ;; i64x2 arithmetic (assert_return (invoke "i64x2.neg" (v128.const i64x2 0x8000000000000000 42)) (v128.const i64x2 0x8000000000000000 -42)) -(assert_return (invoke "i64x2.bitmask" (v128.const i64x2 0x8000000000000000 42)) (i32.const 1)) -(assert_return (invoke "i64x2.bitmask" (v128.const i64x2 1 -1)) (i32.const 2)) +;; TODO: test i64x2.bitmask (assert_return (invoke "i64x2.shl" (v128.const i64x2 1 0x8000000000000000) (i32.const 1)) (v128.const i64x2 2 0)) (assert_return (invoke "i64x2.shl" (v128.const i64x2 1 0x8000000000000000) (i32.const 64)) (v128.const i64x2 1 0x8000000000000000)) (assert_return (invoke "i64x2.shr_s" (v128.const i64x2 1 0x8000000000000000) (i32.const 1)) (v128.const i64x2 0 0xc000000000000000)) @@ -955,6 +881,7 @@ (assert_return (invoke "f32x4.abs" (v128.const f32x4 -0 nan -infinity 5)) (v128.const f32x4 0 nan infinity 5)) (assert_return (invoke "f32x4.neg" (v128.const f32x4 -0 nan -infinity 5)) (v128.const f32x4 0 -nan infinity -5)) (assert_return (invoke "f32x4.sqrt" (v128.const f32x4 -0 nan infinity 4)) (v128.const f32x4 -0 nan infinity 2)) +;; TODO: qfma/qfms tests (assert_return (invoke "f32x4.add" (v128.const f32x4 nan -nan infinity 42) (v128.const f32x4 42 infinity infinity 1)) (v128.const f32x4 nan nan infinity 43)) (assert_return (invoke "f32x4.sub" (v128.const f32x4 nan -nan infinity 42) (v128.const f32x4 42 infinity -infinity 1)) (v128.const f32x4 nan nan infinity 41)) (assert_return (invoke "f32x4.mul" (v128.const f32x4 nan -nan infinity 42) (v128.const f32x4 42 infinity infinity 2)) (v128.const f32x4 nan nan infinity 84)) @@ -983,6 +910,7 @@ (assert_return (invoke "f64x2.neg" (v128.const f64x2 -infinity 5)) (v128.const f64x2 infinity -5)) (assert_return (invoke "f64x2.sqrt" (v128.const f64x2 -0 nan)) (v128.const f64x2 -0 nan)) (assert_return (invoke "f64x2.sqrt" (v128.const f64x2 infinity 4)) (v128.const f64x2 infinity 2)) +;; TODO: qfma/qfms tests (assert_return (invoke "f64x2.add" (v128.const f64x2 nan -nan) (v128.const f64x2 42 infinity)) (v128.const f64x2 nan nan)) (assert_return (invoke "f64x2.add" (v128.const f64x2 infinity 42) (v128.const f64x2 infinity 1)) (v128.const f64x2 infinity 43)) (assert_return (invoke "f64x2.sub" (v128.const f64x2 nan -nan) (v128.const f64x2 42 infinity)) (v128.const f64x2 nan nan)) @@ -1024,36 +952,19 @@ (assert_return (invoke "f64x2.nearest" (v128.const f64x2 1.5 -1.5)) (v128.const f64x2 2 -2)) (assert_return (invoke "f64x2.nearest" (v128.const f64x2 4.2 -4.2)) (v128.const f64x2 4 -4)) -(assert_return - (invoke "i16x8.extadd_pairwise_i8x16_s" - (v128.const i8x16 -1 -1 -127 -127 -128 -128 127 127 255 255 1 1 0 0 126 126) - ) - (v128.const i16x8 -2 -254 -256 254 -2 2 0 252) -) -(assert_return - (invoke "i16x8.extadd_pairwise_i8x16_u" - (v128.const i8x16 0 0 1 1 -1 -1 126 126 -127 -127 -128 -128 127 127 255 255) - ) - (v128.const i16x8 0 2 510 252 258 256 254 510) -) -(assert_return - (invoke "i32x4.extadd_pairwise_i16x8_s" - (v128.const i16x8 32766 32766 -32767 -32767 65535 65535 -1 -1) - ) - (v128.const i32x4 65532 -65534 -2 -2) -) -(assert_return - (invoke "i32x4.extadd_pairwise_i16x8_u" - (v128.const i16x8 -1 -1 -32767 -32767 -32768 -32768 65535 65535) - ) - (v128.const i32x4 131070 65538 65536 131070) -) - ;; conversions (assert_return (invoke "i32x4.trunc_sat_f32x4_s" (v128.const f32x4 42 nan infinity -infinity)) (v128.const i32x4 42 0 2147483647 -2147483648)) (assert_return (invoke "i32x4.trunc_sat_f32x4_u" (v128.const f32x4 42 nan infinity -infinity)) (v128.const i32x4 42 0 4294967295 0)) +(assert_return (invoke "i64x2.trunc_sat_f64x2_s" (v128.const f64x2 42 nan)) (v128.const i64x2 42 0)) +(assert_return (invoke "i64x2.trunc_sat_f64x2_s" (v128.const f64x2 infinity -infinity)) (v128.const i64x2 9223372036854775807 -9223372036854775808)) +(assert_return (invoke "i64x2.trunc_sat_f64x2_u" (v128.const f64x2 42 nan)) (v128.const i64x2 42 0)) +(assert_return (invoke "i64x2.trunc_sat_f64x2_u" (v128.const f64x2 infinity -infinity)) (v128.const i64x2 18446744073709551615 0)) (assert_return (invoke "f32x4.convert_i32x4_s" (v128.const i32x4 0 -1 2147483647 -2147483648)) (v128.const f32x4 0 -1 2147483648 -2147483648)) (assert_return (invoke "f32x4.convert_i32x4_u" (v128.const i32x4 0 -1 2147483647 -2147483648)) (v128.const f32x4 0 4294967296 2147483648 2147483648)) +(assert_return (invoke "f64x2.convert_i64x2_s" (v128.const i64x2 0 -1)) (v128.const f64x2 0 -1)) +(assert_return (invoke "f64x2.convert_i64x2_s" (v128.const i64x2 9223372036854775807 -9223372036854775808)) (v128.const f64x2 9223372036854775807 -9223372036854775808)) +(assert_return (invoke "f64x2.convert_i64x2_u" (v128.const i64x2 0 -1)) (v128.const f64x2 0 18446744073709551616)) +(assert_return (invoke "f64x2.convert_i64x2_u" (v128.const i64x2 9223372036854775807 -9223372036854775808)) (v128.const f64x2 9223372036854775807 9223372036854775808)) (assert_return (invoke "i8x16.narrow_i16x8_s" (v128.const i16x8 129 127 -32767 32767 -32768 -1 1 0) @@ -1083,66 +994,46 @@ (v128.const i16x8 32769 32767 0 65535 0 1 0 0) ) (assert_return - (invoke "i16x8.extend_low_i8x16_s" + (invoke "i16x8.widen_low_i8x16_s" (v128.const i8x16 0 1 -1 -128 127 129 64 -64 -64 64 129 127 -128 -1 1 0) ) (v128.const i16x8 0 1 -1 -128 127 -127 64 -64) ) (assert_return - (invoke "i16x8.extend_high_i8x16_s" + (invoke "i16x8.widen_high_i8x16_s" (v128.const i8x16 0 1 -1 -128 127 129 64 -64 -64 64 129 127 -128 -1 1 0) ) (v128.const i16x8 -64 64 -127 127 -128 -1 1 0) ) (assert_return - (invoke "i16x8.extend_low_i8x16_u" + (invoke "i16x8.widen_low_i8x16_u" (v128.const i8x16 0 1 -1 -128 127 129 64 -64 -64 64 129 127 -128 -1 1 0) ) (v128.const i16x8 0 1 255 128 127 129 64 192) ) (assert_return - (invoke "i16x8.extend_high_i8x16_u" + (invoke "i16x8.widen_high_i8x16_u" (v128.const i8x16 0 1 -1 -128 127 129 64 -64 -64 64 129 127 -128 -1 1 0) ) (v128.const i16x8 192 64 129 127 128 255 1 0) ) -(assert_return (invoke "i32x4.extend_low_i16x8_s" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 0 1 -1 -32768)) -(assert_return (invoke "i32x4.extend_high_i16x8_s" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 32767 -32767 16384 -16384)) -(assert_return (invoke "i32x4.extend_low_i16x8_u" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 0 1 65535 32768)) -(assert_return (invoke "i32x4.extend_high_i16x8_u" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 32767 32769 16384 49152)) -(assert_return (invoke "i64x2.extend_low_i32x4_s" (v128.const i32x4 -1 -1 -2147483648 -2147483648)) (v128.const i64x2 -1 -1)) -(assert_return (invoke "i64x2.extend_high_i32x4_s" (v128.const i32x4 2147483647 2147483647 -1 -1)) (v128.const i64x2 -1 -1)) -(assert_return (invoke "i64x2.extend_low_i32x4_u" (v128.const i32x4 -1 -1 2 2)) (v128.const i64x2 4294967295 4294967295)) -(assert_return (invoke "i64x2.extend_high_i32x4_u" (v128.const i32x4 2 2 -1 -1)) (v128.const i64x2 4294967295 4294967295)) -(assert_return (invoke "v128.load8x8_s" (i32.const 256)) (v128.const i16x8 0xff80 0xff90 0xffa0 0xffb0 0xffc0 0xffd0 0xffe0 0xfff0)) -(assert_return (invoke "v128.load8x8_u" (i32.const 256)) (v128.const i16x8 0x0080 0x0090 0x00a0 0x00b0 0x00c0 0x00d0 0x00e0 0x00f0)) -(assert_return (invoke "v128.load16x4_s" (i32.const 256)) (v128.const i32x4 0xffff9080 0xffffb0a0 0xffffd0c0 0xfffff0e0)) -(assert_return (invoke "v128.load16x4_u" (i32.const 256)) (v128.const i32x4 0x00009080 0x0000b0a0 0x0000d0c0 0x0000f0e0)) -(assert_return (invoke "v128.load32x2_s" (i32.const 256)) (v128.const i64x2 0xffffffffb0a09080 0xfffffffff0e0d0c0)) -(assert_return (invoke "v128.load32x2_u" (i32.const 256)) (v128.const i64x2 0x00000000b0a09080 0x00000000f0e0d0c0)) +(assert_return (invoke "i32x4.widen_low_i16x8_s" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 0 1 -1 -32768)) +(assert_return (invoke "i32x4.widen_high_i16x8_s" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 32767 -32767 16384 -16384)) +(assert_return (invoke "i32x4.widen_low_i16x8_u" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 0 1 65535 32768)) +(assert_return (invoke "i32x4.widen_high_i16x8_u" (v128.const i16x8 0 1 -1 32768 32767 32769 16384 -16384)) (v128.const i32x4 32767 32769 16384 49152)) +;; TODO: test i64x2 widens +(assert_return (invoke "i16x8.load8x8_s" (i32.const 256)) (v128.const i16x8 0xff80 0xff90 0xffa0 0xffb0 0xffc0 0xffd0 0xffe0 0xfff0)) +(assert_return (invoke "i16x8.load8x8_u" (i32.const 256)) (v128.const i16x8 0x0080 0x0090 0x00a0 0x00b0 0x00c0 0x00d0 0x00e0 0x00f0)) +(assert_return (invoke "i32x4.load16x4_s" (i32.const 256)) (v128.const i32x4 0xffff9080 0xffffb0a0 0xffffd0c0 0xfffff0e0)) +(assert_return (invoke "i32x4.load16x4_u" (i32.const 256)) (v128.const i32x4 0x00009080 0x0000b0a0 0x0000d0c0 0x0000f0e0)) +(assert_return (invoke "i64x2.load32x2_s" (i32.const 256)) (v128.const i64x2 0xffffffffb0a09080 0xfffffffff0e0d0c0)) +(assert_return (invoke "i64x2.load32x2_u" (i32.const 256)) (v128.const i64x2 0x00000000b0a09080 0x00000000f0e0d0c0)) (assert_return (invoke "v128.load32_zero" (i32.const 256)) (v128.const i32x4 0xb0a09080 0 0 0)) (assert_return (invoke "v128.load64_zero" (i32.const 256)) (v128.const i64x2 0xf0e0d0c0b0a09080 0)) (assert_return - (invoke "i8x16.swizzle" + (invoke "v8x16.swizzle" (v128.const i8x16 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5 0xf6 0xf7 0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff) (v128.const i8x16 0 4 8 12 16 255 129 128 127 17 15 13 12 8 4 0) ) (v128.const i8x16 0xf0 0xf4 0xf8 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0xff 0xfd 0xfc 0xf8 0xf4 0xf0) ) - -(assert_return (invoke "f64x2.convert_low_i32x4_s" (v128.const i32x4 1 -2147483648 0 0)) (v128.const f64x2 1.0 -2147483648)) -(assert_return (invoke "f64x2.convert_low_i32x4_u" (v128.const i32x4 -2147483648 0xffffffff 0 0)) (v128.const f64x2 2147483648 4294967295.0)) -(assert_return (invoke "i32x4.trunc_sat_f64x2_s_zero" (v128.const f64x2 -inf 4294967296.0)) (v128.const i32x4 -2147483648 2147483647 0 0)) -(assert_return (invoke "i32x4.trunc_sat_f64x2_u_zero" (v128.const f64x2 -inf 4294967296.0)) (v128.const i32x4 0 4294967295 0 0)) -(assert_return - (invoke "f32x4.demote_f64x2_zero" - (v128.const f64x2 0x1.fffffe0000000p-127 -0x1.6972b30cfb562p+1) - ) - (v128.const f32x4 0x1p-126 -0x1.6972b4p+1 0 0) -) -(assert_return - (invoke "f64x2.promote_low_f32x4" - (v128.const f32x4 -0x1p-149 0x1.8f867ep+125 0 0) - ) - (v128.const f64x2 -0x1p-149 6.6382536710104395e+37) -) diff -Nru binaryen-108/test/spec/struct.wast binaryen-99/test/spec/struct.wast --- binaryen-108/test/spec/struct.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/struct.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -;; Binding structure - -(module - (type $s0 (struct (field (ref 0) (ref 1) (ref $s0) (ref $s1)))) - (type $s1 (struct (field (ref 0) (ref 1) (ref $s0) (ref $s1)))) - - (func (param (ref $forward))) - - (type $forward (struct)) -) - -(assert_invalid - (module (type (struct (field (ref 1))))) - "unknown type" -) -(assert_invalid - (module (type (struct (field (mut (ref 1)))))) - "unknown type" -) - - -;; Basic instructions - -(module - (type $vec (struct (field f32) (field $y (mut f32)) (field $z f32))) - - (func $get_0 (param $v (ref $vec)) (result f32) - (struct.get $vec 0 (local.get $v)) - ) - (func (export "get_0") (result f32) - (call $get_0 (struct.new_default_with_rtt $vec (rtt.canon $vec))) - ) - - (func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32) - (struct.set $vec $y (local.get $v) (local.get $y)) - (struct.get $vec $y (local.get $v)) - ) - (func (export "set_get_y") (param $y f32) (result f32) - (call $set_get_y (struct.new_default_with_rtt $vec (rtt.canon $vec)) (local.get $y)) - ) - - (func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32) - (struct.set $vec 1 (local.get $v) (local.get $y)) - (struct.get $vec $y (local.get $v)) - ) - (func (export "set_get_1") (param $y f32) (result f32) - (call $set_get_1 (struct.new_default_with_rtt $vec (rtt.canon $vec)) (local.get $y)) - ) -) - -(assert_return (invoke "get_0") (f32.const 0)) -(assert_return (invoke "set_get_y" (f32.const 7)) (f32.const 7)) -(assert_return (invoke "set_get_1" (f32.const 7)) (f32.const 7)) - -(assert_invalid - (module - (type $s (struct (field i64))) - (func (export "struct.set-immutable") (param $s (ref $s)) - (struct.set $s 0 (local.get $s) (i64.const 1)) - ) - ) - "field is immutable" -) - - -;; Null dereference - -(module - (type $t (struct (field i32) (field (mut i32)))) - (func (export "struct.get-null") - (local (ref null $t)) (drop (struct.get $t 1 (local.get 0))) - ) - (func (export "struct.set-null") - (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0)) - ) -) - -(assert_trap (invoke "struct.get-null") "null structure") -(assert_trap (invoke "struct.set-null") "null structure") - -(assert_invalid - (module - (type $t (struct (field i32) (field (mut i32)))) - (func (export "struct.new-null") - (local (ref null (rtt $t))) (drop (struct.new $t (i32.const 1) (i32.const 2) (local.get 0))) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (type $t (struct (field i32) (field (mut i32)))) - (func (export "struct.new_default-null") - (local (ref null (rtt $t))) (drop (struct.new_default_with_rtt $t (local.get 0))) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (type $A (struct (field i32))) - (type $B (struct (field i64))) - (global $glob (rtt $A) (rtt.sub $A (rtt.canon $B))) - ) - "invalid rtt" -) - -(assert_invalid - (module - (type $vec (struct (field i32))) - (func $test - (drop - ;; too many arguments - (struct.new_with_rtt $vec (i32.const 1) (i32.const 2) (rtt.canon $vec)) - ) - ) - ) - "invalid number of arguments to struct.new" -) - -(assert_invalid - (module - (type $vec (struct (field i32) (field i32))) - (func $test - (drop - ;; too few arguments - (struct.new_with_rtt $vec (i32.const 1) (rtt.canon $vec)) - ) - ) - ) - "invalid number of arguments to struct.new" -) diff -Nru binaryen-108/test/spec/table_get.wast binaryen-99/test/spec/table_get.wast --- binaryen-108/test/spec/table_get.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/table_get.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -(module - (table $t2 2 externref) - (table $t3 3 funcref) - (elem (table $t3) (i32.const 1) func $dummy) - (func $dummy) - - (func (export "get-externref") (param $i i32) (result externref) - (table.get $t2 (local.get $i)) - ) - (func $f3 (export "get-funcref") (param $i i32) (result funcref) - (table.get $t3 (local.get $i)) - ) - - (func (export "is_null-funcref") (param $i i32) (result i32) - (ref.is_null (call $f3 (local.get $i))) - ) -) - -(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) - -(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) -(assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0)) - -(assert_trap (invoke "get-externref" (i32.const 2)) "out of bounds") -(assert_trap (invoke "get-funcref" (i32.const 3)) "out of bounds") -(assert_trap (invoke "get-externref" (i32.const -1)) "out of bounds") -(assert_trap (invoke "get-funcref" (i32.const -1)) "out of bounds") - - -;; Type errors - -(assert_invalid - (module - (table $t 10 externref) - (func $type-index-empty-vs-i32 (result externref) - (table.get $t) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 10 externref) - (func $type-index-f32-vs-i32 (result externref) - (table.get $t (f32.const 1)) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (table $t 10 externref) - (func $type-result-externref-vs-empty - (table.get $t (i32.const 0)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 10 externref) - (func $type-result-externref-vs-funcref (result funcref) - (table.get $t (i32.const 1)) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (table $t1 1 funcref) - (table $t2 1 externref) - (func $type-result-externref-vs-funcref-multi (result funcref) - (table.get $t2 (i32.const 0)) - ) - ) - "type mismatch" -) diff -Nru binaryen-108/test/spec/table_grow.wast binaryen-99/test/spec/table_grow.wast --- binaryen-108/test/spec/table_grow.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/table_grow.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,174 +0,0 @@ -(module - (table $t 0 externref) - - (func (export "get") (param $i i32) (result externref) (table.get $t (local.get $i))) - (func (export "set") (param $i i32) (param $r externref) (table.set $t (local.get $i) (local.get $r))) - - (func (export "grow") (param $sz i32) (param $init externref) (result i32) - (table.grow $t (local.get $init) (local.get $sz)) - ) - (func (export "size") (result i32) (table.size $t)) -) - -(assert_return (invoke "size") (i32.const 0)) -;; (assert_trap (invoke "set" (i32.const 0) (ref.extern 2)) "out of bounds table access") -(assert_trap (invoke "get" (i32.const 0)) "out of bounds table access") - -(assert_return (invoke "grow" (i32.const 1) (ref.null extern)) (i32.const 0)) -(assert_return (invoke "size") (i32.const 1)) -(assert_return (invoke "get" (i32.const 0)) (ref.null extern)) -;; (assert_return (invoke "set" (i32.const 0) (ref.extern 2))) -;; (assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) -;; (assert_trap (invoke "set" (i32.const 1) (ref.extern 2)) "out of bounds table access") -;; (assert_trap (invoke "get" (i32.const 1)) "out of bounds table access") - -;; (assert_return (invoke "grow" (i32.const 4) (ref.extern 3)) (i32.const 1)) -;; (assert_return (invoke "size") (i32.const 5)) -;; (assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) -;; (assert_return (invoke "set" (i32.const 0) (ref.extern 2))) -;; (assert_return (invoke "get" (i32.const 0)) (ref.extern 2)) -;; (assert_return (invoke "get" (i32.const 1)) (ref.extern 3)) -;; (assert_return (invoke "get" (i32.const 4)) (ref.extern 3)) -;; (assert_return (invoke "set" (i32.const 4) (ref.extern 4))) -;; (assert_return (invoke "get" (i32.const 4)) (ref.extern 4)) -;; (assert_trap (invoke "set" (i32.const 5) (ref.extern 2)) "out of bounds table access") -;; (assert_trap (invoke "get" (i32.const 5)) "out of bounds table access") - - -;; Reject growing to size outside i32 value range -;; TODO: parse error -;; (module -;; (table $t 0x10 funcref) -;; (elem declare func $f) -;; (func $f (export "grow") (result i32) -;; (table.grow $t (ref.func $f) (i32.const 0xffff_fff0)) -;; ) -;; ) - -;; (assert_return (invoke "grow") (i32.const -1)) - - -(module - (table $t 0 externref) - (func (export "grow") (param i32) (result i32) - (table.grow $t (ref.null extern) (local.get 0)) - ) -) - -(assert_return (invoke "grow" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) -(assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) -(assert_return (invoke "grow" (i32.const 2)) (i32.const 1)) -(assert_return (invoke "grow" (i32.const 800)) (i32.const 3)) - - -(module - (table $t 0 10 externref) - (func (export "grow") (param i32) (result i32) - (table.grow $t (ref.null extern) (local.get 0)) - ) -) - -(assert_return (invoke "grow" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) -(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) -(assert_return (invoke "grow" (i32.const 2)) (i32.const 2)) -(assert_return (invoke "grow" (i32.const 6)) (i32.const 4)) -(assert_return (invoke "grow" (i32.const 0)) (i32.const 10)) -(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) -(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1)) - - -(module - (table $t 10 funcref) - (func (export "grow") (param i32) (result i32) - (table.grow $t (ref.null func) (local.get 0)) - ) - (elem declare func 1) - (func (export "check-table-null") (param i32 i32) (result funcref) - (local funcref) - (local.set 2 (ref.func 1)) - (block - (loop - (local.set 2 (table.get $t (local.get 0))) - (br_if 1 (i32.eqz (ref.is_null (local.get 2)))) - (br_if 1 (i32.ge_u (local.get 0) (local.get 1))) - (local.set 0 (i32.add (local.get 0) (i32.const 1))) - (br_if 0 (i32.le_u (local.get 0) (local.get 1))) - ) - ) - (local.get 2) - ) -) - -(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null func)) -(assert_return (invoke "grow" (i32.const 10)) (i32.const 10)) -(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null func)) - - -;; Type errors - -(assert_invalid - (module - (table $t 0 externref) - (func $type-init-size-empty-vs-i32-externref (result i32) - (table.grow $t) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 0 externref) - (func $type-size-empty-vs-i32 (result i32) - (table.grow $t (ref.null extern)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 0 externref) - (func $type-init-empty-vs-externref (result i32) - (table.grow $t (i32.const 1)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 0 externref) - (func $type-size-f32-vs-i32 (result i32) - (table.grow $t (ref.null extern) (f32.const 1)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 0 funcref) - (func $type-init-externref-vs-funcref (param $r externref) (result i32) - (table.grow $t (local.get $r) (i32.const 1)) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (table $t 1 externref) - (func $type-result-i32-vs-empty - (table.grow $t (ref.null extern) (i32.const 0)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 1 externref) - (func $type-result-i32-vs-f32 (result f32) - (table.grow $t (ref.null extern) (i32.const 0)) - ) - ) - "type mismatch" -) diff -Nru binaryen-108/test/spec/table_set.wast binaryen-99/test/spec/table_set.wast --- binaryen-108/test/spec/table_set.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/table_set.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,119 +0,0 @@ -(module - (table $t2 1 externref) - (table $t3 2 funcref) - (elem (table $t3) (i32.const 1) func $dummy) - (func $dummy) - - (func (export "get-externref") (param $i i32) (result externref) - (table.get $t2 (local.get $i)) - ) - (func $f3 (export "get-funcref") (param $i i32) (result funcref) - (table.get $t3 (local.get $i)) - ) - - (func (export "set-externref") (param $i i32) (param $r externref) - (table.set $t2 (local.get $i) (local.get $r)) - ) - (func (export "set-funcref") (param $i i32) (param $r funcref) - (table.set $t3 (local.get $i) (local.get $r)) - ) - (func (export "set-funcref-from") (param $i i32) (param $j i32) - (table.set $t3 (local.get $i) (table.get $t3 (local.get $j))) - ) - - (func (export "is_null-funcref") (param $i i32) (result i32) - (ref.is_null (call $f3 (local.get $i))) - ) -) - -(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) -;; (assert_return (invoke "set-externref" (i32.const 0) (ref.extern 1))) -;; (assert_return (invoke "get-externref" (i32.const 0)) (ref.extern 1)) -(assert_return (invoke "set-externref" (i32.const 0) (ref.null extern))) -(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern)) - -(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) -(assert_return (invoke "set-funcref-from" (i32.const 0) (i32.const 1))) -(assert_return (invoke "is_null-funcref" (i32.const 0)) (i32.const 0)) -(assert_return (invoke "set-funcref" (i32.const 0) (ref.null func))) -(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func)) - -(assert_trap (invoke "set-externref" (i32.const 2) (ref.null extern)) "out of bounds table access") -(assert_trap (invoke "set-funcref" (i32.const 3) (ref.null func)) "out of bounds table access") -(assert_trap (invoke "set-externref" (i32.const -1) (ref.null extern)) "out of bounds table access") -(assert_trap (invoke "set-funcref" (i32.const -1) (ref.null func)) "out of bounds table access") - -;; (assert_trap (invoke "set-externref" (i32.const 2) (ref.extern 0)) "out of bounds table access") -(assert_trap (invoke "set-funcref-from" (i32.const 3) (i32.const 1)) "out of bounds table access") -;; (assert_trap (invoke "set-externref" (i32.const -1) (ref.extern 0)) "out of bounds table access") -(assert_trap (invoke "set-funcref-from" (i32.const -1) (i32.const 1)) "out of bounds table access") - - -;; Type errors - -(assert_invalid - (module - (table $t 10 externref) - (func $type-index-value-empty-vs-i32-externref - (table.set $t) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 10 externref) - (func $type-index-empty-vs-i32 - (table.set $t (ref.null extern)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 10 externref) - (func $type-value-empty-vs-externref - (table.set $t (i32.const 1)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 10 externref) - (func $type-size-f32-vs-i32 - (table.set $t (f32.const 1) (ref.null extern)) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 10 funcref) - (func $type-value-externref-vs-funcref (param $r externref) - (table.set $t (i32.const 1) (local.get $r)) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (table $t1 1 externref) - (table $t2 1 funcref) - (func $type-value-externref-vs-funcref-multi (param $r externref) - (table.set $t2 (i32.const 0) (local.get $r)) - ) - ) - "type mismatch" -) - -(assert_invalid - (module - (table $t 10 externref) - (func $type-result-empty-vs-num (result i32) - (table.set $t (i32.const 0) (ref.null extern)) - ) - ) - "type mismatch" -) diff -Nru binaryen-108/test/spec/table_size.wast binaryen-99/test/spec/table_size.wast --- binaryen-108/test/spec/table_size.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/table_size.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -(module - (table $t0 0 externref) - (table $t1 1 externref) - (table $t2 0 2 externref) - (table $t3 3 8 externref) - - (func (export "size-t0") (result i32) (table.size $t0)) - (func (export "size-t1") (result i32) (table.size $t1)) - (func (export "size-t2") (result i32) (table.size $t2)) - (func (export "size-t3") (result i32) (table.size $t3)) - - (func (export "grow-t0") (param $sz i32) - (drop (table.grow $t0 (ref.null extern) (local.get $sz))) - ) - (func (export "grow-t1") (param $sz i32) - (drop (table.grow $t1 (ref.null extern) (local.get $sz))) - ) - (func (export "grow-t2") (param $sz i32) - (drop (table.grow $t2 (ref.null extern) (local.get $sz))) - ) - (func (export "grow-t3") (param $sz i32) - (drop (table.grow $t3 (ref.null extern) (local.get $sz))) - ) -) - -(assert_return (invoke "size-t0") (i32.const 0)) -(assert_return (invoke "grow-t0" (i32.const 1))) -(assert_return (invoke "size-t0") (i32.const 1)) -(assert_return (invoke "grow-t0" (i32.const 4))) -(assert_return (invoke "size-t0") (i32.const 5)) -(assert_return (invoke "grow-t0" (i32.const 0))) -(assert_return (invoke "size-t0") (i32.const 5)) - -(assert_return (invoke "size-t1") (i32.const 1)) -(assert_return (invoke "grow-t1" (i32.const 1))) -(assert_return (invoke "size-t1") (i32.const 2)) -(assert_return (invoke "grow-t1" (i32.const 4))) -(assert_return (invoke "size-t1") (i32.const 6)) -(assert_return (invoke "grow-t1" (i32.const 0))) -(assert_return (invoke "size-t1") (i32.const 6)) - -(assert_return (invoke "size-t2") (i32.const 0)) -(assert_return (invoke "grow-t2" (i32.const 3))) -(assert_return (invoke "size-t2") (i32.const 0)) -(assert_return (invoke "grow-t2" (i32.const 1))) -(assert_return (invoke "size-t2") (i32.const 1)) -(assert_return (invoke "grow-t2" (i32.const 0))) -(assert_return (invoke "size-t2") (i32.const 1)) -(assert_return (invoke "grow-t2" (i32.const 4))) -(assert_return (invoke "size-t2") (i32.const 1)) -(assert_return (invoke "grow-t2" (i32.const 1))) -(assert_return (invoke "size-t2") (i32.const 2)) - -(assert_return (invoke "size-t3") (i32.const 3)) -(assert_return (invoke "grow-t3" (i32.const 1))) -(assert_return (invoke "size-t3") (i32.const 4)) -(assert_return (invoke "grow-t3" (i32.const 3))) -(assert_return (invoke "size-t3") (i32.const 7)) -(assert_return (invoke "grow-t3" (i32.const 0))) -(assert_return (invoke "size-t3") (i32.const 7)) -(assert_return (invoke "grow-t3" (i32.const 2))) -(assert_return (invoke "size-t3") (i32.const 7)) -(assert_return (invoke "grow-t3" (i32.const 1))) -(assert_return (invoke "size-t3") (i32.const 8)) - - -;; Type errors - -(assert_invalid - (module - (table $t 1 externref) - (func $type-result-i32-vs-empty - (table.size $t) - ) - ) - "type mismatch" -) -(assert_invalid - (module - (table $t 1 externref) - (func $type-result-i32-vs-f32 (result f32) - (table.size $t) - ) - ) - "type mismatch" -) diff -Nru binaryen-108/test/spec/table.wast binaryen-99/test/spec/table.wast --- binaryen-108/test/spec/table.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/table.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ - -;; Test table section structure - -(module (table 0 funcref)) -(module (table 0 (ref null func))) -(module (table 1 funcref)) -(module (table 0 0 funcref)) -(module (table 0 1 funcref)) -(module (table 0 1 (ref null func))) -(module (table 1 256 funcref)) -(module (table 0 65536 externref)) -;; (module (table 0 0xffff_ffff funcref)) - -(module (table 0 funcref) (table 0 funcref)) -(module (table (import "spectest" "table") 0 funcref) (table 0 funcref)) - -(assert_invalid (module (elem (i32.const 0))) "unknown table") -(assert_invalid (module (elem (i32.const 0) $f) (func $f)) "unknown table") - - -(assert_invalid - (module (table 1 0 funcref)) - "size minimum must not be greater than maximum" -) diff -Nru binaryen-108/test/spec/tags.wast binaryen-99/test/spec/tags.wast --- binaryen-108/test/spec/tags.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/tags.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -;; Test tags - -(module - (tag (param i32)) - (tag $e (param i32 f32)) - - (tag $e-params0 (param i32 f32)) - (tag $e-params1 (param i32) (param f32)) - - (tag $e-export (export "ex0") (param i32)) - (tag $e-import (import "env" "im0") (param i32)) - - (import "env" "im1" (tag (param i32 f32))) - (export "ex1" (tag $e)) -) - -(assert_invalid - (module (tag $e (param i32) (result i32))) - "Tag type's result type should be none" -) - -(assert_invalid - (module (tag $e (attr 1) (param i32))) - "Currently only attribute 0 is supported" -) - -(assert_invalid - (module - (type $t (param i32)) - (tag $e (type $t) (param i32 f32)) - ) - "type and param don't match" -) diff -Nru binaryen-108/test/spec/tuples.wast binaryen-99/test/spec/tuples.wast --- binaryen-108/test/spec/tuples.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/spec/tuples.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -(assert_invalid - (module - (func $foo - (local $temp ((ref func) i32)) - ) - ) - "var must be defaultable" -) - diff -Nru binaryen-108/test/subtypes.wast binaryen-99/test/subtypes.wast --- binaryen-108/test/subtypes.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/subtypes.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -;; Test that we can roundtrip struct and array types -(module - ;; Arrays - (type $vector-i32 (array i32)) - - (type $vector-i31 (array (ref i31))) - (type $vector-any (array (ref any))) - - ;; Structs - (type $struct-i31 (struct - (field (ref i31)) - )) - (type $struct-any (struct - (field (ref any)) - )) - (type $struct-i31_any (struct - (field (ref i31)) - (field (ref any)) - )) - - ;; Recursive structs - (type $struct-rec-one (struct - (field (ref $struct-rec-one)) - )) - (type $struct-rec-two (struct - (field (ref $struct-rec-two)) - (field (ref $struct-rec-two)) - )) - - (func $foo (param $no-null (ref $vector-i32)) - (param $yes-null (ref null $vector-i32)) - ;; ok to set a non-nullable reference to a nullable target - (local.set $yes-null (local.get $no-null)) - ) - - (func $bar (param $v-i31 (ref $vector-i31)) - (param $v-any (ref $vector-any)) - ;; ok to set a vector of (immutable) i31s to a vector of anyies - (local.set $v-any (local.get $v-i31)) - ) - - (func $baz (param $s-i31 (ref $struct-i31)) - (param $s-any (ref $struct-any)) - ;; ok to set a struct of an (immutable) i31 to a one of an any - (local.set $s-any (local.get $s-i31)) - ) - - (func $boo (param $s-i31 (ref $struct-i31)) - (param $s-i31_any (ref $struct-i31_any)) - ;; also ok to have extra fields - (local.set $s-i31 (local.get $s-i31_any)) - ) - - (func $coinductive (param $rec-one (ref $struct-rec-one)) - (param $rec-two (ref $struct-rec-two)) - ;; Do not infinitely recurse when determining this subtype relation! - (local.set $rec-one (local.get $rec-two)) - ) -) diff -Nru binaryen-108/test/subtypes.wast.fromBinary binaryen-99/test/subtypes.wast.fromBinary --- binaryen-108/test/subtypes.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/subtypes.wast.fromBinary 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -(module - (type $struct-rec-two (struct (field (ref $struct-rec-two)) (field (ref $struct-rec-two)))) - (type $vector-i32 (array i32)) - (type $struct-i31 (struct (field i31ref))) - (type $struct-rec-one (struct (field (ref $struct-rec-one)))) - (type $ref|$vector-i32|_ref?|$vector-i32|_=>_none (func (param (ref $vector-i32) (ref null $vector-i32)))) - (type $ref|$vector-i31|_ref|$vector-any|_=>_none (func (param (ref $vector-i31) (ref $vector-any)))) - (type $ref|$struct-i31|_ref|$struct-any|_=>_none (func (param (ref $struct-i31) (ref $struct-any)))) - (type $ref|$struct-i31|_ref|$struct-i31_any|_=>_none (func (param (ref $struct-i31) (ref $struct-i31_any)))) - (type $ref|$struct-rec-one|_ref|$struct-rec-two|_=>_none (func (param (ref $struct-rec-one) (ref $struct-rec-two)))) - (type $vector-i31 (array i31ref)) - (type $vector-any (array (ref any))) - (type $struct-any (struct (field (ref any)))) - (type $struct-i31_any (struct (field i31ref) (field (ref any)))) - (func $foo (param $no-null (ref $vector-i32)) (param $yes-null (ref null $vector-i32)) - (local.set $yes-null - (local.get $no-null) - ) - ) - (func $bar (param $v-i31 (ref $vector-i31)) (param $v-any (ref $vector-any)) - (local.set $v-any - (local.get $v-i31) - ) - ) - (func $baz (param $s-i31 (ref $struct-i31)) (param $s-any (ref $struct-any)) - (local.set $s-any - (local.get $s-i31) - ) - ) - (func $boo (param $s-i31 (ref $struct-i31)) (param $s-i31_any (ref $struct-i31_any)) - (local.set $s-i31 - (local.get $s-i31_any) - ) - ) - (func $coinductive (param $rec-one (ref $struct-rec-one)) (param $rec-two (ref $struct-rec-two)) - (local.set $rec-one - (local.get $rec-two) - ) - ) -) - diff -Nru binaryen-108/test/subtypes.wast.fromBinary.noDebugInfo binaryen-99/test/subtypes.wast.fromBinary.noDebugInfo --- binaryen-108/test/subtypes.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/subtypes.wast.fromBinary.noDebugInfo 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -(module - (type ${ref|...0|_ref|...0|} (struct (field (ref ${ref|...0|_ref|...0|})) (field (ref ${ref|...0|_ref|...0|})))) - (type $[i32] (array i32)) - (type ${i31ref} (struct (field i31ref))) - (type ${ref|...0|} (struct (field (ref ${ref|...0|})))) - (type $ref|[i32]|_ref?|[i32]|_=>_none (func (param (ref $[i32]) (ref null $[i32])))) - (type $ref|[i31ref]|_ref|[ref|any|]|_=>_none (func (param (ref $[i31ref]) (ref $[ref|any|])))) - (type $ref|{i31ref}|_ref|{ref|any|}|_=>_none (func (param (ref ${i31ref}) (ref ${ref|any|})))) - (type $ref|{i31ref}|_ref|{i31ref_ref|any|}|_=>_none (func (param (ref ${i31ref}) (ref ${i31ref_ref|any|})))) - (type $ref|{ref|...0|}|_ref|{ref|...0|_ref|...0|}|_=>_none (func (param (ref ${ref|...0|}) (ref ${ref|...0|_ref|...0|})))) - (type $[i31ref] (array i31ref)) - (type $[ref|any|] (array (ref any))) - (type ${ref|any|} (struct (field (ref any)))) - (type ${i31ref_ref|any|} (struct (field i31ref) (field (ref any)))) - (func $0 (param $0 (ref $[i32])) (param $1 (ref null $[i32])) - (local.set $1 - (local.get $0) - ) - ) - (func $1 (param $0 (ref $[i31ref])) (param $1 (ref $[ref|any|])) - (local.set $1 - (local.get $0) - ) - ) - (func $2 (param $0 (ref ${i31ref})) (param $1 (ref ${ref|any|})) - (local.set $1 - (local.get $0) - ) - ) - (func $3 (param $0 (ref ${i31ref})) (param $1 (ref ${i31ref_ref|any|})) - (local.set $0 - (local.get $1) - ) - ) - (func $4 (param $0 (ref ${ref|...0|})) (param $1 (ref ${ref|...0|_ref|...0|})) - (local.set $0 - (local.get $1) - ) - ) -) - diff -Nru binaryen-108/test/subtypes.wast.from-wast binaryen-99/test/subtypes.wast.from-wast --- binaryen-108/test/subtypes.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/subtypes.wast.from-wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -(module - (type $struct-rec-two (struct (field (ref $struct-rec-two)) (field (ref $struct-rec-two)))) - (type $vector-i32 (array i32)) - (type $struct-i31 (struct (field i31ref))) - (type $struct-rec-one (struct (field (ref $struct-rec-one)))) - (type $ref|$vector-i32|_ref?|$vector-i32|_=>_none (func (param (ref $vector-i32) (ref null $vector-i32)))) - (type $ref|$vector-i31|_ref|$vector-any|_=>_none (func (param (ref $vector-i31) (ref $vector-any)))) - (type $ref|$struct-i31|_ref|$struct-any|_=>_none (func (param (ref $struct-i31) (ref $struct-any)))) - (type $ref|$struct-i31|_ref|$struct-i31_any|_=>_none (func (param (ref $struct-i31) (ref $struct-i31_any)))) - (type $ref|$struct-rec-one|_ref|$struct-rec-two|_=>_none (func (param (ref $struct-rec-one) (ref $struct-rec-two)))) - (type $vector-i31 (array i31ref)) - (type $vector-any (array (ref any))) - (type $struct-any (struct (field (ref any)))) - (type $struct-i31_any (struct (field i31ref) (field (ref any)))) - (func $foo (param $no-null (ref $vector-i32)) (param $yes-null (ref null $vector-i32)) - (local.set $yes-null - (local.get $no-null) - ) - ) - (func $bar (param $v-i31 (ref $vector-i31)) (param $v-any (ref $vector-any)) - (local.set $v-any - (local.get $v-i31) - ) - ) - (func $baz (param $s-i31 (ref $struct-i31)) (param $s-any (ref $struct-any)) - (local.set $s-any - (local.get $s-i31) - ) - ) - (func $boo (param $s-i31 (ref $struct-i31)) (param $s-i31_any (ref $struct-i31_any)) - (local.set $s-i31 - (local.get $s-i31_any) - ) - ) - (func $coinductive (param $rec-one (ref $struct-rec-one)) (param $rec-two (ref $struct-rec-two)) - (local.set $rec-one - (local.get $rec-two) - ) - ) -) diff -Nru binaryen-108/test/table-import.wast.fromBinary binaryen-99/test/table-import.wast.fromBinary --- binaryen-108/test/table-import.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/table-import.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (import "env" "table" (table $timport$0 1 1 funcref)) - (memory $0 0) (elem (i32.const 0) $foo) + (memory $0 0) (func $foo (nop) ) diff -Nru binaryen-108/test/table-import.wast.fromBinary.noDebugInfo binaryen-99/test/table-import.wast.fromBinary.noDebugInfo --- binaryen-108/test/table-import.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/table-import.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module (type $none_=>_none (func)) (import "env" "table" (table $timport$0 1 1 funcref)) - (memory $0 0) (elem (i32.const 0) $0) + (memory $0 0) (func $0 (nop) ) diff -Nru binaryen-108/test/table-import.wast.from-wast binaryen-99/test/table-import.wast.from-wast --- binaryen-108/test/table-import.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/table-import.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,8 @@ (module - (type $0 (func)) + (type $none_=>_none (func)) (import "env" "table" (table $timport$0 1 1 funcref)) - (memory $0 0) (elem (i32.const 0) $foo) + (memory $0 0) (func $foo (nop) ) diff -Nru binaryen-108/test/tags.wast binaryen-99/test/tags.wast --- binaryen-108/test/tags.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tags.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -;; Test tags - -(module - (tag (param i32)) - (tag $e (param i32 f32)) - (tag $empty) - - (tag $e-params0 (param i32 f32)) - (tag $e-params1 (param i32) (param f32)) - - (tag $e-export (export "ex0") (param i32)) - (tag $e-import (import "env" "im0") (param i32)) - - (import "env" "im1" (tag (param i32 f32))) - (export "ex1" (tag $e)) -) diff -Nru binaryen-108/test/tags.wast.fromBinary binaryen-99/test/tags.wast.fromBinary --- binaryen-108/test/tags.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tags.wast.fromBinary 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -(module - (type $i32_f32_=>_none (func (param i32 f32))) - (type $i32_=>_none (func (param i32))) - (type $none_=>_none (func)) - (import "env" "im0" (tag $eimport$0 (param i32))) - (import "env" "im1" (tag $eimport$1 (param i32 f32))) - (tag $tag$0 (param i32)) - (tag $tag$1 (param i32 f32)) - (tag $tag$2 (param)) - (tag $tag$3 (param i32 f32)) - (tag $tag$4 (param i32 f32)) - (tag $tag$5 (param i32)) - (export "ex1" (tag $tag$1)) -) - diff -Nru binaryen-108/test/tags.wast.fromBinary.noDebugInfo binaryen-99/test/tags.wast.fromBinary.noDebugInfo --- binaryen-108/test/tags.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tags.wast.fromBinary.noDebugInfo 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -(module - (type $i32_f32_=>_none (func (param i32 f32))) - (type $i32_=>_none (func (param i32))) - (type $none_=>_none (func)) - (import "env" "im0" (tag $eimport$0 (param i32))) - (import "env" "im1" (tag $eimport$1 (param i32 f32))) - (tag $tag$0 (param i32)) - (tag $tag$1 (param i32 f32)) - (tag $tag$2 (param)) - (tag $tag$3 (param i32 f32)) - (tag $tag$4 (param i32 f32)) - (tag $tag$5 (param i32)) - (export "ex1" (tag $tag$1)) -) - diff -Nru binaryen-108/test/tags.wast.from-wast binaryen-99/test/tags.wast.from-wast --- binaryen-108/test/tags.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tags.wast.from-wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -(module - (type $i32_f32_=>_none (func (param i32 f32))) - (type $i32_=>_none (func (param i32))) - (type $none_=>_none (func)) - (import "env" "im0" (tag $e-import (param i32))) - (import "env" "im1" (tag $eimport$1 (param i32 f32))) - (tag $2 (param i32)) - (tag $e (param i32 f32)) - (tag $empty (param)) - (tag $e-params0 (param i32 f32)) - (tag $e-params1 (param i32 f32)) - (tag $e-export (param i32)) - (export "ex1" (tag $e)) -) diff -Nru binaryen-108/test/tail-call.wast binaryen-99/test/tail-call.wast --- binaryen-108/test/tail-call.wast 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/tail-call.wast 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,11 @@ +(module + (type $void (func)) + (table 1 1 funcref) + (elem (i32.const 0) $foo) + (func $foo + (return_call $bar) + ) + (func $bar + (return_call_indirect (type $void) (i32.const 0)) + ) +) \ No newline at end of file diff -Nru binaryen-108/test/tail-call.wast.fromBinary binaryen-99/test/tail-call.wast.fromBinary --- binaryen-108/test/tail-call.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tail-call.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $void (func)) + (type $none_=>_none (func)) (table $0 1 1 funcref) (elem (i32.const 0) $foo) (func $foo (return_call $bar) ) (func $bar - (return_call_indirect $0 (type $void) + (return_call_indirect (type $none_=>_none) (i32.const 0) ) ) diff -Nru binaryen-108/test/tail-call.wast.fromBinary.noDebugInfo binaryen-99/test/tail-call.wast.fromBinary.noDebugInfo --- binaryen-108/test/tail-call.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tail-call.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -6,7 +6,7 @@ (return_call $1) ) (func $1 - (return_call_indirect $0 (type $none_=>_none) + (return_call_indirect (type $none_=>_none) (i32.const 0) ) ) diff -Nru binaryen-108/test/tail-call.wast.from-wast binaryen-99/test/tail-call.wast.from-wast --- binaryen-108/test/tail-call.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/tail-call.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,12 +1,12 @@ (module - (type $void (func)) + (type $none_=>_none (func)) (table $0 1 1 funcref) (elem (i32.const 0) $foo) (func $foo (return_call $bar) ) (func $bar - (return_call_indirect $0 (type $void) + (return_call_indirect (type $none_=>_none) (i32.const 0) ) ) Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/try-delegate.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/try-delegate.wasm differ diff -Nru binaryen-108/test/try-delegate.wasm.fromBinary binaryen-99/test/try-delegate.wasm.fromBinary --- binaryen-108/test/try-delegate.wasm.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/try-delegate.wasm.fromBinary 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -(module - (type $none_=>_none (func)) - (tag $tag$0 (param)) - (func $0 - (try $label$6 - (do - (block $label$1 - (try $label$4 - (do - ) - (delegate $label$6) - ) - ) - ) - (catch $tag$0 - ) - ) - ) - (func $1 - (try $label$9 - (do - (block $label$1 - (try $label$7 - (do - ) - (catch $tag$0 - (drop - (i32.const 0) - ) - (try $label$6 - (do - ) - (delegate $label$9) - ) - ) - ) - ) - ) - (catch $tag$0 - ) - ) - ) -) - diff -Nru binaryen-108/test/typed-function-references.wast binaryen-99/test/typed-function-references.wast --- binaryen-108/test/typed-function-references.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/typed-function-references.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,10 +1,7 @@ (module ;; inline ref type in result - (type $_=>_eqref (func (result eqref))) - (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $_=>_eqref)))) + (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null (func (result eqref)))))) (type $=>eqref (func (result eqref))) - (type $=>anyref (func (result anyref))) - (type $mixed_results (func (result anyref f32 anyref f32))) (type $i32-i32 (func (param i32) (result i32))) @@ -28,17 +25,20 @@ (local.set $f (ref.func $call-ref-more)) (call_ref (i32.const 42) (local.get $f)) ) - (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) + (func $ref-in-sig (param $0 f64) (result (ref null (func (result eqref)))) (ref.null $=>eqref) ) (func $type-only-in-tuple-local - (local $x (i32 (ref null $=>anyref) f64)) + (local $x (i32 (ref null (func (result anyref))) f64)) ) (func $type-only-in-tuple-block (drop - (block (result i32 (ref null $mixed_results) f64) + (block (result i32 (ref null (func (result anyref f32 anyref f32))) f64) (unreachable) ) ) ) + (func $nested-type-only-there (result (ref (func (result (ref (func (param i32 i32 i32 i32 i32))))))) + (unreachable) + ) ) diff -Nru binaryen-108/test/typed-function-references.wast.fromBinary binaryen-99/test/typed-function-references.wast.fromBinary --- binaryen-108/test/typed-function-references.wast.fromBinary 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/typed-function-references.wast.fromBinary 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,16 @@ (module (type $none_=>_none (func)) - (type $i32-i32 (func (param i32) (result i32))) - (type $mixed_results (func (result anyref f32 anyref f32))) - (type $=>eqref (func (result eqref))) - (type $ref|$i32-i32|_=>_i32 (func (param (ref $i32-i32)) (result i32))) - (type $ref?|$i32-i32|_=>_i32 (func (param (ref null $i32-i32)) (result i32))) + (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_eqref (func (result eqref))) + (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) (type $none_=>_i32 (func (result i32))) - (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref)))) - (type $=>anyref (func (result anyref))) - (type $none_=>_i32_ref?|$mixed_results|_f64 (func (result i32 (ref null $mixed_results) f64))) - (elem declare func $call-ref $call-ref-more) + (type $none_=>_anyref (func (result anyref))) + (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) + (type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64))) + (type $none_=>_ref?|i32_i32_i32_i32_i32_->_none| (func (result (ref null $i32_i32_i32_i32_i32_=>_none)))) + (type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref)))) + (type $none_=>_ref?|none_->_ref?|i32_i32_i32_i32_i32_->_none|| (func (result (ref null $none_=>_ref?|i32_i32_i32_i32_i32_->_none|)))) (func $call-ref (call_ref (ref.func $call-ref) @@ -26,20 +27,20 @@ (ref.func $call-ref-more) ) ) - (func $call_from-param (param $f (ref $i32-i32)) (result i32) + (func $call_from-param (param $f (ref null $i32_=>_i32)) (result i32) (call_ref (i32.const 42) (local.get $f) ) ) - (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) + (func $call_from-param-null (param $f (ref null $i32_=>_i32)) (result i32) (call_ref (i32.const 42) (local.get $f) ) ) (func $call_from-local-null (result i32) - (local $f (ref null $i32-i32)) + (local $f (ref null $i32_=>_i32)) (local.set $f (ref.func $call-ref-more) ) @@ -48,21 +49,21 @@ (local.get $f) ) ) - (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) - (ref.null $=>eqref) + (func $ref-in-sig (param $0 f64) (result (ref null $none_=>_eqref)) + (ref.null $none_=>_eqref) ) (func $type-only-in-tuple-local (local $x i32) - (local $1 (ref null $=>anyref)) - (local $2 f64) + (local $1 f64) + (local $2 (ref null $none_=>_anyref)) (nop) ) (func $type-only-in-tuple-block - (local $0 (i32 (ref null $mixed_results) f64)) - (local $1 (ref null $mixed_results)) + (local $0 (i32 (ref null (func (result anyref f32 anyref f32))) f64)) + (local $1 (ref null $none_=>_anyref_f32_anyref_f32)) (local $2 i32) (local.set $0 - (block $label$1 (result i32 (ref null $mixed_results) f64) + (block $label$1 (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64) (unreachable) ) ) @@ -74,7 +75,7 @@ ) ) (drop - (block (result (ref null $mixed_results)) + (block (result (ref null $none_=>_anyref_f32_anyref_f32)) (local.set $1 (tuple.extract 1 (local.get $0) @@ -92,5 +93,8 @@ ) ) ) + (func $nested-type-only-there (result (ref null $none_=>_ref?|i32_i32_i32_i32_i32_->_none|)) + (unreachable) + ) ) diff -Nru binaryen-108/test/typed-function-references.wast.fromBinary.noDebugInfo binaryen-99/test/typed-function-references.wast.fromBinary.noDebugInfo --- binaryen-108/test/typed-function-references.wast.fromBinary.noDebugInfo 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/typed-function-references.wast.fromBinary.noDebugInfo 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,16 @@ (module (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32))) + (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_eqref (func (result eqref))) - (type $ref|i32_->_i32|_=>_i32 (func (param (ref $i32_=>_i32)) (result i32))) - (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) + (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) (type $none_=>_i32 (func (result i32))) - (type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref)))) (type $none_=>_anyref (func (result anyref))) + (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) (type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64))) - (elem declare func $0 $2) + (type $none_=>_ref?|i32_i32_i32_i32_i32_->_none| (func (result (ref null $i32_i32_i32_i32_i32_=>_none)))) + (type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref)))) + (type $none_=>_ref?|none_->_ref?|i32_i32_i32_i32_i32_->_none|| (func (result (ref null $none_=>_ref?|i32_i32_i32_i32_i32_->_none|)))) (func $0 (call_ref (ref.func $0) @@ -26,7 +27,7 @@ (ref.func $2) ) ) - (func $3 (param $0 (ref $i32_=>_i32)) (result i32) + (func $3 (param $0 (ref null $i32_=>_i32)) (result i32) (call_ref (i32.const 42) (local.get $0) @@ -53,12 +54,12 @@ ) (func $7 (local $0 i32) - (local $1 (ref null $none_=>_anyref)) - (local $2 f64) + (local $1 f64) + (local $2 (ref null $none_=>_anyref)) (nop) ) (func $8 - (local $0 (i32 (ref null $none_=>_anyref_f32_anyref_f32) f64)) + (local $0 (i32 (ref null (func (result anyref f32 anyref f32))) f64)) (local $1 (ref null $none_=>_anyref_f32_anyref_f32)) (local $2 i32) (local.set $0 @@ -92,5 +93,8 @@ ) ) ) + (func $9 (result (ref null $none_=>_ref?|i32_i32_i32_i32_i32_->_none|)) + (unreachable) + ) ) diff -Nru binaryen-108/test/typed-function-references.wast.from-wast binaryen-99/test/typed-function-references.wast.from-wast --- binaryen-108/test/typed-function-references.wast.from-wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/typed-function-references.wast.from-wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,15 +1,16 @@ (module (type $none_=>_none (func)) - (type $i32-i32 (func (param i32) (result i32))) - (type $=>eqref (func (result eqref))) - (type $ref|$i32-i32|_=>_i32 (func (param (ref $i32-i32)) (result i32))) - (type $ref?|$i32-i32|_=>_i32 (func (param (ref null $i32-i32)) (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_eqref (func (result eqref))) + (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) (type $none_=>_i32 (func (result i32))) - (type $f64_=>_ref_null<_->_eqref> (func (param f64) (result (ref null $=>eqref)))) - (type $=>anyref (func (result anyref))) - (type $none_=>_i32_ref?|$mixed_results|_f64 (func (result i32 (ref null $mixed_results) f64))) - (type $mixed_results (func (result anyref f32 anyref f32))) - (elem declare func $call-ref $call-ref-more) + (type $none_=>_anyref (func (result anyref))) + (type $none_=>_anyref_f32_anyref_f32 (func (result anyref f32 anyref f32))) + (type $ref?|i32_->_i32|_=>_i32 (func (param (ref null $i32_=>_i32)) (result i32))) + (type $none_=>_i32_ref?|none_->_anyref_f32_anyref_f32|_f64 (func (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64))) + (type $none_=>_ref?|i32_i32_i32_i32_i32_->_none| (func (result (ref null $i32_i32_i32_i32_i32_=>_none)))) + (type $f64_=>_ref?|none_->_eqref| (func (param f64) (result (ref null $none_=>_eqref)))) + (type $none_=>_ref?|none_->_ref?|i32_i32_i32_i32_i32_->_none|| (func (result (ref null $none_=>_ref?|i32_i32_i32_i32_i32_->_none|)))) (func $call-ref (call_ref (ref.func $call-ref) @@ -26,20 +27,20 @@ (ref.func $call-ref-more) ) ) - (func $call_from-param (param $f (ref $i32-i32)) (result i32) + (func $call_from-param (param $f (ref null $i32_=>_i32)) (result i32) (call_ref (i32.const 42) (local.get $f) ) ) - (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) + (func $call_from-param-null (param $f (ref null $i32_=>_i32)) (result i32) (call_ref (i32.const 42) (local.get $f) ) ) (func $call_from-local-null (result i32) - (local $f (ref null $i32-i32)) + (local $f (ref null $i32_=>_i32)) (local.set $f (ref.func $call-ref-more) ) @@ -48,18 +49,21 @@ (local.get $f) ) ) - (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) - (ref.null $=>eqref) + (func $ref-in-sig (param $0 f64) (result (ref null $none_=>_eqref)) + (ref.null $none_=>_eqref) ) (func $type-only-in-tuple-local - (local $x (i32 (ref null $=>anyref) f64)) + (local $x (i32 (ref null (func (result anyref))) f64)) (nop) ) (func $type-only-in-tuple-block (drop - (block $block (result i32 (ref null $mixed_results) f64) + (block $block (result i32 (ref null $none_=>_anyref_f32_anyref_f32) f64) (unreachable) ) ) ) + (func $nested-type-only-there (result (ref null $none_=>_ref?|i32_i32_i32_i32_i32_->_none|)) + (unreachable) + ) ) diff -Nru binaryen-108/test/unit/input/em_asm_mangled_string.wat binaryen-99/test/unit/input/em_asm_mangled_string.wat --- binaryen-108/test/unit/input/em_asm_mangled_string.wat 1970-01-01 00:00:00.000000000 +0000 +++ binaryen-99/test/unit/input/em_asm_mangled_string.wat 2021-01-07 20:01:06.000000000 +0000 @@ -0,0 +1,11 @@ +(module + (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32))) + (global $global$0 (mut i32) (i32.const 66192)) + (global $global$1 i32 (i32.const 652)) + (export "__data_end" (global $global$1)) + (export "main" (func $main)) + (func $main (param $0 i32) (param $1 i32) (result i32) + (drop (call $emscripten_asm_const_int (local.get $0) (i32.const 0) (i32.const 0))) + (i32.const 0) + ) +) Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/unit/input/exception_handling_target_feature.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/unit/input/exception_handling_target_feature.wasm differ Binary files /tmp/tmpcr64qsb1/EKXcJhfBvt/binaryen-108/test/unit/input/gc_target_feature.wasm and /tmp/tmpcr64qsb1/CB1lWI5N76/binaryen-99/test/unit/input/gc_target_feature.wasm differ diff -Nru binaryen-108/test/unit/test_asyncify.py binaryen-99/test/unit/test_asyncify.py --- binaryen-108/test/unit/test_asyncify.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_asyncify.py 2021-01-07 20:01:06.000000000 +0000 @@ -87,18 +87,3 @@ self.assertEqual(normal, response) without = test(['--pass-arg=asyncify-imports@without.anything']) self.assertNotEqual(normal, without) - - def test_asyncify_too_many_locals(self): - # With 64K+ locals we cannot run the liveness analysis optimization, but - # should at least not fatally error. - temp = tempfile.NamedTemporaryFile().name - with open(temp, 'w') as f: - f.write('(module\n') - f.write(' (import "env" "foo" (func $import))\n') - f.write(' (func $many-locals\n') - for i in range(65 * 1024): - f.write(f' (local $x{i} i32)\n') - f.write(' (call $import)\n') - f.write(' )\n') - f.write(')\n') - shared.run_process(shared.WASM_OPT + [temp, '--asyncify']) diff -Nru binaryen-108/test/unit/test_dwarf.py binaryen-99/test/unit/test_dwarf.py --- binaryen-108/test/unit/test_dwarf.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_dwarf.py 2021-01-07 20:01:06.000000000 +0000 @@ -1,5 +1,4 @@ import os -import subprocess from scripts.test import shared from . import utils @@ -15,37 +14,3 @@ args = [os.path.join(path, name)] + \ ['-g', '--dwarfdump', '--roundtrip', '--dwarfdump'] shared.run_process(shared.WASM_OPT + args, capture_output=True) - - def test_dwarf_incompatibility(self): - warning = 'not fully compatible with DWARF' - path = self.input_path(os.path.join('dwarf', 'cubescript.wasm')) - args = [path, '-g'] - # flatten warns - err = shared.run_process(shared.WASM_OPT + args + ['--flatten'], stderr=subprocess.PIPE).stderr - self.assertIn(warning, err) - # safe passes do not - err = shared.run_process(shared.WASM_OPT + args + ['--metrics'], stderr=subprocess.PIPE).stderr - self.assertNotIn(warning, err) - - def test_strip_dwarf_and_opts(self): - # some optimizations are disabled when DWARF is present (as they would - # destroy it). we scan the wasm to see if there is any DWARF when - # making the decision whether to run them. this test checks that we also - # check if --strip* is being run, which would remove the DWARF anyhow - path = self.input_path(os.path.join('dwarf', 'cubescript.wasm')) - # strip the DWARF, then run all the opts to check as much as possible - args = [path, '--strip-dwarf', '-Oz'] - # run it normally, without -g. in this case no DWARF will be preserved - # in a trivial way - shared.run_process(shared.WASM_OPT + args + ['-o', 'a.wasm']) - # run it with -g. in this case we need to be clever as described above, - # and see --strip-dwarf removes the need for DWARF - shared.run_process(shared.WASM_OPT + args + ['-o', 'b.wasm', '-g']) - # run again on the last output without -g, as we don't want the names - # section to skew the results - shared.run_process(shared.WASM_OPT + ['b.wasm', '-o', 'c.wasm']) - # compare the sizes. there might be a tiny difference in size to to - # minor roundtrip changes, so ignore up to a tiny % - a_size = os.path.getsize('a.wasm') - c_size = os.path.getsize('c.wasm') - self.assertLess((100 * abs(a_size - c_size)) / c_size, 1) diff -Nru binaryen-108/test/unit/test_features.py binaryen-99/test/unit/test_features.py --- binaryen-108/test/unit/test_features.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_features.py 2021-01-07 20:01:06.000000000 +0000 @@ -31,7 +31,9 @@ self.check_feature(module, error, '--enable-bulk-memory') def check_exception_handling(self, module, error): - self.check_feature(module, error, '--enable-exception-handling') + # Exception handling implies reference types + self.check_feature(module, error, '--enable-exception-handling', + ['--enable-reference-types']) def check_tail_call(self, module, error): self.check_feature(module, error, '--enable-tail-call') @@ -44,7 +46,8 @@ def check_multivalue_exception_handling(self, module, error): self.check_feature(module, error, '--enable-multivalue', - ['--enable-exception-handling']) + ['--enable-exception-handling', + '--enable-reference-types']) def check_gc(self, module, error): # GC implies reference types @@ -136,7 +139,7 @@ module = ''' (module (memory 256 256) - (data "42") + (data passive "42") ) ''' self.check_bulk_mem(module, 'nonzero segment flags (bulk memory is disabled)') @@ -184,16 +187,26 @@ ''' self.check_reference_types(module, 'all used types should be allowed') - def test_tag(self): + def test_exnref_local(self): module = ''' (module - (tag $e (param i32)) + (func $foo + (local exnref) + ) + ) + ''' + self.check_exception_handling(module, 'all used types should be allowed') + + def test_event(self): + module = ''' + (module + (event $e (attr 0) (param i32)) (func $foo (throw $e (i32.const 0)) ) ) ''' - self.check_exception_handling(module, 'Module has tags') + self.check_exception_handling(module, 'Module has events') def test_multivalue_import(self): module = ''' @@ -218,13 +231,13 @@ self.check_multivalue(module, 'Multivalue function results ' + '(multivalue is not enabled)') - def test_multivalue_tag(self): + def test_multivalue_event(self): module = ''' (module - (tag $foo (param i32 i64)) + (event $foo (attr 0) (param i32 i64)) ) ''' - self.check_multivalue_exception_handling(module, 'Multivalue tag type ' + + self.check_multivalue_exception_handling(module, 'Multivalue event type ' + '(multivalue is not enabled)') def test_multivalue_block(self): @@ -245,19 +258,19 @@ self.check_multivalue(module, 'Multivalue block type ' + '(multivalue is not enabled)') - def test_i31_global(self): + def test_anyref_global(self): module = ''' (module - (global $foo (ref null i31) (ref.null i31)) + (global $foo anyref (ref.null any)) ) ''' self.check_gc(module, 'all used types should be allowed') - def test_i31_local(self): + def test_anyref_local(self): module = ''' (module (func $foo - (local $0 (ref null i31)) + (local $0 anyref) ) ) ''' @@ -330,12 +343,12 @@ filename = 'reference_types_target_feature.wasm' self.roundtrip(filename) self.check_features(filename, ['reference-types']) - self.assertIn('anyref', self.disassemble(filename)) + self.assertIn('externref', self.disassemble(filename)) def test_exception_handling(self): filename = 'exception_handling_target_feature.wasm' self.roundtrip(filename) - self.check_features(filename, ['exception-handling']) + self.check_features(filename, ['exception-handling', 'reference-types']) self.assertIn('throw', self.disassemble(filename)) def test_gc(self): @@ -346,26 +359,27 @@ self.assertIn('anyref', disassembly) self.assertIn('eqref', disassembly) - def test_superset(self): - # It is ok to enable additional features past what is in the section. - shared.run_process( - shared.WASM_OPT + ['--print', '--detect-features', '-mvp', - '--enable-simd', '--enable-sign-ext', - self.input_path('signext_target_feature.wasm')]) - - def test_superset_even_without_detect_features(self): - # It is ok to enable additional features past what is in the section, - # even without passing --detect-features (which is now a no-op). + def test_incompatible_features(self): path = self.input_path('signext_target_feature.wasm') - shared.run_process( + p = shared.run_process( shared.WASM_OPT + ['--print', '--enable-simd', '-o', os.devnull, - path]) + path], + check=False, capture_output=True + ) + self.assertNotEqual(p.returncode, 0) + self.assertIn('Fatal: module features do not match specified features. ' + + 'Use --detect-features to resolve.', + p.stderr) - def test_superset_with_detect_features(self): + def test_incompatible_features_forced(self): path = self.input_path('signext_target_feature.wasm') - shared.run_process( - shared.WASM_OPT + ['--print', '--detect-features', - '--enable-simd', '-o', os.devnull, path]) + p = shared.run_process( + shared.WASM_OPT + ['--print', '--detect-features', '-mvp', + '--enable-simd', '-o', os.devnull, path], + check=False, capture_output=True + ) + self.assertNotEqual(p.returncode, 0) + self.assertIn('all used features should be allowed', p.stderr) def test_explicit_detect_features(self): self.check_features('signext_target_feature.wasm', ['simd', 'sign-ext'], @@ -396,6 +410,4 @@ '--enable-gc', '--enable-memory64', '--enable-typed-function-references', - '--enable-relaxed-simd', - '--enable-extended-const', ], p2.stdout.splitlines()) diff -Nru binaryen-108/test/unit/test_finalize.py binaryen-99/test/unit/test_finalize.py --- binaryen-108/test/unit/test_finalize.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_finalize.py 2021-01-07 20:01:06.000000000 +0000 @@ -1,8 +1,18 @@ +import os + from scripts.test import shared from . import utils class EmscriptenFinalizeTest(utils.BinaryenTestCase): + def test_em_asm_mangled_string(self): + p = shared.run_process(shared.WASM_EMSCRIPTEN_FINALIZE + [ + self.input_path('em_asm_mangled_string.wat'), '-o', os.devnull, '--global-base=1024' + ], check=False, capture_output=True) + self.assertNotEqual(p.returncode, 0) + self.assertIn('Fatal: local.get of unknown in arg0 of call to emscripten_asm_const_int (used by EM_ASM* macros) in function main.', p.stderr) + self.assertIn('This might be caused by aggressive compiler transformations. Consider using EM_JS instead.', p.stderr) + def do_output_test(self, args): # without any output file specified, don't error, don't write the wasm, # but do emit metadata diff -Nru binaryen-108/test/unit/test_fuzz_empty_data.py binaryen-99/test/unit/test_fuzz_empty_data.py --- binaryen-108/test/unit/test_fuzz_empty_data.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_fuzz_empty_data.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -import os -import tempfile -from scripts.test import shared -from . import utils - - -class EmptyDataFuzzTest(utils.BinaryenTestCase): - def test_empty_data(self): - try: - temp = tempfile.NamedTemporaryFile(delete=False).name - shared.run_process(shared.WASM_OPT + ['-ttf', temp], - capture_output=True) - finally: - os.unlink(temp) diff -Nru binaryen-108/test/unit/test_reduce.py binaryen-99/test/unit/test_reduce.py --- binaryen-108/test/unit/test_reduce.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_reduce.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -import subprocess - -from scripts.test import shared -from . import utils - - -class ReduceTest(utils.BinaryenTestCase): - def test_warn_on_no_passes(self): - # run a reducer command that does nothing, and so ignores the input - open('do_nothing.py', 'w').close() - cmd = shared.WASM_REDUCE + [self.input_path('empty.wasm'), '-w', 'w.wasm', '-t', 't.wasm', '--command=python do_nothing.py'] - err = shared.run_process(cmd, check=False, stderr=subprocess.PIPE).stderr - self.assertIn('Fatal: running the command on the given input gives the same result as when running it on either a trivial valid wasm or a file with nonsense in it. does the script not look at the test file (t.wasm)? (use -f to ignore this check)', err) diff -Nru binaryen-108/test/unit/test_symbolmap.py binaryen-99/test/unit/test_symbolmap.py --- binaryen-108/test/unit/test_symbolmap.py 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/unit/test_symbolmap.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -from scripts.test import shared -from . import utils - - -class SymbolMapTest(utils.BinaryenTestCase): - def test_symbolmap(self): - input_wasm = self.input_path('hello_world.wat') - # write the symbol map to a file - args = [input_wasm, '--symbolmap=out.symbols'] - shared.run_process(shared.WASM_OPT + args) - with open('out.symbols') as f: - file_output = f.read() - # write the symbol map to stdout - args = [input_wasm, '--symbolmap'] - stdout_output = shared.run_process(shared.WASM_OPT + args, - capture_output=True).stdout - # ignore whitespace in the comparison as on windows stdout gets an \r - self.assertEqual(file_output.strip(), stdout_output.strip()) - # the wat contains a single function "add" - self.assertIn('0:add', file_output) diff -Nru binaryen-108/test/wasm2js/atomics_32.2asm.js binaryen-99/test/wasm2js/atomics_32.2asm.js --- binaryen-108/test/wasm2js/atomics_32.2asm.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/atomics_32.2asm.js 2021-01-07 20:01:06.000000000 +0000 @@ -30,14 +30,9 @@ var f64ScratchView = new Float64Array(scratchBuffer); function wasm2js_atomic_wait_i32(ptr, expected, timeoutLow, timeoutHigh) { - var timeout = Infinity; - if (timeoutHigh >= 0) { - // Convert from nanoseconds to milliseconds - // Taken from convertI32PairToI53 in emscripten's library_int53.js - timeout = ((timeoutLow >>> 0) / 1e6) + timeoutHigh * (4294967296 / 1e6); - } + if (timeoutLow != -1 || timeoutHigh != -1) throw 'unsupported timeout'; var view = new Int32Array(bufferView.buffer); // TODO cache - var result = Atomics.wait(view, ptr >> 2, expected, timeout); + var result = Atomics.wait(view, ptr, expected); if (result == 'ok') return 0; if (result == 'not-equal') return 1; if (result == 'timed-out') return 2; @@ -45,7 +40,7 @@ } function wasm2js_atomic_rmw_i64(op, bytes, offset, ptr, valueLow, valueHigh) { - // TODO: support bytes=1, 2, 4 as well as 8. + assert(bytes == 8); // TODO: support 1, 2, 4 as well var view = new BigInt64Array(bufferView.buffer); // TODO cache ptr = (ptr + offset) >> 3; var value = BigInt(valueLow >>> 0) | (BigInt(valueHigh >>> 0) << BigInt(32)); diff -Nru binaryen-108/test/wasm2js/atomics_32.2asm.js.opt binaryen-99/test/wasm2js/atomics_32.2asm.js.opt --- binaryen-108/test/wasm2js/atomics_32.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/atomics_32.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -30,14 +30,9 @@ var f64ScratchView = new Float64Array(scratchBuffer); function wasm2js_atomic_wait_i32(ptr, expected, timeoutLow, timeoutHigh) { - var timeout = Infinity; - if (timeoutHigh >= 0) { - // Convert from nanoseconds to milliseconds - // Taken from convertI32PairToI53 in emscripten's library_int53.js - timeout = ((timeoutLow >>> 0) / 1e6) + timeoutHigh * (4294967296 / 1e6); - } + if (timeoutLow != -1 || timeoutHigh != -1) throw 'unsupported timeout'; var view = new Int32Array(bufferView.buffer); // TODO cache - var result = Atomics.wait(view, ptr >> 2, expected, timeout); + var result = Atomics.wait(view, ptr, expected); if (result == 'ok') return 0; if (result == 'not-equal') return 1; if (result == 'timed-out') return 2; @@ -45,7 +40,7 @@ } function wasm2js_atomic_rmw_i64(op, bytes, offset, ptr, valueLow, valueHigh) { - // TODO: support bytes=1, 2, 4 as well as 8. + assert(bytes == 8); // TODO: support 1, 2, 4 as well var view = new BigInt64Array(bufferView.buffer); // TODO cache ptr = (ptr + offset) >> 3; var value = BigInt(valueLow >>> 0) | (BigInt(valueHigh >>> 0) << BigInt(32)); diff -Nru binaryen-108/test/wasm2js/atomics_32.wast binaryen-99/test/wasm2js/atomics_32.wast --- binaryen-108/test/wasm2js/atomics_32.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/atomics_32.wast 2021-01-07 20:01:06.000000000 +0000 @@ -1,7 +1,7 @@ (module (memory (shared 256 256)) - (data "hello,") - (data "world!") + (data passive "hello,") + (data passive "world!") (func "test" (local $x i32) (local $y i64) diff -Nru binaryen-108/test/wasm2js/br_table.2asm.js binaryen-99/test/wasm2js/br_table.2asm.js --- binaryen-108/test/wasm2js/br_table.2asm.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/br_table.2asm.js 2021-01-07 20:01:06.000000000 +0000 @@ -12560,12 +12560,12 @@ function $20() { var $1_1 = 0, $2_1 = 0, $4_1 = 0; - __binaryen_fake_return : { + fake_return_waka123 : { loop_in : while (1) { $1_1 = 3; switch (0 | 0) { default: - break __binaryen_fake_return; + break fake_return_waka123; }; }; } @@ -12574,13 +12574,13 @@ function $21() { var $1_1 = 0, $2_1 = 0, $4_1 = 0; - __binaryen_fake_return : { + fake_return_waka123 : { loop_in : while (1) { dummy(); $1_1 = 4; switch (-1 | 0) { default: - break __binaryen_fake_return; + break fake_return_waka123; }; }; } @@ -12589,13 +12589,13 @@ function $22() { var $1_1 = 0; - __binaryen_fake_return : { + fake_return_waka123 : { loop_in : while (1) { dummy(); $1_1 = 5; switch (1 | 0) { default: - break __binaryen_fake_return; + break fake_return_waka123; }; }; } diff -Nru binaryen-108/test/wasm2js/br_table_temp.2asm.js binaryen-99/test/wasm2js/br_table_temp.2asm.js --- binaryen-108/test/wasm2js/br_table_temp.2asm.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/br_table_temp.2asm.js 2021-01-07 20:01:06.000000000 +0000 @@ -12556,12 +12556,12 @@ function $20() { var $1_1 = 0, $2_1 = 0, $4_1 = 0; - __binaryen_fake_return : { + fake_return_waka123 : { loop_in : while (1) { $1_1 = 3; switch (0 | 0) { default: - break __binaryen_fake_return; + break fake_return_waka123; }; }; } @@ -12570,13 +12570,13 @@ function $21() { var $1_1 = 0, $2_1 = 0, $4_1 = 0; - __binaryen_fake_return : { + fake_return_waka123 : { loop_in : while (1) { dummy(); $1_1 = 4; switch (-1 | 0) { default: - break __binaryen_fake_return; + break fake_return_waka123; }; }; } @@ -12585,13 +12585,13 @@ function $22() { var $1_1 = 0; - __binaryen_fake_return : { + fake_return_waka123 : { loop_in : while (1) { dummy(); $1_1 = 5; switch (1 | 0) { default: - break __binaryen_fake_return; + break fake_return_waka123; }; }; } diff -Nru binaryen-108/test/wasm2js/br_table_temp.2asm.js.opt binaryen-99/test/wasm2js/br_table_temp.2asm.js.opt --- binaryen-108/test/wasm2js/br_table_temp.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/br_table_temp.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -12555,14 +12555,15 @@ function $60($0) { $0 = $0 | 0; - var $1 = 0; + var $1 = 0, $2 = 0; $1 = 16; + $2 = 16; block : { switch ($0 | 0) { case 0: - $1 = 18; + $2 = 18; case 1: - $1 = $1 + 1 | 0; + $1 = $2 + 1 | 0; break; default: break block; @@ -12573,14 +12574,15 @@ function $61($0) { $0 = $0 | 0; - var $1 = 0; + var $1 = 0, $2 = 0; $1 = 8; + $2 = 8; block : { switch ($0 | 0) { default: - $1 = 16; + $2 = 16; case 1: - $1 = $1 + 1 | 0; + $1 = $2 + 1 | 0; break; case 0: break block; @@ -12591,14 +12593,15 @@ function $62($0) { $0 = $0 | 0; - var $1 = 0; + var $1 = 0, $2 = 0; $1 = 8; + $2 = 8; block : { switch ($0 | 0) { case 0: - $1 = 16; + $2 = 16; case 1: - $1 = $1 + 1 | 0; + $1 = $2 + 1 | 0; break; default: break block; diff -Nru binaryen-108/test/wasm2js/conversions-modified.2asm.js.opt binaryen-99/test/wasm2js/conversions-modified.2asm.js.opt --- binaryen-108/test/wasm2js/conversions-modified.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/conversions-modified.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -66,6 +66,18 @@ return ~~$0 >>> 0 | 0; } + function $7($0) { + $0 = Math_fround($0); + i64toi32_i32$HIGH_BITS = Math_fround(Math_abs($0)) >= Math_fround(1.0) ? ($0 > Math_fround(0.0) ? ~~Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 * Math_fround(2.3283064365386963e-10)))), Math_fround(4294967296.0))) >>> 0 : ~~Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) * Math_fround(2.3283064365386963e-10)))) >>> 0) : 0; + return ~~$0 >>> 0 | 0; + } + + function $9($0) { + $0 = +$0; + i64toi32_i32$HIGH_BITS = Math_abs($0) >= 1.0 ? ($0 > 0.0 ? ~~Math_min(Math_floor($0 * 2.3283064365386963e-10), 4294967295.0) >>> 0 : ~~Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) * 2.3283064365386963e-10) >>> 0) : 0; + return ~~$0 >>> 0 | 0; + } + function $11($0) { $0 = $0 | 0; return Math_fround(Math_fround($0 | 0)); @@ -123,15 +135,17 @@ } function legalstub$7($0) { - i64toi32_i32$HIGH_BITS = Math_fround(Math_abs($0)) >= Math_fround(1.0) ? ~~($0 > Math_fround(0.0) ? Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 * Math_fround(2.3283064365386963e-10)))), Math_fround(4294967296.0))) : Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) * Math_fround(2.3283064365386963e-10))))) >>> 0 : 0; + var $1 = 0; + $1 = $7($0); setTempRet0(i64toi32_i32$HIGH_BITS | 0); - return ~~$0 >>> 0; + return $1; } function legalstub$9($0) { - i64toi32_i32$HIGH_BITS = Math_abs($0) >= 1.0 ? ~~($0 > 0.0 ? Math_min(Math_floor($0 * 2.3283064365386963e-10), 4294967295.0) : Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) * 2.3283064365386963e-10)) >>> 0 : 0; + var $1 = 0; + $1 = $9($0); setTempRet0(i64toi32_i32$HIGH_BITS | 0); - return ~~$0 >>> 0; + return $1; } function legalstub$12($0, $1) { diff -Nru binaryen-108/test/wasm2js/emscripten.2asm.js.opt binaryen-99/test/wasm2js/emscripten.2asm.js.opt --- binaryen-108/test/wasm2js/emscripten.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/emscripten.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -185,16 +185,14 @@ function bools($0) { $0 = $0 | 0; - var $1 = 0; bools(HEAP8[0] & 1); bools(HEAP8[0] & 1); bools(HEAP16[0] & 1); bools(HEAP16[0] & 1); bools(HEAP32[0] & 1); bools(HEAPU8[0] & 2); - $1 = $0 ^ 1; - bools($1); - if ($1) { + bools($0 ^ 1); + if ($0 ^ 1) { bools(2) } if ($0 ^ 2) { diff -Nru binaryen-108/test/wasm2js/emscripten-grow-yes.2asm.js binaryen-99/test/wasm2js/emscripten-grow-yes.2asm.js --- binaryen-108/test/wasm2js/emscripten-grow-yes.2asm.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/emscripten-grow-yes.2asm.js 2021-01-07 20:01:06.000000000 +0000 @@ -50,10 +50,6 @@ var infinity = Infinity; // EMSCRIPTEN_START_FUNCS ; - function $0() { - return __wasm_memory_size() | 0; - } - // EMSCRIPTEN_END_FUNCS ; bufferView = HEAPU8; @@ -96,8 +92,7 @@ } } - }), - "get_size": $0 + }) }; } diff -Nru binaryen-108/test/wasm2js/emscripten-grow-yes.2asm.js.opt binaryen-99/test/wasm2js/emscripten-grow-yes.2asm.js.opt --- binaryen-108/test/wasm2js/emscripten-grow-yes.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/emscripten-grow-yes.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -50,10 +50,6 @@ var infinity = Infinity; // EMSCRIPTEN_START_FUNCS ; - function $0() { - return __wasm_memory_size() | 0; - } - // EMSCRIPTEN_END_FUNCS ; bufferView = HEAPU8; @@ -96,8 +92,7 @@ } } - }), - "get_size": $0 + }) }; } diff -Nru binaryen-108/test/wasm2js/emscripten-grow-yes.wast binaryen-99/test/wasm2js/emscripten-grow-yes.wast --- binaryen-108/test/wasm2js/emscripten-grow-yes.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/emscripten-grow-yes.wast 2021-01-07 20:01:06.000000000 +0000 @@ -3,6 +3,5 @@ (import "env" "memory" (memory $0 256 1024)) (data (i32.const 1600) "abc") (export "memory" (memory $0)) - (func (export "get_size") (result i32) (memory.size)) ) diff -Nru binaryen-108/test/wasm2js/export_global.2asm.js binaryen-99/test/wasm2js/export_global.2asm.js --- binaryen-108/test/wasm2js/export_global.2asm.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/export_global.2asm.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ - -function asmFunc(env) { - var Math_imul = Math.imul; - var Math_fround = Math.fround; - var Math_abs = Math.abs; - var Math_clz32 = Math.clz32; - var Math_min = Math.min; - var Math_max = Math.max; - var Math_floor = Math.floor; - var Math_ceil = Math.ceil; - var Math_trunc = Math.trunc; - var Math_sqrt = Math.sqrt; - var abort = env.abort; - var nan = NaN; - var infinity = Infinity; - var global0 = 655360; - function $0() { - return 42 | 0; - } - - return { - "HELLO": { - get value() { - return global0; - }, - set value(_global0) { - global0 = _global0; - } - }, - "helloWorld": $0 - }; -} - -var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); } - }); -export var HELLO = retasmFunc.HELLO; -export var helloWorld = retasmFunc.helloWorld; diff -Nru binaryen-108/test/wasm2js/export_global.2asm.js.opt binaryen-99/test/wasm2js/export_global.2asm.js.opt --- binaryen-108/test/wasm2js/export_global.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/export_global.2asm.js.opt 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ - -function asmFunc(env) { - var Math_imul = Math.imul; - var Math_fround = Math.fround; - var Math_abs = Math.abs; - var Math_clz32 = Math.clz32; - var Math_min = Math.min; - var Math_max = Math.max; - var Math_floor = Math.floor; - var Math_ceil = Math.ceil; - var Math_trunc = Math.trunc; - var Math_sqrt = Math.sqrt; - var abort = env.abort; - var nan = NaN; - var infinity = Infinity; - var global0 = 655360; - function $0() { - return 42; - } - - return { - "HELLO": { - get value() { - return global0; - }, - set value(_global0) { - global0 = _global0; - } - }, - "helloWorld": $0 - }; -} - -var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); } - }); -export var HELLO = retasmFunc.HELLO; -export var helloWorld = retasmFunc.helloWorld; diff -Nru binaryen-108/test/wasm2js/export_global.wast binaryen-99/test/wasm2js/export_global.wast --- binaryen-108/test/wasm2js/export_global.wast 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/export_global.wast 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -(module - (global $global0 i32 (i32.const 655360)) - (export "HELLO" (global $global0)) - (func (result i32) (i32.const 42)) - (export "helloWorld" (func 0)) -) \ No newline at end of file diff -Nru binaryen-108/test/wasm2js/float-ops.2asm.js.opt binaryen-99/test/wasm2js/float-ops.2asm.js.opt --- binaryen-108/test/wasm2js/float-ops.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/float-ops.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -239,12 +239,12 @@ function $47($0) { $0 = Math_fround($0); - return !(~~$0 >>> 0 | (Math_fround(Math_abs($0)) >= Math_fround(1.0) ? ~~($0 > Math_fround(0.0) ? Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 * Math_fround(2.3283064365386963e-10)))), Math_fround(4294967296.0))) : Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) * Math_fround(2.3283064365386963e-10))))) >>> 0 : 0)) | 0; + return !(~~$0 >>> 0 | (Math_fround(Math_abs($0)) >= Math_fround(1.0) ? ($0 > Math_fround(0.0) ? ~~Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 * Math_fround(2.3283064365386963e-10)))), Math_fround(4294967296.0))) >>> 0 : ~~Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) * Math_fround(2.3283064365386963e-10)))) >>> 0) : 0)) | 0; } function $48($0) { $0 = +$0; - return !(~~$0 >>> 0 | (Math_abs($0) >= 1.0 ? ~~($0 > 0.0 ? Math_min(Math_floor($0 * 2.3283064365386963e-10), 4294967295.0) : Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) * 2.3283064365386963e-10)) >>> 0 : 0)) | 0; + return !(~~$0 >>> 0 | (Math_abs($0) >= 1.0 ? ($0 > 0.0 ? ~~Math_min(Math_floor($0 * 2.3283064365386963e-10), 4294967295.0) >>> 0 : ~~Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) * 2.3283064365386963e-10) >>> 0) : 0)) | 0; } function legalstub$43($0, $1_1) { diff -Nru binaryen-108/test/wasm2js/i64-add-sub.2asm.js.opt binaryen-99/test/wasm2js/i64-add-sub.2asm.js.opt --- binaryen-108/test/wasm2js/i64-add-sub.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/i64-add-sub.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -13,15 +13,25 @@ var abort = env.abort; var nan = NaN; var infinity = Infinity; - function legalstub$1($0, $1, $2, $3, $4, $5) { - $1 = $1 + $3 | 0; + function $1($0, $1_1, $2, $3, $4, $5) { + $0 = $0 | 0; + $1_1 = $1_1 | 0; + $2 = $2 | 0; + $3 = $3 | 0; + $4 = $4 | 0; + $5 = $5 | 0; + $1_1 = $1_1 + $3 | 0; $0 = $0 + $2 | 0; - $1 = $2 >>> 0 > $0 >>> 0 ? $1 + 1 | 0 : $1; - return ($0 | 0) == ($4 | 0) & ($1 | 0) == ($5 | 0); + $1_1 = $2 >>> 0 > $0 >>> 0 ? $1_1 + 1 | 0 : $1_1; + return ($0 | 0) == ($4 | 0) & ($1_1 | 0) == ($5 | 0); } - function legalstub$2($0, $1, $2, $3, $4, $5) { - return ($4 | 0) == ($0 - $2 | 0) & ($5 | 0) == ($1 - (($0 >>> 0 < $2 >>> 0) + $3 | 0) | 0); + function legalstub$1($0, $1_1, $2, $3, $4, $5) { + return $1($0, $1_1, $2, $3, $4, $5); + } + + function legalstub$2($0, $1_1, $2, $3, $4, $5) { + return ($4 | 0) == ($0 - $2 | 0) & ($5 | 0) == ($1_1 - (($0 >>> 0 < $2 >>> 0) + $3 | 0) | 0); } return { diff -Nru binaryen-108/test/wasm2js/i64-ctz.2asm.js.opt binaryen-99/test/wasm2js/i64-ctz.2asm.js.opt --- binaryen-108/test/wasm2js/i64-ctz.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/i64-ctz.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -17,46 +17,52 @@ var setTempRet0 = env.setTempRet0; var i64toi32_i32$HIGH_BITS = 0; function legalstub$popcnt64($0, $1) { - var $2 = 0, $3 = 0, $4 = 0; - $2 = $1; - while (1) { - if ($0 | $2) { - $1 = $0; - $0 = $0 - 1 & $0; - $2 = $2 - !$1 & $2; - $3 = $3 + 1 | 0; - $4 = $3 ? $4 : $4 + 1 | 0; - continue; - } - break; - }; - i64toi32_i32$HIGH_BITS = $4; - $0 = $3; + $0 = __wasm_popcnt_i64($0, $1); setTempRet0(i64toi32_i32$HIGH_BITS | 0); return $0; } function legalstub$ctz64($0, $1) { + $0 = __wasm_ctz_i64($0, $1); + setTempRet0(i64toi32_i32$HIGH_BITS | 0); + return $0; + } + + function __wasm_ctz_i64($0, $1) { + var $2 = 0, $3 = 0; + if ($0 | $1) { + $2 = $1 - 1 | 0; + $3 = $0 - 1 | 0; + $2 = ($3 | 0) != -1 ? $2 + 1 | 0 : $2; + $3 = Math_clz32($0 ^ $3) + 32 | 0; + $0 = Math_clz32($1 ^ $2); + $0 = ($0 | 0) == 32 ? $3 : $0; + $1 = 63 - $0 | 0; + i64toi32_i32$HIGH_BITS = 0 - ($0 >>> 0 > 63) | 0; + return $1; + } + i64toi32_i32$HIGH_BITS = 0; + return 64; + } + + function __wasm_popcnt_i64($0, $1) { var $2 = 0, $3 = 0, $4 = 0, $5 = 0; - __inlined_func$__wasm_ctz_i64 : { + while (1) { + $5 = $4; + $2 = $3; if ($0 | $1) { - $2 = $1 - 1 | 0; - $3 = $2 + 1 | 0; + $2 = $0; + $0 = $2 - 1 & $2; + $1 = $1 - ($2 >>> 0 < 1) & $1; + $2 = $4 + 1 | 0; + $3 = $2 >>> 0 < 1 ? $3 + 1 | 0 : $3; $4 = $2; - $2 = $0 - 1 | 0; - $5 = Math_clz32($0 ^ $2) + 32 | 0; - $0 = Math_clz32($1 ^ (($2 | 0) != -1 ? $3 : $4)); - $0 = ($0 | 0) == 32 ? $5 : $0; - $1 = 63 - $0 | 0; - i64toi32_i32$HIGH_BITS = 0 - ($0 >>> 0 > 63) | 0; - $0 = $1; - break __inlined_func$__wasm_ctz_i64; + continue; } - i64toi32_i32$HIGH_BITS = 0; - $0 = 64; - } - setTempRet0(i64toi32_i32$HIGH_BITS | 0); - return $0; + break; + }; + i64toi32_i32$HIGH_BITS = $2; + return $5; } return { diff -Nru binaryen-108/test/wasm2js/i64-lowering.2asm.js.opt binaryen-99/test/wasm2js/i64-lowering.2asm.js.opt --- binaryen-108/test/wasm2js/i64-lowering.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/i64-lowering.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -22,19 +22,19 @@ } function legalstub$3($0, $1, $2, $3) { - return ($1 | 0) >= ($3 | 0) & $0 >>> 0 >= $2 >>> 0 | ($1 | 0) > ($3 | 0); + return ($1 | 0) > ($3 | 0) ? 1 : ($1 | 0) >= ($3 | 0) ? $0 >>> 0 >= $2 >>> 0 : 0; } function legalstub$4($0, $1, $2, $3) { - return $0 >>> 0 > $2 >>> 0 & ($1 | 0) >= ($3 | 0) | ($1 | 0) > ($3 | 0); + return ($1 | 0) > ($3 | 0) ? 1 : ($1 | 0) >= ($3 | 0) ? $0 >>> 0 > $2 >>> 0 : 0; } function legalstub$5($0, $1, $2, $3) { - return ($1 | 0) <= ($3 | 0) & $0 >>> 0 <= $2 >>> 0 | ($1 | 0) < ($3 | 0); + return ($1 | 0) < ($3 | 0) ? 1 : ($1 | 0) <= ($3 | 0) ? $0 >>> 0 <= $2 >>> 0 : 0; } function legalstub$6($0, $1, $2, $3) { - return $0 >>> 0 < $2 >>> 0 & ($1 | 0) <= ($3 | 0) | ($1 | 0) < ($3 | 0); + return ($1 | 0) < ($3 | 0) ? 1 : ($1 | 0) <= ($3 | 0) ? $0 >>> 0 < $2 >>> 0 : 0; } function legalstub$7($0, $1, $2, $3) { diff -Nru binaryen-108/test/wasm2js/i64-rotate.2asm.js.opt binaryen-99/test/wasm2js/i64-rotate.2asm.js.opt --- binaryen-108/test/wasm2js/i64-rotate.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/i64-rotate.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -15,99 +15,104 @@ var infinity = Infinity; var i64toi32_i32$HIGH_BITS = 0; function legalstub$1($0, $1, $2, $3, $4, $5) { - var $6 = 0, $7 = 0, $8 = 0; - $8 = $0; - $0 = 0; - $7 = $2 & 63; - $6 = $7; - $3 = $6 & 31; - if ($6 >>> 0 >= 32) { + return (__wasm_rotl_i64($0, $1, $2) | 0) == ($4 | 0) & ($5 | 0) == (i64toi32_i32$HIGH_BITS | 0); + } + + function legalstub$2($0, $1, $2, $3, $4, $5) { + return (__wasm_rotr_i64($0, $1, $2) | 0) == ($4 | 0) & ($5 | 0) == (i64toi32_i32$HIGH_BITS | 0); + } + + function __wasm_rotl_i64($0, $1, $2) { + var $3 = 0, $4 = 0, $5 = 0, $6 = 0; + $6 = $2 & 63; + $5 = $6; + $3 = $5 & 31; + if ($5 >>> 0 >= 32) { $3 = -1 >>> $3 | 0 } else { - $0 = -1 >>> $3 | 0; - $3 = $0 | (1 << $3) - 1 << 32 - $3; + $4 = -1 >>> $3 | 0; + $3 = (1 << $3) - 1 << 32 - $3 | -1 >>> $3; } - $6 = $3 & $8; - $0 = $0 & $1; - $3 = $7 & 31; - if ($7 >>> 0 >= 32) { - $0 = $6 << $3; + $5 = $3 & $0; + $3 = $1 & $4; + $4 = $6 & 31; + if ($6 >>> 0 >= 32) { + $3 = $5 << $4; $6 = 0; } else { - $0 = (1 << $3) - 1 & $6 >>> 32 - $3 | $0 << $3; - $6 = $6 << $3; + $3 = (1 << $4) - 1 & $5 >>> 32 - $4 | $3 << $4; + $6 = $5 << $4; } - $3 = $0; - $2 = 0 - $2 & 63; - $0 = $2 & 31; - if ($2 >>> 0 >= 32) { - $0 = -1 << $0; - $7 = 0; + $5 = $3; + $4 = 0 - $2 & 63; + $3 = $4; + $2 = $3 & 31; + if ($3 >>> 0 >= 32) { + $3 = -1 << $2; + $2 = 0; } else { - $7 = -1 << $0; - $0 = $7 | (1 << $0) - 1 & -1 >>> 32 - $0; + $3 = (1 << $2) - 1 & -1 >>> 32 - $2 | -1 << $2; + $2 = -1 << $2; } - $8 = $7 & $8; - $1 = $0 & $1; - $0 = $2 & 31; - if ($2 >>> 0 >= 32) { + $0 = $2 & $0; + $3 = $1 & $3; + $1 = $4 & 31; + if ($4 >>> 0 >= 32) { $2 = 0; - $0 = $1 >>> $0 | 0; + $0 = $3 >>> $1 | 0; } else { - $2 = $1 >>> $0 | 0; - $0 = ((1 << $0) - 1 & $1) << 32 - $0 | $8 >>> $0; + $2 = $3 >>> $1 | 0; + $0 = ((1 << $1) - 1 & $3) << 32 - $1 | $0 >>> $1; } $0 = $0 | $6; - i64toi32_i32$HIGH_BITS = $2 | $3; - return ($0 | 0) == ($4 | 0) & ($5 | 0) == (i64toi32_i32$HIGH_BITS | 0); + i64toi32_i32$HIGH_BITS = $2 | $5; + return $0; } - function legalstub$2($0, $1, $2, $3, $4, $5) { - var $6 = 0, $7 = 0, $8 = 0, $9 = 0; - $8 = $0; - $7 = $2 & 63; - $3 = $7; - $0 = $3 & 31; - if ($3 >>> 0 >= 32) { - $0 = -1 << $0; - $3 = 0; + function __wasm_rotr_i64($0, $1, $2) { + var $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0; + $6 = $2 & 63; + $3 = $6 & 31; + if ($6 >>> 0 >= 32) { + $4 = -1 << $3; + $7 = 0; } else { - $3 = -1 << $0; - $0 = $3 | (1 << $0) - 1 & -1 >>> 32 - $0; + $4 = (1 << $3) - 1 & -1 >>> 32 - $3 | -1 << $3; + $7 = -1 << $3; } - $9 = $3 & $8; - $6 = $0 & $1; - $3 = $7 & 31; - if ($7 >>> 0 >= 32) { - $0 = 0; - $7 = $6 >>> $3 | 0; + $7 = $7 & $0; + $3 = $1 & $4; + $5 = $6 & 31; + if ($6 >>> 0 >= 32) { + $4 = 0; + $6 = $3 >>> $5 | 0; } else { - $0 = $6 >>> $3 | 0; - $7 = ((1 << $3) - 1 & $6) << 32 - $3 | $9 >>> $3; + $4 = $3 >>> $5 | 0; + $6 = ((1 << $5) - 1 & $3) << 32 - $5 | $7 >>> $5; } - $3 = $0; - $6 = 0 - $2 & 63; - $2 = $6 & 31; - if ($6 >>> 0 >= 32) { - $0 = 0; - $2 = -1 >>> $2 | 0; + $7 = $4; + $3 = 0 - $2 & 63; + $5 = $3 & 31; + if ($3 >>> 0 >= 32) { + $4 = 0; + $2 = -1 >>> $5 | 0; } else { - $0 = -1 >>> $2 | 0; - $2 = $0 | (1 << $2) - 1 << 32 - $2; + $4 = -1 >>> $5 | 0; + $2 = (1 << $5) - 1 << 32 - $5 | -1 >>> $5; } - $2 = $2 & $8; - $1 = $0 & $1; - $0 = $6 & 31; - if ($6 >>> 0 >= 32) { - $1 = $2 << $0; + $0 = $2 & $0; + $1 = $1 & $4; + $4 = $3 & 31; + if ($3 >>> 0 >= 32) { + $2 = $0 << $4; $0 = 0; } else { - $1 = (1 << $0) - 1 & $2 >>> 32 - $0 | $1 << $0; - $0 = $2 << $0; + $2 = (1 << $4) - 1 & $0 >>> 32 - $4 | $1 << $4; + $0 = $0 << $4; } - $0 = $0 | $7; - i64toi32_i32$HIGH_BITS = $1 | $3; - return ($0 | 0) == ($4 | 0) & ($5 | 0) == (i64toi32_i32$HIGH_BITS | 0); + $0 = $0 | $6; + i64toi32_i32$HIGH_BITS = $2 | $7; + return $0; } return { diff -Nru binaryen-108/test/wasm2js/i64-shifts.2asm.js.opt binaryen-99/test/wasm2js/i64-shifts.2asm.js.opt --- binaryen-108/test/wasm2js/i64-shifts.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/i64-shifts.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -13,30 +13,48 @@ var abort = env.abort; var nan = NaN; var infinity = Infinity; - function legalstub$1($0, $1, $2, $3, $4, $5) { - $3 = $0; - $0 = $2 & 31; - if (($2 & 63) >>> 0 >= 32) { - $1 = $3 << $0; + function $1($0, $1_1, $2_1, $3, $4) { + $0 = $0 | 0; + $1_1 = $1_1 | 0; + $2_1 = $2_1 | 0; + $3 = $3 | 0; + $4 = $4 | 0; + var $5 = 0; + $5 = $2_1 & 31; + if (($2_1 & 63) >>> 0 >= 32) { + $1_1 = $0 << $5; $0 = 0; } else { - $1 = (1 << $0) - 1 & $3 >>> 32 - $0 | $1 << $0; - $0 = $3 << $0; + $1_1 = (1 << $5) - 1 & $0 >>> 32 - $5 | $1_1 << $5; + $0 = $0 << $5; } - return ($0 | 0) == ($4 | 0) & ($1 | 0) == ($5 | 0); + return ($0 | 0) == ($3 | 0) & ($1_1 | 0) == ($4 | 0); } - function legalstub$2($0, $1, $2, $3, $4, $5) { - $3 = $0; - $0 = $2 & 31; - if (($2 & 63) >>> 0 >= 32) { - $2 = $1 >> 31; - $0 = $1 >> $0; + function $2($0, $1_1, $2_1, $3, $4) { + $0 = $0 | 0; + $1_1 = $1_1 | 0; + $2_1 = $2_1 | 0; + $3 = $3 | 0; + $4 = $4 | 0; + var $5 = 0; + $5 = $2_1 & 31; + if (($2_1 & 63) >>> 0 >= 32) { + $2_1 = $1_1 >> 31; + $0 = $1_1 >> $5; } else { - $2 = $1 >> $0; - $0 = ((1 << $0) - 1 & $1) << 32 - $0 | $3 >>> $0; + $2_1 = $1_1 >> $5; + $0 = ((1 << $5) - 1 & $1_1) << 32 - $5 | $0 >>> $5; } - return ($0 | 0) == ($4 | 0) & ($2 | 0) == ($5 | 0); + return ($0 | 0) == ($3 | 0) & ($2_1 | 0) == ($4 | 0); + } + + function legalstub$1($0, $1_1, $2_1, $3, $4, $5) { + return $1($0, $1_1, $2_1, $4, $5); + } + + function legalstub$2($0, $1_1, $2_1, $3, $4, $5) { + return $2($0, $1_1, $2_1, $4, $5); } return { diff -Nru binaryen-108/test/wasm2js/reinterpret.2asm.js.opt binaryen-99/test/wasm2js/reinterpret.2asm.js.opt --- binaryen-108/test/wasm2js/reinterpret.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/reinterpret.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -21,6 +21,14 @@ f64ScratchView[0] = value; } + function wasm2js_scratch_store_f32(value) { + f32ScratchView[2] = value; + } + + function wasm2js_scratch_load_f32() { + return f32ScratchView[2]; + } + function asmFunc(env) { var Math_imul = Math.imul; var Math_fround = Math.fround; @@ -37,16 +45,22 @@ var infinity = Infinity; function $1($0) { $0 = $0 | 0; - return 1; + return ((wasm2js_scratch_store_f32((wasm2js_scratch_store_i32(2, $0), wasm2js_scratch_load_f32())), wasm2js_scratch_load_i32(2)) | 0) == ($0 | 0) | 0; } - function legalstub$2($0, $1_1) { - var $2 = 0; + function $2($0, $1_1) { + $0 = $0 | 0; + $1_1 = $1_1 | 0; + var $2_1 = 0; wasm2js_scratch_store_i32(0, $0 | 0); wasm2js_scratch_store_i32(1, $1_1 | 0); wasm2js_scratch_store_f64(+wasm2js_scratch_load_f64()); - $2 = wasm2js_scratch_load_i32(1) | 0; - return (wasm2js_scratch_load_i32(0) | 0) == ($0 | 0) & ($1_1 | 0) == ($2 | 0); + $2_1 = wasm2js_scratch_load_i32(1) | 0; + return (wasm2js_scratch_load_i32(0) | 0) == ($0 | 0) & ($1_1 | 0) == ($2_1 | 0); + } + + function legalstub$2($0, $1_1) { + return $2($0, $1_1); } return { diff -Nru binaryen-108/test/wasm2js/stack-modified.2asm.js.opt binaryen-99/test/wasm2js/stack-modified.2asm.js.opt --- binaryen-108/test/wasm2js/stack-modified.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/stack-modified.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -16,34 +16,47 @@ var infinity = Infinity; var setTempRet0 = env.setTempRet0; var i64toi32_i32$HIGH_BITS = 0; - function legalstub$0($0, $1) { - var $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0; - $4 = $1; - $2 = 1; + function $0($0_1, $1) { + $0_1 = $0_1 | 0; + $1 = $1 | 0; + var $2 = 0, $3 = 0, $4 = 0; + $2 = $1; + $3 = 1; while (1) { - if ($0 | $4) { - $1 = $2 >>> 16 | 0; - $3 = $0 >>> 16 | 0; - $9 = Math_imul($1, $3); - $5 = $2 & 65535; - $6 = $0 & 65535; - $7 = Math_imul($5, $6); - $3 = ($7 >>> 16 | 0) + Math_imul($3, $5) | 0; - $1 = ($3 & 65535) + Math_imul($1, $6) | 0; - i64toi32_i32$HIGH_BITS = (Math_imul($2, $4) + $9 | 0) + Math_imul($0, $8) + ($3 >>> 16) + ($1 >>> 16) | 0; - $2 = $7 & 65535 | $1 << 16; - $8 = i64toi32_i32$HIGH_BITS; - $1 = $0; - $0 = $1 - 1 | 0; - $4 = $4 - !$1 | 0; + if ($0_1 | $2) { + $3 = _ZN17compiler_builtins3int3mul3Mul3mul17h070e9a1c69faec5bE($0_1, $2, $3, $4); + $4 = i64toi32_i32$HIGH_BITS; + $1 = $0_1; + $0_1 = $0_1 - 1 | 0; + $2 = $2 - ($1 >>> 0 < 1) | 0; continue; } break; }; - i64toi32_i32$HIGH_BITS = $8; - $0 = $2; + i64toi32_i32$HIGH_BITS = $4; + return $3 | 0; + } + + function legalstub$0($0_1, $1) { + $0_1 = $0($0_1, $1); setTempRet0(i64toi32_i32$HIGH_BITS | 0); - return $0; + return $0_1; + } + + function _ZN17compiler_builtins3int3mul3Mul3mul17h070e9a1c69faec5bE($0_1, $1, $2, $3) { + var $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0; + $4 = $2 >>> 16 | 0; + $5 = $0_1 >>> 16 | 0; + $9 = Math_imul($4, $5); + $6 = $2 & 65535; + $7 = $0_1 & 65535; + $8 = Math_imul($6, $7); + $5 = ($8 >>> 16 | 0) + Math_imul($5, $6) | 0; + $4 = ($5 & 65535) + Math_imul($4, $7) | 0; + $0_1 = (Math_imul($1, $2) + $9 | 0) + Math_imul($0_1, $3) + ($5 >>> 16) + ($4 >>> 16) | 0; + $1 = $8 & 65535 | $4 << 16; + i64toi32_i32$HIGH_BITS = $0_1; + return $1; } return { diff -Nru binaryen-108/test/wasm2js/unaligned.2asm.js.opt binaryen-99/test/wasm2js/unaligned.2asm.js.opt --- binaryen-108/test/wasm2js/unaligned.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/unaligned.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -56,6 +56,11 @@ return HEAPU8[0] | HEAPU8[1] << 8 | (HEAPU8[2] << 16 | HEAPU8[3] << 24); } + function $1() { + i64toi32_i32$HIGH_BITS = HEAPU8[4] | HEAPU8[5] << 8 | (HEAPU8[6] << 16 | HEAPU8[7] << 24); + return HEAPU8[0] | HEAPU8[1] << 8 | (HEAPU8[2] << 16 | HEAPU8[3] << 24); + } + function $2() { return Math_fround((wasm2js_scratch_store_i32(2, HEAPU8[0] | HEAPU8[1] << 8 | (HEAPU8[2] << 16 | HEAPU8[3] << 24)), wasm2js_scratch_load_f32())); } @@ -87,14 +92,14 @@ } function $7() { - var $0_1 = 0, $1 = 0; + var $0_1 = 0, $1_1 = 0; wasm2js_scratch_store_f64(0.0); $0_1 = wasm2js_scratch_load_i32(1) | 0; - $1 = wasm2js_scratch_load_i32(0) | 0; - HEAP8[0] = $1; - HEAP8[1] = $1 >>> 8; - HEAP8[2] = $1 >>> 16; - HEAP8[3] = $1 >>> 24; + $1_1 = wasm2js_scratch_load_i32(0) | 0; + HEAP8[0] = $1_1; + HEAP8[1] = $1_1 >>> 8; + HEAP8[2] = $1_1 >>> 16; + HEAP8[3] = $1_1 >>> 24; HEAP8[4] = $0_1; HEAP8[5] = $0_1 >>> 8; HEAP8[6] = $0_1 >>> 16; @@ -103,8 +108,7 @@ function legalstub$1() { var $0_1 = 0; - i64toi32_i32$HIGH_BITS = HEAPU8[4] | HEAPU8[5] << 8 | (HEAPU8[6] << 16 | HEAPU8[7] << 24); - $0_1 = HEAPU8[0] | HEAPU8[1] << 8 | (HEAPU8[2] << 16 | HEAPU8[3] << 24); + $0_1 = $1(); setTempRet0(i64toi32_i32$HIGH_BITS | 0); return $0_1; } diff -Nru binaryen-108/test/wasm2js/unary-ops.2asm.js.opt binaryen-99/test/wasm2js/unary-ops.2asm.js.opt --- binaryen-108/test/wasm2js/unary-ops.2asm.js.opt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js/unary-ops.2asm.js.opt 2021-01-07 20:01:06.000000000 +0000 @@ -16,16 +16,7 @@ var i64toi32_i32$HIGH_BITS = 0; function $1($0) { $0 = $0 | 0; - var $1_1 = 0; - while (1) { - if ($0) { - $0 = $0 - 1 & $0; - $1_1 = $1_1 + 1 | 0; - continue; - } - break; - }; - return $1_1 | 0; + return __wasm_popcnt_i32($0) | 0; } function $6($0) { @@ -43,22 +34,19 @@ return $0 | 0; } + function $8($0, $1_1, $2, $3) { + $0 = $0 | 0; + $1_1 = $1_1 | 0; + $2 = $2 | 0; + $3 = $3 | 0; + var $4 = 0; + $4 = Math_clz32($0) + 32 | 0; + $0 = Math_clz32($1_1); + return !$3 & ($2 | 0) == ((($0 | 0) == 32 ? $4 : $0) | 0); + } + function legalstub$2($0, $1_1, $2, $3) { - var $4 = 0, $5 = 0, $6_1 = 0; - $4 = $0; - while (1) { - if ($1_1 | $4) { - $0 = $4; - $4 = $4 - 1 & $4; - $1_1 = $1_1 - !$0 & $1_1; - $5 = $5 + 1 | 0; - $6_1 = $5 ? $6_1 : $6_1 + 1 | 0; - continue; - } - break; - }; - i64toi32_i32$HIGH_BITS = $6_1; - return ($2 | 0) == ($5 | 0) & ($3 | 0) == (i64toi32_i32$HIGH_BITS | 0); + return (__wasm_popcnt_i64($0, $1_1) | 0) == ($2 | 0) & ($3 | 0) == (i64toi32_i32$HIGH_BITS | 0); } function legalstub$3($0, $1_1, $2) { @@ -74,31 +62,62 @@ } function legalstub$8($0, $1_1, $2, $3) { - var $4 = 0; - $4 = Math_clz32($0) + 32 | 0; - $0 = Math_clz32($1_1); - return !$3 & ($2 | 0) == ((($0 | 0) == 32 ? $4 : $0) | 0); + return $8($0, $1_1, $2, $3); } function legalstub$9($0, $1_1, $2, $3) { - var $4 = 0, $5 = 0, $6_1 = 0, $7_1 = 0; - __inlined_func$__wasm_ctz_i64 : { - if ($1_1 | $0) { - $4 = $1_1 - 1 | 0; - $5 = $4 + 1 | 0; - $6_1 = $4; - $4 = $0 - 1 | 0; - $7_1 = Math_clz32($0 ^ $4) + 32 | 0; - $0 = Math_clz32($1_1 ^ (($4 | 0) != -1 ? $5 : $6_1)); - $0 = ($0 | 0) == 32 ? $7_1 : $0; - $1_1 = 63 - $0 | 0; - i64toi32_i32$HIGH_BITS = 0 - ($0 >>> 0 > 63) | 0; - break __inlined_func$__wasm_ctz_i64; - } - i64toi32_i32$HIGH_BITS = 0; - $1_1 = 64; + return (__wasm_ctz_i64($0, $1_1) | 0) == ($2 | 0) & ($3 | 0) == (i64toi32_i32$HIGH_BITS | 0); + } + + function __wasm_ctz_i64($0, $1_1) { + var $2 = 0, $3 = 0; + if ($0 | $1_1) { + $2 = $1_1 - 1 | 0; + $3 = $0 - 1 | 0; + $2 = ($3 | 0) != -1 ? $2 + 1 | 0 : $2; + $3 = Math_clz32($0 ^ $3) + 32 | 0; + $0 = Math_clz32($1_1 ^ $2); + $0 = ($0 | 0) == 32 ? $3 : $0; + $1_1 = 63 - $0 | 0; + i64toi32_i32$HIGH_BITS = 0 - ($0 >>> 0 > 63) | 0; + return $1_1; } - return ($1_1 | 0) == ($2 | 0) & ($3 | 0) == (i64toi32_i32$HIGH_BITS | 0); + i64toi32_i32$HIGH_BITS = 0; + return 64; + } + + function __wasm_popcnt_i32($0) { + var $1_1 = 0, $2 = 0; + while (1) { + $2 = $1_1; + if ($0) { + $0 = $0 - 1 & $0; + $1_1 = $1_1 + 1 | 0; + continue; + } + break; + }; + return $2; + } + + function __wasm_popcnt_i64($0, $1_1) { + var $2 = 0, $3 = 0, $4 = 0, $5 = 0; + while (1) { + $5 = $4; + $2 = $3; + if ($0 | $1_1) { + $2 = $0; + $0 = $2 - 1 & $2; + $1_1 = $1_1 - ($2 >>> 0 < 1) & $1_1; + $2 = $4 + 1 | 0; + $3 = $2 >>> 0 < 1 ? $3 + 1 | 0 : $3; + $4 = $2; + continue; + } + break; + }; + i64toi32_i32$HIGH_BITS = $2; + return $5; } return { diff -Nru binaryen-108/test/wasm2js.asserts.js binaryen-99/test/wasm2js.asserts.js --- binaryen-108/test/wasm2js.asserts.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js.asserts.js 2021-01-07 20:01:06.000000000 +0000 @@ -74,9 +74,9 @@ return 1 | 0; } -if (!check1()) throw 'assertion failed: ( assert_return ( invoke empty ) )'; +if (!check1()) throw 'assertion failed: ( assert_return ( call empty ) )'; function check2() { return (retasmFunc0.add(1 | 0, 1 | 0) | 0 | 0) == (2 | 0) | 0; } -if (!check2()) throw 'assertion failed: ( assert_return ( invoke add ( i32.const 1 ) ( i32.const 1 ) ) ( i32.const 2 ) )'; +if (!check2()) throw 'assertion failed: ( assert_return ( call add ( i32.const 1 ) ( i32.const 1 ) ) ( i32.const 2 ) )'; diff -Nru binaryen-108/test/wasm2js.traps.js binaryen-99/test/wasm2js.traps.js --- binaryen-108/test/wasm2js.traps.js 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/test/wasm2js.traps.js 2021-01-07 20:01:06.000000000 +0000 @@ -74,15 +74,15 @@ return 1 | 0; } -if (!check1()) throw 'assertion failed: ( assert_return ( invoke empty ) )'; +if (!check1()) throw 'assertion failed: ( assert_return ( call empty ) )'; function check2() { return (retasmFunc0.add(1 | 0, 1 | 0) | 0 | 0) == (2 | 0) | 0; } -if (!check2()) throw 'assertion failed: ( assert_return ( invoke add ( i32.const 1 ) ( i32.const 1 ) ) ( i32.const 2 ) )'; +if (!check2()) throw 'assertion failed: ( assert_return ( call add ( i32.const 1 ) ( i32.const 1 ) ) ( i32.const 2 ) )'; function check3() { function f() { - return retasmFunc0.div_s(0 | 0, 0 | 0) | 0 | 0; + retasmFunc0.div_s(0 | 0, 0 | 0); } try { @@ -93,10 +93,10 @@ return 0; } -if (!check3()) throw 'assertion failed: ( assert_trap ( invoke div_s ( i32.const 0 ) ( i32.const 0 ) ) integer divide by zero )'; +if (!check3()) throw 'assertion failed: ( assert_trap ( call div_s ( i32.const 0 ) ( i32.const 0 ) ) integer divide by zero )'; function check4() { function f() { - return retasmFunc0.div_s(-2147483648 | 0, -1 | 0) | 0 | 0; + retasmFunc0.div_s(-2147483648 | 0, -1 | 0); } try { @@ -107,4 +107,4 @@ return 0; } -if (!check4()) throw 'assertion failed: ( assert_trap ( invoke div_s ( i32.const 0x80000000 ) ( i32.const -1 ) ) integer overflow )'; +if (!check4()) throw 'assertion failed: ( assert_trap ( call div_s ( i32.const 0x80000000 ) ( i32.const -1 ) ) integer overflow )'; diff -Nru binaryen-108/third_party/CMakeLists.txt binaryen-99/third_party/CMakeLists.txt --- binaryen-108/third_party/CMakeLists.txt 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/CMakeLists.txt 2021-01-07 20:01:06.000000000 +0000 @@ -1,13 +1,3 @@ if(BUILD_LLVM_DWARF) add_subdirectory(llvm-project) endif() - -include_directories( - googletest/googletest - googletest/googletest/include -) - -if(BUILD_TESTS) - add_library(gtest STATIC googletest/googletest/src/gtest-all.cc) - add_library(gtest_main STATIC googletest/googletest/src/gtest_main.cc) -endif() diff -Nru binaryen-108/third_party/llvm-project/dwarf2yaml.cpp binaryen-99/third_party/llvm-project/dwarf2yaml.cpp --- binaryen-108/third_party/llvm-project/dwarf2yaml.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/llvm-project/dwarf2yaml.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -116,10 +116,7 @@ } void dumpDebugLoc(DWARFContext &DCtx, DWARFYAML::Data &Y) { // XXX BINARYEN - // This blindly grabs the first CU, which should be ok since they all have - // the same address size? - auto CU = DCtx.normal_units().begin()->get(); - uint8_t savedAddressByteSize = CU->getFormParams().AddrSize; // XXX BINARYEN + uint8_t savedAddressByteSize = 4; DWARFDataExtractor locsData(DCtx.getDWARFObj(), DCtx.getDWARFObj().getLocSection(), DCtx.isLittleEndian(), savedAddressByteSize); uint64_t offset = 0; @@ -129,7 +126,7 @@ auto list = locList.parseOneLocationList(locsData, &offset); if (!list) { errs() << "debug_loc error\n"; - exit(1); + break; } for (auto& entry : list.get().Entries) { DWARFYAML::Loc loc; @@ -325,8 +322,6 @@ DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data, DCtx.isLittleEndian(), CU->getAddressByteSize()); uint64_t Offset = *StmtOffset; - DebugLines.Position = Offset; - dumpInitialLength(LineData, Offset, DebugLines.Length); uint64_t LineTableLength = DebugLines.Length.getLength(); uint64_t SizeOfPrologueLength = DebugLines.Length.isDWARF64() ? 8 : 4; @@ -431,10 +426,9 @@ dumpDebugStrings(DCtx, Y); dumpDebugARanges(DCtx, Y); dumpDebugRanges(DCtx, Y); // XXX BINARYEN + dumpDebugLoc(DCtx, Y); // XXX BINARYEN dumpDebugPubSections(DCtx, Y); dumpDebugInfo(DCtx, Y); - // dumpDebugLoc relies on the address size being known from dumpDebugInfo. - dumpDebugLoc(DCtx, Y); // XXX BINARYEN dumpDebugLines(DCtx, Y); return obj2yaml_error::success; } diff -Nru binaryen-108/third_party/llvm-project/DWARFEmitter.cpp binaryen-99/third_party/llvm-project/DWARFEmitter.cpp --- binaryen-108/third_party/llvm-project/DWARFEmitter.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/llvm-project/DWARFEmitter.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -133,10 +133,8 @@ // XXX BINARYEN void DWARFYAML::EmitDebugLoc(raw_ostream &OS, const DWARFYAML::Data &DI) { for (auto Loc : DI.Locs) { - auto AddrSize = DI.CompileUnits[0].AddrSize; // XXX BINARYEN - // FIXME: Loc.Start etc should probably not be 32-bit. - writeVariableSizedInteger((uint64_t)(int32_t)Loc.Start, AddrSize, OS, DI.IsLittleEndian); - writeVariableSizedInteger((uint64_t)(int32_t)Loc.End, AddrSize, OS, DI.IsLittleEndian); + writeInteger((uint32_t)Loc.Start, OS, DI.IsLittleEndian); + writeInteger((uint32_t)Loc.End, OS, DI.IsLittleEndian); if (Loc.Start == 0 && Loc.End == 0) { // End of a list. continue; diff -Nru binaryen-108/third_party/llvm-project/DWARFVisitor.cpp binaryen-99/third_party/llvm-project/DWARFVisitor.cpp --- binaryen-108/third_party/llvm-project/DWARFVisitor.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/llvm-project/DWARFVisitor.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -135,7 +135,7 @@ case dwarf::DW_FORM_block: onValue((uint64_t)FormVal->BlockData.size(), true); onValue( - MemoryBufferRef(StringRef((const char *)FormVal->BlockData.data(), + MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0], FormVal->BlockData.size()), "")); break; @@ -143,7 +143,7 @@ auto writeSize = FormVal->BlockData.size(); onValue((uint8_t)writeSize); onValue( - MemoryBufferRef(StringRef((const char *)FormVal->BlockData.data(), + MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0], FormVal->BlockData.size()), "")); break; @@ -152,7 +152,7 @@ auto writeSize = FormVal->BlockData.size(); onValue((uint16_t)writeSize); onValue( - MemoryBufferRef(StringRef((const char *)FormVal->BlockData.data(), + MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0], FormVal->BlockData.size()), "")); break; @@ -161,7 +161,7 @@ auto writeSize = FormVal->BlockData.size(); onValue((uint32_t)writeSize); onValue( - MemoryBufferRef(StringRef((const char *)FormVal->BlockData.data(), + MemoryBufferRef(StringRef((const char *)&FormVal->BlockData[0], FormVal->BlockData.size()), "")); break; diff -Nru binaryen-108/third_party/llvm-project/include/llvm/BinaryFormat/Wasm.h binaryen-99/third_party/llvm-project/include/llvm/BinaryFormat/Wasm.h --- binaryen-108/third_party/llvm-project/include/llvm/BinaryFormat/Wasm.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/llvm-project/include/llvm/BinaryFormat/Wasm.h 2021-01-07 20:01:06.000000000 +0000 @@ -225,6 +225,7 @@ WASM_TYPE_F64 = 0x7C, WASM_TYPE_V128 = 0x7B, WASM_TYPE_FUNCREF = 0x70, + WASM_TYPE_EXNREF = 0x68, WASM_TYPE_FUNC = 0x60, WASM_TYPE_NORESULT = 0x40, // for blocks with no result values }; @@ -347,6 +348,7 @@ F32 = WASM_TYPE_F32, F64 = WASM_TYPE_F64, V128 = WASM_TYPE_V128, + EXNREF = WASM_TYPE_EXNREF, }; struct WasmSignature { diff -Nru binaryen-108/third_party/llvm-project/include/llvm/ObjectYAML/DWARFYAML.h binaryen-99/third_party/llvm-project/include/llvm/ObjectYAML/DWARFYAML.h --- binaryen-108/third_party/llvm-project/include/llvm/ObjectYAML/DWARFYAML.h 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/llvm-project/include/llvm/ObjectYAML/DWARFYAML.h 2021-01-07 20:01:06.000000000 +0000 @@ -151,7 +151,6 @@ }; struct LineTable { - uint64_t Position; // XXX BINARYEN: the binary location in .debug_line InitialLength Length; uint16_t Version; uint64_t PrologueLength; diff -Nru binaryen-108/third_party/llvm-project/Twine.cpp binaryen-99/third_party/llvm-project/Twine.cpp --- binaryen-108/third_party/llvm-project/Twine.cpp 2022-05-12 03:18:49.000000000 +0000 +++ binaryen-99/third_party/llvm-project/Twine.cpp 2021-01-07 20:01:06.000000000 +0000 @@ -173,6 +173,7 @@ OS << ")"; } +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void Twine::dump() const { print(dbgs()); } @@ -180,3 +181,4 @@ LLVM_DUMP_METHOD void Twine::dumpRepr() const { printRepr(dbgs()); } +#endif